182 lines
6.4 KiB
C#
182 lines
6.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using SkiaSharp;
|
|
using ZXing;
|
|
using ZXing.Common;
|
|
using ZXing.QrCode.Internal;
|
|
|
|
namespace 常用工具集.Utility.Qrcode
|
|
{
|
|
public class BarCodeUtils
|
|
{
|
|
public static SKBitmap EncodeBarCode(BarcodeFormat barcodeFormat, string message, int widthPixels, int hightPixels, out string svg)
|
|
{
|
|
Dictionary<EncodeHintType, object> hints = new Dictionary<EncodeHintType, object>();
|
|
hints.Add(EncodeHintType.CHARACTER_SET, "utf-8");
|
|
hints.Add(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
|
|
hints.Add(EncodeHintType.MARGIN, 1);
|
|
BitMatrix matrix = new MultiFormatWriter().encode(message, barcodeFormat, widthPixels, hightPixels, 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("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
|
|
sb.AppendLine($"<svg version=\"1.1\" id=\"图层_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\r\n\t viewBox=\"0 0 {matrix.Width} {matrix.Height}\" style=\"enable-background:new 0 0 {matrix.Width} {matrix.Height};\" xml:space=\"preserve\">");
|
|
sb.AppendLine("<style type=\"text/css\">.st0{fill:#E60012;}</style>");
|
|
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($"<rect class=\"st0\" x=\"{x}\" y=\"{y}\" width=\"{width}\" height=\"{height}\" />");
|
|
canvas.DrawRect(x, y, width, height, paint);
|
|
}
|
|
}
|
|
}
|
|
sb.AppendLine("</svg>");
|
|
svg = sb.ToString();
|
|
canvas.Dispose();
|
|
return bitmap;
|
|
|
|
|
|
|
|
//BarcodeWriter writer = new BarcodeWriter();
|
|
////使用ITF 格式,不能被现在常用的支付宝、微信扫出来
|
|
////如果想生成可识别的可以使用 CODE_128 格式
|
|
////writer.Format = BarcodeFormat.ITF;
|
|
//writer.Format = barcodeFormat;
|
|
//EncodingOptions options = new EncodingOptions()
|
|
//{
|
|
// Width = widthPixels,
|
|
// Height = hightPixels,
|
|
// Margin = 2
|
|
//};
|
|
//writer.Options = options;
|
|
//Bitmap map = writer.Write(message);
|
|
//return map;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 找到未处理的矩形区域
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
/// <param name="matrix"></param>
|
|
/// <param name="handled"></param>
|
|
/// <param name="width"></param>
|
|
/// <param name="height"></param>
|
|
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;
|
|
}
|
|
public static SKBitmap EncodeBarCode(string message, int widthPixels, int hightPixels, out string svg)
|
|
{
|
|
return EncodeBarCode(BarcodeFormat.CODE_128, message, widthPixels, hightPixels, out svg);
|
|
}
|
|
|
|
|
|
public static SKBitmap EncodeBarCode(string msg, out string svg)
|
|
{
|
|
return EncodeBarCode(msg, 960, 500, out svg);
|
|
}
|
|
|
|
}
|
|
} |