Picture Processing of.net core and Generation and Resolution of Two-Dimensional Code

It has been more than ten years since I wrote the code.

 

From html to css to javascript to vbscript to c#, from interest to occupation, life is always lost and surprising.

 

Most of the time, I don't start because I know where to go, I just know I can't stay anymore, that's all.After being hit by the wind and rain, there will be a lot of unique feelings and thinking, ideas start to develop and firm in the swing, think this is growth, well...Even if it's growing up, oh!

 

Say Microsoft's.net core 3.0 will be released soon, as a yard farmer, you still need to care about it.Starting with.net core 2.0 and MySql officially supporting.Net core, I tried to convert my own class library into a.net standard class library, began to understand the maturity of.Net core, wrote a few demo s, and then quit because I still worked on web(asp.net core), but.Net coreProcessing pictures is blank, System.Drawing is just a setup (and it's likely to be the same later), even though ImageSharp, which many people praise, was abandoned after a few attempts due to large interface changes and lack of documentation. I think there should not be a mature Library of picture processing classes under.Net core, and it's not enough to migrate projects.If Microsoft officially wants to build an independent image processing application for image processing, asp.net core is only used as a simple data interface, which is worth weighing. After all, small and medium-sized projects are worth it to build a dedicated image processing application. Do you know if Microsoft products and engineers have thought about it?Or are so-called enterprise apps their goal?

 

I assume that System.Drawing will end up in.net core as IE browser and Edge browser did after Win10, so maybe it's time to give up.Find an alternative, so I finally decided to use SkiaSharp for picture processing, and handled the QR code by the way. After all, it's also a picture, and QR code is available for scenes in the sky. I used to use ThoughtWorks.QRCode consistently in the.net framework before.Although ThoughtWorks.QRCode does not seem to support working in.net core at present, the generation and analysis of 2D codes is finally handled by ZXing.Net.

 

The two-dimensional code generated by ZXing.Net has a percentage of white edges by default, which is probably an industry standard, but sometimes white edges may not be needed in real-world applications, so I do some logic with white edges, which specify the width pixel values to be retained or preserve the original default white edges.

 

