📜 ⬆️ ⬇️

1C image processing using the .Net framework when uploading to a website

1C: The company does not provide regular means of working with images for resizing and imposing watermarks. This functionality is often in demand, for example, in online stores, when goods with photos are exported from 1C. Previously, this was done by uploading photos to disk and calling utilities via the command line. It is clear that this option does not have the flexibility and speed, plus there may still be security problems and allowing for temporary files on the disk.


In the proposed version, the .Net framework is processed in memory without creating intermediate files. When processing, all System.Drawing classes are available, which adds flexibility to the method, because if you wish, you can achieve any effects using standard methods. It uses the .Net framework 4.0 and the means of interfacing it with 1C .Net bridge 4.

Initialization


The initialization code creates an object within 1C responsible for working with the .Net Framework and loads the System.Drawing 4th version assembly:
')
("Elisy.NetBridge4"); AddIn = New("AddIn.ElisyNetBridge4"); net = AddIn.GetNet(); net.LoadAssembly("System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); 


Conversion between formats



Inside the .Net Framework, work with images is carried out through an object of the Bitmap class, and inside 1C, the image type is responsible for images. It is necessary to organize the conversion of the type Picture into a Bitmap object.

On the 1C side, the BinaryData () method is called for the Picture type. To configure Trade Management 10.3, the code can be as follows:

  ()   (.)   ...().();   =  ();  .(); ;  


The GetPicture function will return the 1C-type BinaryData. It can be converted to .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)); 


Image resizing



If the sizes of the final image width, height are known and there is the original Bitmap image, then in 1C the resizing code 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 a g object of type Graphics, allowing you to perform graphics operations based on the final blank image outputBitmap with dimensions of width and height. The g.Clear call will fill the background of the pattern with a certain color (in this case, WhiteSmoke). Filling with color is necessary if the original image does not completely fill the specified dimensions. Based on the proportions of the width and height parameters and the width and height of the original image, the original image is superimposed on the resulting image.

In order to use the resource-intensive object g as optimally as possible, the procedure Add Watermark 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 which need have disappeared: Bitmap, outputBitmap, objects of the type MemoryStream.

Watermark overlay



The watermark is overlaid with 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 graphic representation of the string that you plan to put on the image.

Method 1



The first method applies a watermark at the bottom of the image. Font sizes are moved, starting from 72 and below, until the specified watermark string enters the borders of the image. The line will be displayed twice: with a translucent black brush and a translucent white brush with a slight offset.

Sample watermark obtained by method 1

 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 a watermark on the diagonal of the original image. From the hundredth font size down, an attempt is made to fit a line into an image. If the attempt is successful, a line with a slightly visible white brush is drawn with the found font with the found corner.

 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); 


Sample image for mode 2:
Sample watermark obtained by method 2

Source: https://habr.com/ru/post/176717/


All Articles