using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Text; using SkiaSharp; using ZXing; using ZXing.Common; using ZXing.QrCode.Internal; namespace 常用工具集.Utility.Qrcode { public class QRCodeUtils { /// /// /// /// 二维码内容 /// 图片长宽 /// public static SKBitmap EncodeQrCode(string msg, int codeSizeInPixels, out string svg) { Dictionary hints = new Dictionary(); hints.Add(EncodeHintType.CHARACTER_SET, "utf-8"); hints.Add(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); hints.Add(EncodeHintType.MARGIN, 1); BitMatrix matrix = new MultiFormatWriter().encode(msg, BarcodeFormat.QR_CODE, codeSizeInPixels, codeSizeInPixels, hints); matrix = deleteWhite(matrix);//删除白边 SKBitmap bitmap = new SKBitmap(matrix.Width, matrix.Height); SKCanvas canvas = new SKCanvas(bitmap); canvas.Clear(); SKPaint paint = new SKPaint() { Color = SKColors.Black, IsAntialias = true, Style = SKPaintStyle.Fill }; StringBuilder sb = new StringBuilder(); sb.AppendLine(""); sb.AppendLine($""); sb.AppendLine(""); bool[,] handled = new bool[matrix.Width, matrix.Height];//默认全部false for (int x = 0; x < matrix.Width; x++) { for (int y = 0; y < matrix.Height; y++) { if (matrix[x, y] && !handled[x, y]) { //从当前位置找矩形区域 FindRect(x, y, matrix, ref handled, out int width, out int height); //x从x到x+width //y从y到y+height //这些区域是已处理的 for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { handled[x + i, y + j] = true; } } sb.AppendLine($""); canvas.DrawRect(x, y, width, height, paint); } } } sb.AppendLine(""); svg = sb.ToString(); canvas.Dispose(); return bitmap; } /// /// 找到未处理的矩形区域 /// /// /// /// /// /// /// private static void FindRect(int x, int y, BitMatrix matrix, ref bool[,] handled, out int width, out int height) { width = 1; height = 1; bool flag = false; int maxOffset = FindXMax(matrix, x, y, ref handled); A: if (maxOffset == 0) { return; } while (true) { height++; if ((y + height) >= matrix.Height) { break; } if (!matrix[x, y + height] || handled[x, y + height]) { break; } bool allTrue = true;//默认最后一行全是true for (int i = 0; i < maxOffset; i++) { if (!matrix[x + i, y + height]) { allTrue = false; break; } if (handled[x + i, y + height]) { allTrue = false; break; } } if (allTrue) { flag = true; } else { if (flag || height == 2) { height--; break; } maxOffset--; flag = false; goto A; } } width = maxOffset + 1; } private static int FindXMax(BitMatrix matrix, int x, int y, ref bool[,] handled) { int offset = 0; while (true) { if ((x + offset) > matrix.Width) { break; } if (!matrix[x + offset, y]) { offset--; break; } offset++; } return offset; } /// /// 去除白边 /// /// /// private static BitMatrix deleteWhite(BitMatrix matrix) { int[] rec = matrix.getEnclosingRectangle(); int resWidth = rec[2] + 1; int resHeight = rec[3] + 1; BitMatrix resMatrix = new BitMatrix(resWidth, resHeight); resMatrix.clear(); for (int i = 0; i < resWidth; i++) { for (int j = 0; j < resHeight; j++) { if (matrix[i + rec[0], j + rec[1]]) resMatrix[i, j] = true; } } return resMatrix; } public static SKBitmap EncodeQrCode(string msg, out string svg) { return EncodeQrCode(msg, 900, out svg); } } }