1C image processing using .Net framework when uploading to a website
In the proposed version, through the .Net framework, processing is performed in memory without creating intermediate files. During processing, all System.Drawing classes are available, which adds flexibility to the method, because if desired, you can achieve any effects using regular methods. It uses .Net framework 4.0 and a means of interfacing with 1C .Net bridge 4.
Initialization
The initialization code creates an object inside 1C that is responsible for working with the .Net Framework and loads the build of System.Drawing 4th version:
ПодключитьВнешнююКомпоненту("Elisy.NetBridge4");
AddIn = New("AddIn.ElisyNetBridge4");
net = AddIn.GetNet();
net.LoadAssembly("System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
Convert between formats
Inside the .Net Framework, work with images is done through an object of the Bitmap class, and inside 1C, the Picture type is responsible for images. It is necessary to organize the conversion of the type Image into a Bitmap object.
On the 1C side, the BinaryData () method is called for the Picture type. For the configuration of Trade Management 10.3, the code may be as follows:
Функция ПолучитьКартинку(Номенклатура) Экспорт
Если ЗначениеЗаполнено(Номенклатура.ОсновноеИзображение) Тогда
Возврат Номенклатура.ОсновноеИзображение.Хранилище.Получить().ПолучитьДвоичныеДанные();
Иначе
Картинка = Новый Картинка();
Возврат Картинка.ПолучитьДвоичныеДанные();
КонецЕсли;
КонецФункции
Function GetPicture will return 1C-type BinaryData. It can be converted to a .Net type with the following code:
bytes = net.CallStatic("System.Convert", "FromBase64String", Base64String(картинка));
bitmap = net.New("System.Drawing.Bitmap", net.New("System.IO.MemoryStream", bytes));
Resize Image
If the dimensions of the final image width, height are known and there is the original Bitmap image, then in 1C the code for resizing will be approximately as follows:
outputBitmap = net.New("System.Drawing.Bitmap", width, height);
g = net.CallStatic("System.Drawing.Graphics", "FromImage", outputBitmap);
g.CompositingQuality = net.New("System.Drawing.Drawing2D.CompositingQuality").HighQuality;
g.SmoothingMode = net.New("System.Drawing.Drawing2D.SmoothingMode").HighQuality;
g.InterpolationMode = net.New("System.Drawing.Drawing2D.InterpolationMode").HighQualityBicubic;
g.Clear(net.GetStatic("System.Drawing.Color", "WhiteSmoke"));
sx = width / Bitmap.Width;
sy = height / Bitmap.Height;
scale = Мин(sx, sy);
g.DrawImage(bitmap, Окр((outputBitmap.Width - scale * bitmap.Width) / 2, 0), Окр((outputBitmap.Height - scale * bitmap.Height) / 2, 0), Окр(scale * bitmap.Width, 0), Окр(scale * bitmap.Height, 0));
Если width >= 100 ИЛИ height >= 100 Тогда
ДобавитьВодянойЗнак(net, g, watermark, width, height);
КонецЕсли;
The code creates an object of type Graphics Graphics, which allows you to perform operations with graphics, based on the final empty image outputBitmap with dimensions of width and height. Calling g.Clear will fill the background of the picture with a specific color (in this case, WhiteSmoke). Filling with color is necessary if the original image does not completely fill the specified dimensions. Based on the proportion of the width and height parameters and the width and height of the original image, the original image is superimposed on the resulting image.
To make the best use of the resource-intensive object g, the Add Watermark procedure is called here, where the text string watermark is passed as a parameter. It is advisable to call explicitly at the end of processing:
g.Dispose(); It is better to explicitly call the Dispose method for all IDisposable objects that are no longer needed: Bitmap, outputBitmap, objects of type MemoryStream.
Watermark overlay
The watermark is superimposed by System.Drawing. The two methods that will be discussed are based on the g method. MeasureString, which allows you to return the size of the graphical representation of the string that you plan to put on the image.
Method 1
The first method puts a watermark at the bottom of the image. Font sizes are searched, starting from 72 and below, until the specified watermark string enters the image borders. The line will be displayed two times: a translucent black brush and a translucent white brush with a slight offset.

sizes = net.New("System.Collections.Generic.List", net.T("System.Int32"));
sizes.Add(72);
sizes.Add(36);
sizes.Add(24);
sizes.Add(16);
sizes.Add(14);
sizes.Add(12);
sizes.Add(10);
sizes.Add(8);
sizes.Add(6);
sizes.Add(4);
crFont = null;
crSize = net.New("System.Drawing.SizeF");
Для i = 0 по 8 цикл
crFont = net.New("System.Drawing.Font", "arial", sizes.get_Item(i), net.New("System.Drawing.FontStyle").Bold);
crSize = g.MeasureString(Watermark, crFont);
Если crSize.Width < width тогда
Прервать;
КонецЕсли;
КонецЦикла;
yPixlesFromBottom = Окр(height * 0.05, 0);
yPosFromBottom = ((height -
yPixlesFromBottom) - (crSize.Height / 2));
xCenterOfImg = width / 2;
StrFormat = net.New("System.Drawing.StringFormat");
StrFormat.Alignment = net.New("System.Drawing.StringAlignment").Center;
semiTransBrush2 = net.New("System.Drawing.SolidBrush", net.CallStatic("System.Drawing.Color", "FromArgb", 153, 0, 0, 0));
g.DrawString(watermark,
crFont,
semiTransBrush2,
net.New("System.Drawing.PointF", Окр(xCenterOfImg + 1, 0), Окр(yPosFromBottom + 1, 0)),
StrFormat);
semiTransBrush = net.New("System.Drawing.SolidBrush", net.CallStatic("System.Drawing.Color", "FromArgb", 153, 255, 255, 255));
g.DrawString(watermark,
crFont,
semiTransBrush,
net.New("System.Drawing.PointF", Окр(xCenterOfImg, 0), Окр(yPosFromBottom, 0)),
StrFormat);
Method 2
The second method will display the watermark diagonally on the original image. From the hundredth font size down, an attempt is made to fit a string into an image. If the attempt is successful, then a line with a slightly visible white brush is drawn with the found font with the found angle.
font = net.New("System.Drawing.Font", "Tahoma", 40);
color = net.CallStatic("System.Drawing.Color", "FromArgb", 25, 255, 255, 255);
tangent = height / width;
angle = ATan(tangent) * (180 / 3.1415);
halfHypotenuse = Sqrt((Height * Height) + (Width * Width)) / 2;
Для i2 = 0 по 99 цикл
i = 100 - i2;
font = net.New("System.Drawing.Font", "Tahoma", i, net.New("System.Drawing.FontStyle").Bold);
sizef = g.MeasureString(watermark, font, net.GetStatic("System.Int32", "MaxValue"));
sin = Sin(angle * (3.1415 / 180));
cos = Cos(angle * (3.1415 / 180));
opp1 = sin * sizef.Width;
adj1 = cos * sizef.Height;
opp2 = sin * sizef.Height;
adj2 = cos * sizef.Width;
Если opp1 + adj1 < height И opp2 + adj2 < width тогда
Прервать;
КонецЕсли;
КонецЦикла;
stringFormat = net.New("System.Drawing.StringFormat");
stringFormat.Alignment = net.New("System.Drawing.StringAlignment").Center;
stringFormat.LineAlignment = net.New("System.Drawing.StringAlignment").Center;
g.SmoothingMode = net.New("System.Drawing.Drawing2D.SmoothingMode").AntiAlias;
g.RotateTransform(Окр(angle, 0));
g.DrawString(watermark,
font,
net.New("System.Drawing.SolidBrush", color),
net.New("System.Drawing.PointF", Окр(halfHypotenuse, 0), 0),
stringFormat);
Example image for the 2nd method:
