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 }
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 }
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