By referencing SkiaSharp(1.68.0) and ZXing.Net(0.16.4), a static class was written to scale and crop pictures and generate and parse QR codes as follows:

  1 public static class ImageHelper
  2     {
  3         static readonly long maxLength = 10485760;//10*1024*1024
  4         public static SkiaSharp.SKEncodedImageFormat GetImageFormatBySuffix(string suffix)
  5         {
  6             var format = SkiaSharp.SKEncodedImageFormat.Jpeg;
  7             if (string.IsNullOrEmpty(suffix))
  8             {
  9                 return format;
 10             }
 11             if (suffix[0] == '.')
 12             {
 13                 suffix = suffix.Substring(1);
 14             }
 15             if (string.IsNullOrEmpty(suffix))
 16             {
 17                 return format;
 18             }
 19             suffix = suffix.ToUpper();
 20             switch (suffix)
 21             {
 22                 case "PNG":
 23                     format = SkiaSharp.SKEncodedImageFormat.Png;
 24                     break;
 25                 case "GIF":
 26                     format = SkiaSharp.SKEncodedImageFormat.Gif;
 27                     break;
 28                 case "BMP":
 29                     format = SkiaSharp.SKEncodedImageFormat.Bmp;
 30                     break;
 31                 case "ICON":
 32                     format = SkiaSharp.SKEncodedImageFormat.Ico;
 33                     break;
 34                 case "ICO":
 35                     format = SkiaSharp.SKEncodedImageFormat.Ico;
 36                     break;
 37                 case "DNG":
 38                     format = SkiaSharp.SKEncodedImageFormat.Dng;
 39                     break;
 40                 case "WBMP":
 41                     format = SkiaSharp.SKEncodedImageFormat.Wbmp;
 42                     break;
 43                 case "WEBP":
 44                     format = SkiaSharp.SKEncodedImageFormat.Webp;
 45                     break;
 46                 case "PKM":
 47                     format = SkiaSharp.SKEncodedImageFormat.Pkm;
 48                     break;
 49                 case "KTX":
 50                     format = SkiaSharp.SKEncodedImageFormat.Ktx;
 51                     break;
 52                 case "ASTC":
 53                     format = SkiaSharp.SKEncodedImageFormat.Astc;
 54                     break;
 55             }
 56             return format;
 57         }
 58         public static SkiaSharp.SKEncodedImageFormat GetImageFormatByPath(string path)
 59         {
 60             var suffix = "";
 61             if (System.IO.Path.HasExtension(path))
 62             {
 63                 suffix = System.IO.Path.GetExtension(path);
 64             }
 65             return GetImageFormatBySuffix(suffix);
 66         }
 67         public static Tuple<int, int, long, SkiaSharp.SKEncodedImageFormat> GetImageInfo(string path)
 68         {
 69             if (string.IsNullOrEmpty(path))
 70             {
 71                 throw new Exception("Path cannot be empty");
 72             }
 73             if (!System.IO.File.Exists(path))
 74             {
 75                 throw new Exception("file does not exist");
 76             }
 77             var fileStream = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); //fileInfo.OpenRead();
 78             var fileLength = fileStream.Length;
 79             if (fileLength > maxLength)
 80             {
 81                 fileStream.Dispose();
 82                 throw new Exception("File too large");
 83             }
 84             var sKManagedStream = new SkiaSharp.SKManagedStream(fileStream, true);
 85             var sKBitmap = SkiaSharp.SKBitmap.Decode(sKManagedStream);
 86             sKManagedStream.Dispose();
 87 
 88             if (sKBitmap.IsEmpty)
 89             {
 90                 sKBitmap.Dispose();
 91                 throw new Exception("Invalid file");
 92             }
 93             int w = sKBitmap.Width;
 94             int h = sKBitmap.Height;
 95             return new Tuple<int, int, long, SkiaSharp.SKEncodedImageFormat>(w, h, fileLength, GetImageFormatByPath(path));
 96         }
 97         public static void ImageMaxCutByCenter(string path, string savePath, int saveWidth, int saveHeight, int quality)
 98         {
 99             var bytes = ImageMaxCutByCenter(path, saveWidth, saveHeight, quality);
100             if (bytes == null || bytes.Length < 1)
101             {
102                 return;
103             }
104             string saveDirPath = System.IO.Path.GetDirectoryName(savePath);
105             if (!System.IO.Directory.Exists(saveDirPath))
106             {
107                 System.IO.Directory.CreateDirectory(saveDirPath);
108             }
109             System.IO.FileStream fs = new System.IO.FileStream(savePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None);
110             fs.Write(bytes, 0, bytes.Length);
111             fs.Close();
112         }
113         public static byte[] ImageMaxCutByCenter(string path, int saveWidth, int saveHeight, int quality)
114         {
115             byte[] bytes = null;
116             if (!System.IO.File.Exists(path))
117             {
118                 return bytes;
119             }
120             var fileStream = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); //fileInfo.OpenRead();
121             if (fileStream.Length > maxLength)
122             {
123                 fileStream.Dispose();
124                 return bytes;
125             }
126             var sKManagedStream = new SkiaSharp.SKManagedStream(fileStream, true);
127             var sKBitmap = SkiaSharp.SKBitmap.Decode(sKManagedStream);
128             sKManagedStream.Dispose();
129 
130             if (sKBitmap.IsEmpty)
131             {
132                 return bytes;
133             }
134 
135             if (saveWidth < 1) { saveWidth = 1; }
136             if (saveHeight < 1) { saveHeight = 1; }
137             if (quality < 1) { quality = 1; }
138             if (quality > 100) { quality = 100; }
139 
140             int oW = sKBitmap.Width;
141             int oH = sKBitmap.Height;
142             int cutW = saveWidth;
143             int cutH = saveHeight;
144             double ratio = 1;
145             if (cutW > oW)
146             {
147                 ratio = (double)oW / (double)cutW;
148                 cutH = Convert.ToInt32((double)cutH * ratio);
149                 cutW = oW;
150                 if (cutH > oH)
151                 {
152                     ratio = (double)oH / (double)cutH;
153                     cutW = Convert.ToInt32((double)cutW * ratio);
154                     cutH = oH;
155                 }
156             }
157             else if (cutW < oW)
158             {
159                 ratio = (double)oW / (double)cutW;
160                 cutH = Convert.ToInt32(Convert.ToDouble(cutH) * ratio);
161                 cutW = oW;
162                 if (cutH > oH)
163                 {
164                     ratio = (double)oH / (double)cutH;
165                     cutW = Convert.ToInt32((double)cutW * ratio);
166                     cutH = oH;
167                 }
168             }
169             else
170             {
171                 if (cutH > oH)
172                 {
173                     ratio = (double)oH / (double)cutH;
174                     cutW = Convert.ToInt32((double)cutW * ratio);
175                     cutH = oH;
176                 }
177             }
178             int startX = oW > cutW ? (oW / 2 - cutW / 2) : (cutW / 2 - oW / 2);
179             int startY = oH > cutH ? (oH / 2 - cutH / 2) : (cutH / 2 - oH / 2);
180 
181             var sKBitmap2 = new SkiaSharp.SKBitmap(saveWidth, saveHeight);
182             var sKCanvas = new SkiaSharp.SKCanvas(sKBitmap2);
183             var sKPaint = new SkiaSharp.SKPaint
184             {
185                 FilterQuality = SkiaSharp.SKFilterQuality.Medium,
186                 IsAntialias = true
187             };
188             sKCanvas.DrawBitmap(
189                 sKBitmap,
190                 new SkiaSharp.SKRect
191                 {
192                     Location = new SkiaSharp.SKPoint { X = startX, Y = startY },
193                     Size = new SkiaSharp.SKSize { Height = cutH, Width = cutW }
194                 },
195                 new SkiaSharp.SKRect
196                 {
197                     Location = new SkiaSharp.SKPoint { X = 0, Y = 0 },
198                     Size = new SkiaSharp.SKSize { Height = saveHeight, Width = saveWidth }
199                 }, sKPaint);
200             sKCanvas.Dispose();
201             var sKImage2 = SkiaSharp.SKImage.FromBitmap(sKBitmap2);
202             sKBitmap2.Dispose();
203             var data = sKImage2.Encode(GetImageFormatByPath(path), quality);
204             sKImage2.Dispose();
205             bytes = data.ToArray();
206             data.Dispose();
207 
208             return bytes;
209         }
210         public static void ImageScalingToRange(string path, string savePath, int maxWidth, int maxHeight, int quality)
211         {
212             var bytes = ImageScalingToRange(path, maxWidth, maxHeight, quality);
213             if (bytes == null || bytes.Length < 1)
214             {
215                 return;
216             }
217             string saveDirPath = System.IO.Path.GetDirectoryName(savePath);
218             if (!System.IO.Directory.Exists(saveDirPath))
219             {
220                 System.IO.Directory.CreateDirectory(saveDirPath);
221             }
222             System.IO.FileStream fs = new System.IO.FileStream(savePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None);
223             fs.Write(bytes, 0, bytes.Length);
224             fs.Close();
225         }
226         public static byte[] ImageScalingToRange(string path, int maxWidth, int maxHeight, int quality)
227         {
228             byte[] bytes = null;
229             if (!System.IO.File.Exists(path))
230             {
231                 return bytes;
232             }
233             var fileStream = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); //fileInfo.OpenRead();
234             if (fileStream.Length > maxLength)
235             {
236                 fileStream.Dispose();
237                 return bytes;
238             }
239             var sKManagedStream = new SkiaSharp.SKManagedStream(fileStream, true);
240             var sKBitmap = SkiaSharp.SKBitmap.Decode(sKManagedStream);
241             sKManagedStream.Dispose();
242 
243             if (sKBitmap.IsEmpty)
244             {
245                 return bytes;
246             }
247 
248             if (maxWidth < 1) { maxWidth = 1; }
249             if (maxHeight < 1) { maxHeight = 1; }
250             if (quality < 1) { quality = 1; }
251             if (quality > 100) { quality = 100; }
252 
253             int oW = sKBitmap.Width;
254             int oH = sKBitmap.Height;
255             int nW = oW;
256             int nH = oH;
257 
258             if (nW < maxWidth && nH < maxHeight)//enlarge
259             {
260                 if (nW < maxWidth)
261                 {
262                     var r = (double)maxWidth / (double)nW;
263                     nW = maxWidth;
264                     nH = (int)Math.Floor((double)nH * r);
265                 }
266                 if (nH < maxHeight)
267                 {
268                     var r = (double)maxHeight / (double)nH;
269                     nH = maxHeight;
270                     nW = (int)Math.Floor((double)nW * r);
271                 }
272             }
273             //Limit exceeded(narrow)
274             if (nW > maxWidth)
275             {
276                 var r = (double)maxWidth / (double)nW;
277                 nW = maxWidth;
278                 nH = (int)Math.Floor((double)nH * r);
279             }
280             if (nH > maxHeight)
281             {
282                 var r = (double)maxHeight / (double)nH;
283                 nH = maxHeight;
284                 nW = (int)Math.Floor((double)nW * r);
285             }
286 
287 
288             var sKBitmap2 = new SkiaSharp.SKBitmap(nW, nH);
289             var sKCanvas = new SkiaSharp.SKCanvas(sKBitmap2);
290             var sKPaint = new SkiaSharp.SKPaint
291             {
292                 FilterQuality = SkiaSharp.SKFilterQuality.Medium,
293                 IsAntialias = true
294             };
295             sKCanvas.DrawBitmap(
296                 sKBitmap,
297                 new SkiaSharp.SKRect
298                 {
299                     Location = new SkiaSharp.SKPoint { X = 0, Y = 0 },
300                     Size = new SkiaSharp.SKSize { Height = oH, Width = oW }
301                 },
302                 new SkiaSharp.SKRect
303                 {
304                     Location = new SkiaSharp.SKPoint { X = 0, Y = 0 },
305                     Size = new SkiaSharp.SKSize { Height = nH, Width = nW }
306                 }, sKPaint);
307             sKCanvas.Dispose();
308             var sKImage2 = SkiaSharp.SKImage.FromBitmap(sKBitmap2);
309             sKBitmap2.Dispose();
310             var data = sKImage2.Encode(GetImageFormatByPath(path), quality);
311             sKImage2.Dispose();
312             bytes = data.ToArray();
313             data.Dispose();
314 
315             return bytes;
316         }
317         public static void ImageScalingByOversized(string path, string savePath, int maxWidth, int maxHeight, int quality)
318         {
319             var bytes = ImageScalingByOversized(path, maxWidth, maxHeight, quality);
320             if (bytes == null || bytes.Length < 1)
321             {
322                 return;
323             }
324             string saveDirPath = System.IO.Path.GetDirectoryName(savePath);
325             if (!System.IO.Directory.Exists(saveDirPath))
326             {
327                 System.IO.Directory.CreateDirectory(saveDirPath);
328             }
329             System.IO.FileStream fs = new System.IO.FileStream(savePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None);
330             fs.Write(bytes, 0, bytes.Length);
331             fs.Close();
332         }
333         public static byte[] ImageScalingByOversized(string path, int maxWidth, int maxHeight, int quality)
334         {
335             byte[] bytes = null;
336             if (!System.IO.File.Exists(path))
337             {
338                 return bytes;
339             }
340             var fileStream = new System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
341             if (fileStream.Length > maxLength)
342             {
343                 fileStream.Dispose();
344                 return bytes;
345             }
346             var sKManagedStream = new SkiaSharp.SKManagedStream(fileStream, true);
347             var sKBitmap = SkiaSharp.SKBitmap.Decode(sKManagedStream);
348             sKManagedStream.Dispose();
349 
350             if (sKBitmap.IsEmpty)
351             {
352                 return bytes;
353             }
354 
355             if (maxWidth < 1) { maxWidth = 1; }
356             if (maxHeight < 1) { maxHeight = 1; }
357             if (quality < 1) { quality = 1; }
358             if (quality > 100) { quality = 100; }
359 
360             int oW = sKBitmap.Width;
361             int oH = sKBitmap.Height;
362             int nW = oW;
363             int nH = oH;
364 
365             if (oW > maxWidth || oH > maxHeight)
366             {
367                 nW = maxWidth;
368                 nH = maxHeight;
369                 double ratio = 1;
370 
371                 if (nW > 0 && nH > 0)
372                 {
373                     ratio = (double)nW / oW;
374                     nH = Convert.ToInt32(oH * ratio);
375                     if (maxHeight < nH)
376                     {
377                         ratio = (double)maxHeight / nH;
378                         nW = Convert.ToInt32(nW * ratio);
379                         nH = maxHeight;
380                     }
381                 }
382                 if (nW < 1 && nH < 1)
383                 {
384                     nW = oW;
385                     nH = oH;
386                 }
387                 if (nW < 1)
388                 {
389                     ratio = (double)nH / oH;
390                     nW = Convert.ToInt32(oW * ratio);
391                 }
392                 if (nH < 1)
393                 {
394                     ratio = (double)nW / oW;
395                     nH = Convert.ToInt32(oH * ratio);
396                 }
397                 var sKBitmap2 = new SkiaSharp.SKBitmap(nW, nH);
398                 var sKCanvas = new SkiaSharp.SKCanvas(sKBitmap2);
399                 var sKPaint = new SkiaSharp.SKPaint
400                 {
401                     FilterQuality = SkiaSharp.SKFilterQuality.Medium,
402                     IsAntialias = true
403                 };
404                 sKCanvas.DrawBitmap(
405                     sKBitmap,
406                     new SkiaSharp.SKRect
407                     {
408                         Location = new SkiaSharp.SKPoint { X = 0, Y = 0 },
409                         Size = new SkiaSharp.SKSize { Height = oH, Width = oW }
410                     },
411                     new SkiaSharp.SKRect
412                     {
413                         Location = new SkiaSharp.SKPoint { X = 0, Y = 0 },
414                         Size = new SkiaSharp.SKSize { Height = nH, Width = nW }
415                     }, sKPaint);
416                 sKCanvas.Dispose();
417                 sKBitmap.Dispose();
418                 sKBitmap = sKBitmap2;
419             }
420 
421             var sKImage = SkiaSharp.SKImage.FromBitmap(sKBitmap);
422             sKBitmap.Dispose();
423             var data = sKImage.Encode(GetImageFormatByPath(path), quality);
424             sKImage.Dispose();
425             bytes = data.ToArray();
426             data.Dispose();
427 
428             return bytes;
429         }
430 
431         /// <summary>
432         /// Generate two-dimensional code(320*320)
433         /// </summary>
434         /// <param name="text">Text Content</param>
435         /// <param name="savePath">Save Path</param>
436         /// <param name="logoPath">Logo Picture Path(Zoom to 1 for real QR code area size/6)</param>
437         /// <param name="keepWhiteBorderPixelVal">White Edge Processing(Negative value means no processing, maximum value not exceeding 1 in the real QR code area/10)</param>
438         public static void QRCoder(string text, string savePath, string logoPath = "", int keepWhiteBorderPixelVal = -1)
439         {
440             var format = GetImageFormatByPath(savePath);
441             byte[] bytesLogo = null;
442             if (!string.IsNullOrEmpty(logoPath) && System.IO.File.Exists(logoPath))
443             {
444                 var fsLogo = new System.IO.FileStream(logoPath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
445                 System.IO.MemoryStream ms = new System.IO.MemoryStream();
446                 fsLogo.CopyTo(ms);
447                 fsLogo.Dispose();
448                 bytesLogo = ms.ToArray();
449                 ms.Dispose();
450             }
451 
452             var bytes = QRCoder(text, format, bytesLogo, keepWhiteBorderPixelVal);
453 
454             if (bytes == null || bytes.Length < 1)
455             {
456                 return;
457             }
458 
459             var saveDirPath = System.IO.Path.GetDirectoryName(savePath);
460             if (!System.IO.Directory.Exists(saveDirPath))
461             {
462                 System.IO.Directory.CreateDirectory(saveDirPath);
463             }
464             var fs = new System.IO.FileStream(savePath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.None);
465             fs.Write(bytes, 0, bytes.Length);
466             fs.Close();
467         }
468         /// <summary>
469         /// Generate two-dimensional code(320*320)
470         /// </summary>
471         /// <param name="text">Text Content</param>
472         /// <param name="format">Save Format</param>
473         /// <param name="logoImgae">Logo picture(Zoom to 1 for real QR code area size/6)</param>
474         /// <param name="keepWhiteBorderPixelVal">White Edge Processing(Negative value means no processing, maximum value not exceeding 1 in the real QR code area/10)</param>
475         /// <returns></returns>
476         public static byte[] QRCoder(string text, SkiaSharp.SKEncodedImageFormat format, byte[] logoImgae = null, int keepWhiteBorderPixelVal = -1)
477         {
478             byte[] reval = null;
479             int width = 320;
480             int height = 320;
481             var qRCodeWriter = new ZXing.QrCode.QRCodeWriter();
482             var hints = new Dictionary<ZXing.EncodeHintType, object>();
483             hints.Add(ZXing.EncodeHintType.CHARACTER_SET, "utf-8");
484             hints.Add(ZXing.EncodeHintType.QR_VERSION, 8);
485             hints.Add(ZXing.EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.Q);
486             var bitMatrix = qRCodeWriter.encode(text, ZXing.BarcodeFormat.QR_CODE, width, height, hints);
487             var w = bitMatrix.Width;
488             var h = bitMatrix.Height;
489             var sKBitmap = new SkiaSharp.SKBitmap(w, h);
490 
491             int blackStartPointX = 0;
492             int blackStartPointY = 0;
493             int blackEndPointX = w;
494             int blackEndPointY = h;
495 
496             #region --Draw 2-D code(Get the coordinates of the start and end points of the real two-dimensional code area at the same time)--
497             var sKCanvas = new SkiaSharp.SKCanvas(sKBitmap);
498             var sKColorBlack = SkiaSharp.SKColor.Parse("000000");
499             var sKColorWihte = SkiaSharp.SKColor.Parse("ffffff");
500             sKCanvas.Clear(sKColorWihte);
501             bool blackStartPointIsNotWriteDown = true;
502             for (var y = 0; y < h; y++)
503             {
504                 for (var x = 0; x < w; x++)
505                 {
506                     var flag = bitMatrix[x, y];
507                     if (flag)
508                     {
509                         if (blackStartPointIsNotWriteDown)
510                         {
511                             blackStartPointX = x;
512                             blackStartPointY = y;
513                             blackStartPointIsNotWriteDown = false;
514                         }
515                         blackEndPointX = x;
516                         blackEndPointY = y;
517                         sKCanvas.DrawPoint(x, y, sKColorBlack);
518                     }
519                     else
520                     {
521                         //sKCanvas.DrawPoint(x, y, sKColorWihte);//Do not draw(The background is white)
522                     }
523                 }
524             }
525             sKCanvas.Dispose();
526             #endregion
527 
528             int qrcodeRealWidth = blackEndPointX - blackStartPointX;
529             int qrcodeRealHeight = blackEndPointY - blackStartPointY;
530 
531             #region -- Handling white edges --
532             if (keepWhiteBorderPixelVal > -1)//Border width specified
533             {
534                 var borderMaxWidth = (int)Math.Floor((double)qrcodeRealWidth / 10);
535                 if (keepWhiteBorderPixelVal > borderMaxWidth)
536                 {
537                     keepWhiteBorderPixelVal = borderMaxWidth;
538                 }
539                 var nQrcodeRealWidth = width - keepWhiteBorderPixelVal - keepWhiteBorderPixelVal;
540                 var nQrcodeRealHeight = height - keepWhiteBorderPixelVal - keepWhiteBorderPixelVal;
541 
542                 var sKBitmap2 = new SkiaSharp.SKBitmap(width, height);
543                 var sKCanvas2 = new SkiaSharp.SKCanvas(sKBitmap2);
544                 sKCanvas2.Clear(sKColorWihte);
545                 //No anti-aliasing, etc. is required when 2D code is drawn on a temporary canvas(Avoid file enlargement)
546                 sKCanvas2.DrawBitmap(
547                     sKBitmap,
548                     new SkiaSharp.SKRect
549                     {
550                         Location = new SkiaSharp.SKPoint { X = blackStartPointX, Y = blackStartPointY },
551                         Size = new SkiaSharp.SKSize { Height = qrcodeRealHeight, Width = qrcodeRealWidth }
552                     },
553                     new SkiaSharp.SKRect
554                     {
555                         Location = new SkiaSharp.SKPoint { X = keepWhiteBorderPixelVal, Y = keepWhiteBorderPixelVal },
556                         Size = new SkiaSharp.SKSize { Width = nQrcodeRealWidth, Height = nQrcodeRealHeight }
557                     });
558 
559                 blackStartPointX = keepWhiteBorderPixelVal;
560                 blackStartPointY = keepWhiteBorderPixelVal;
561                 qrcodeRealWidth = nQrcodeRealWidth;
562                 qrcodeRealHeight = nQrcodeRealHeight;
563 
564                 sKCanvas2.Dispose();
565                 sKBitmap.Dispose();
566                 sKBitmap = sKBitmap2;
567             }
568             #endregion
569 
570             #region -- Draw LOGO --
571             if (logoImgae != null && logoImgae.Length > 0)
572             {
573                 SkiaSharp.SKBitmap sKBitmapLogo = SkiaSharp.SKBitmap.Decode(logoImgae);
574                 if (!sKBitmapLogo.IsEmpty)
575                 {
576                     var sKPaint2 = new SkiaSharp.SKPaint
577                     {
578                         FilterQuality = SkiaSharp.SKFilterQuality.None,
579                         IsAntialias = true
580                     };
581                     var logoTargetMaxWidth = (int)Math.Floor((double)qrcodeRealWidth / 6);
582                     var logoTargetMaxHeight = (int)Math.Floor((double)qrcodeRealHeight / 6);
583                     var qrcodeCenterX = (int)Math.Floor((double)qrcodeRealWidth / 2);
584                     var qrcodeCenterY = (int)Math.Floor((double)qrcodeRealHeight / 2);
585                     var logoResultWidth = sKBitmapLogo.Width;
586                     var logoResultHeight = sKBitmapLogo.Height;
587                     if (logoResultWidth > logoTargetMaxWidth)
588                     {
589                         var r = (double)logoTargetMaxWidth / logoResultWidth;
590                         logoResultWidth = logoTargetMaxWidth;
591                         logoResultHeight = (int)Math.Floor(logoResultHeight * r);
592                     }
593                     if (logoResultHeight > logoTargetMaxHeight)
594                     {
595                         var r = (double)logoTargetMaxHeight / logoResultHeight;
596                         logoResultHeight = logoTargetMaxHeight;
597                         logoResultWidth = (int)Math.Floor(logoResultWidth * r);
598                     }
599                     var pointX = qrcodeCenterX - (int)Math.Floor((double)logoResultWidth / 2) + blackStartPointX;
600                     var pointY = qrcodeCenterY - (int)Math.Floor((double)logoResultHeight / 2) + blackStartPointY;
601 
602                     var sKCanvas3 = new SkiaSharp.SKCanvas(sKBitmap);
603                     var sKPaint = new SkiaSharp.SKPaint
604                     {
605                         FilterQuality = SkiaSharp.SKFilterQuality.Medium,
606                         IsAntialias = true
607                     };
608                     sKCanvas3.DrawBitmap(
609                         sKBitmapLogo,
610                         new SkiaSharp.SKRect
611                         {
612                             Location = new SkiaSharp.SKPoint { X = 0, Y = 0 },
613                             Size = new SkiaSharp.SKSize { Height = sKBitmapLogo.Height, Width = sKBitmapLogo.Width }
614                         },
615                         new SkiaSharp.SKRect
616                         {
617                             Location = new SkiaSharp.SKPoint { X = pointX, Y = pointY },
618                             Size = new SkiaSharp.SKSize { Height = logoResultHeight, Width = logoResultWidth }
619                         }, sKPaint);
620                     sKCanvas3.Dispose();
621                     sKPaint.Dispose();
622                     sKBitmapLogo.Dispose();
623                 }
624                 else
625                 {
626                     sKBitmapLogo.Dispose();
627                 }
628             }
629             #endregion
630 
631             SkiaSharp.SKImage sKImage = SkiaSharp.SKImage.FromBitmap(sKBitmap);
632             sKBitmap.Dispose();
633             var data = sKImage.Encode(format, 75);
634             sKImage.Dispose();
635             reval = data.ToArray();
636             data.Dispose();
637 
638             return reval;
639         }
640         public static string QRDecoder(string qrCodeFilePath)
641         {
642             if (!System.IO.File.Exists(qrCodeFilePath))
643             {
644                 throw new Exception("file does not exist");
645             }
646 
647             System.IO.FileStream fileStream = new System.IO.FileStream(qrCodeFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
648             if (fileStream.Length > maxLength)
649             {
650                 fileStream.Dispose();
651                 throw new Exception("Picture file is too large");
652             }
653             return QRDecoder(fileStream);
654         }
655         public static string QRDecoder(byte[] qrCodeBytes)
656         {
657             if(qrCodeBytes==null|| qrCodeBytes.Length<1)
658             {
659                 throw new Exception("parameter qrCodeBytes Non-existent");
660             }
661             if (qrCodeBytes.Length > maxLength)
662             {
663                 throw new Exception("Picture file is too large");
664             }
665             System.IO.MemoryStream ms = new System.IO.MemoryStream(qrCodeBytes);
666             return QRDecoder(ms);
667         }
668         public static string QRDecoder(System.IO.Stream qrCodeFileStream)
669         {
670             var sKManagedStream = new SkiaSharp.SKManagedStream(qrCodeFileStream, true);
671             var sKBitmap = SkiaSharp.SKBitmap.Decode(sKManagedStream);
672             sKManagedStream.Dispose();
673             if (sKBitmap.IsEmpty)
674             {
675                 sKBitmap.Dispose();
676                 throw new Exception("Unrecognized Picture File");
677             }
678 
679             var w = sKBitmap.Width;
680             var h = sKBitmap.Height;
681             int ps = w * h;
682             byte[] bytes = new byte[ps * 3];
683             int byteIndex = 0;
684             for (var x = 0; x < w; x++)
685             {
686                 for (var y = 0; y < h; y++)
687                 {
688                     var color = sKBitmap.GetPixel(x, y);
689                     bytes[byteIndex + 0] = color.Red;
690                     bytes[byteIndex + 1] = color.Green;
691                     bytes[byteIndex + 2] = color.Blue;
692                     byteIndex += 3;
693                 }
694             }
695             sKBitmap.Dispose();
696 
697             var qRCodeReader = new ZXing.QrCode.QRCodeReader();
698             var rGBLuminanceSource = new ZXing.RGBLuminanceSource(bytes, w, h);
699             var hybridBinarizer = new ZXing.Common.HybridBinarizer(rGBLuminanceSource);
700             var binaryBitmap = new ZXing.BinaryBitmap(hybridBinarizer);
701             var hints = new Dictionary<ZXing.DecodeHintType, object>();
702             hints.Add(ZXing.DecodeHintType.CHARACTER_SET, "utf-8");
703             var result = qRCodeReader.decode(binaryBitmap, hints);
704 
705             return result != null ? result.Text : "";
706         }
707     }
View Code

Start a console program to test the code:

 1 static void Main(string[] args)
 2         {
 3             var path = @"d:\a\Text Design.png";//size=595*842
 4             ImageHelper.ImageMaxCutByCenter(path, @"d:\a\Text Design 002.png", 1024, 768, 75);//size=1024*768
 5             ImageHelper.ImageMaxCutByCenter(path, @"d:\a\Text Design 003.png", 768, 1024, 75);//size=768*1024
 6             ImageHelper.ImageScalingToRange(path, @"d:\a\Text Design 004.png", 1024, 768, 75);//size=542*768
 7             ImageHelper.ImageScalingToRange(path, @"d:\a\Text Design 005.png", 768, 1024, 75);//size=724*1024
 8             ImageHelper.ImageScalingByOversized(path, @"d:\a\Text Design 006.png", 640, 320, 75);//size=226*320
 9             ImageHelper.ImageScalingByOversized(path, @"d:\a\Text Design 007.png", 320, 640, 75);//size=320*453
10 
11             var qrcodeSavePath = @"d:\a\hello.png";
12             var qrcodeLogoPath = @"d:\a\logo.png";
13             var qrcodeWhiteBorderPixelVal = 5;
14             var qrcodeText = "The mirror in the lobby is sad and white, like the twilight and snow!";
15             ImageHelper.QRCoder(qrcodeText, qrcodeSavePath, qrcodeLogoPath, qrcodeWhiteBorderPixelVal);
16             var result = ImageHelper.QRDecoder(qrcodeSavePath);
17             Console.WriteLine(result);
18 
19             var imageInfo = ImageHelper.GetImageInfo(qrcodeLogoPath);
20             Console.WriteLine($"WIDTH={imageInfo.Item1}&HEIGHT={imageInfo.Item2}&LENGTH={imageInfo.Item3}&FORMAT={imageInfo.Item4}");
21         }
View Code

Program run results:

Picture processing results:

 

The final picture quality is still good. If you also have image processing requirements under.net core, you can try this!

 

In the future, I will send out some small things I have written to share with you, mostly fragmented things, in order to solve real and specific problems, I hope to help all friends who have been there!

 

Origin: https://www.cnblogs.com/ruzi/p/10140754.html

Keywords: QRCode Javascript MySQL IE

Added by theqase on Fri, 17 Apr 2020 23:57:07 +0300