| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
-
- using System;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Runtime.InteropServices;
- //using Curtain.Helpers;
- using ZXing;
- using ZXing.QrCode;
- using ZXing.QrCode.Internal;
- namespace Dongke.WinForm.Controls.InvoiceLayout.DrawBarcode.QRCode
- {
- /// <summary>
- /// 二维码生成
- /// </summary>
- public sealed class QRCodeHelper
- {
- /// <summary>
- /// 原始二维码
- /// </summary>
- /// <param name="contents"></param>
- /// <param name="encodingOptions"></param>
- /// <returns></returns>
- public static QRCodeData Encode(string contents, QRCodeEncodingOptions encodingOptions = null)
- {
- if (encodingOptions == null)
- {
- encodingOptions = new QRCodeEncodingOptions();
- }
- QrCodeEncodingOptions qroptions = new QrCodeEncodingOptions
- {
- DisableECI = encodingOptions.DisableECI,
- CharacterSet = encodingOptions.CharacterSet,
- ErrorCorrection = GetErrorCorrectionLevel(encodingOptions.ECLevel),
- QrVersion = encodingOptions.Version
- };
- ZXing.QrCode.Internal.QRCode qrcode = null;
- try
- {
- qrcode = ZXing.QrCode.Internal.Encoder.encode(contents, qroptions.ErrorCorrection, qroptions.Hints);
- }
- catch (WriterException wex)
- {
- if (encodingOptions.Version.HasValue && wex.Message.Contains("Data too big for requested version"))
- {
- qroptions.QrVersion = null;
- try
- {
- qrcode = ZXing.QrCode.Internal.Encoder.encode(contents, qroptions.ErrorCorrection, qroptions.Hints);
- }
- catch
- {
- }
- }
- }
- if (qrcode == null)
- {
- return null;
- }
- ByteMatrix bm = qrcode.Matrix;
- int size = bm.Width;
- QRCodeData data = new QRCodeData(size)
- {
- Text = contents,
- MaskPattern = qrcode.MaskPattern,
- ModeName = qrcode.Mode.Name.ToString(),
- Version = qrcode.Version.VersionNumber,
- Options = encodingOptions,
- Width = size,
- Height = size,
- };
- for (int y = 0; y < size; y++)
- {
- for (int x = 0; x < size; x++)
- {
- data[x, y] = (bm[x, y] == 1);
- }
- }
- return data;
- }
- /// <summary>
- /// 按比例放大的原始二维码
- /// </summary>
- /// <param name="contents"></param>
- /// <param name="width"></param>
- /// <param name="height"></param>
- /// <param name="encodingOptions"></param>
- /// <returns></returns>
- public static QRCodeData Encode(string contents, int width, int height, QRCodeEncodingOptions encodingOptions = null)
- {
- QRCodeData data = Encode(contents, encodingOptions);
- if (data == null)
- {
- return null;
- }
- return Encode(data, width, height);
- }
- /// <summary>
- /// 按比例放大的原始二维码
- /// </summary>
- /// <param name="data"></param>
- /// <param name="width"></param>
- /// <param name="height"></param>
- /// <returns></returns>
- public static QRCodeData Encode(QRCodeData data, int width, int height)
- {
- if (data == null)
- {
- return null;
- }
- data.Width = width;
- data.Height = height;
- bool isHorizontal = (width > height);
- int qrSize = (isHorizontal ? height : width);
- //if (qrSize < data.Size)
- //{
- // throw new ArgumentOutOfRangeException((isHorizontal? "barcode height" : "barcode width"), (isHorizontal ? height : width), $"data size is {data.Size}");
- //}
- if (qrSize <= data.Size)
- {
- return data;
- }
- int multiple = (qrSize / data.Size);
- if (multiple == 1)
- {
- return data;
- }
- int qrDataSize = data.Size * multiple;
- QRCodeData qrData = new QRCodeData(qrDataSize)
- {
- Text = data.Text,
- MaskPattern = data.MaskPattern,
- ModeName = data.ModeName,
- Version = data.Version,
- Options = data.Options,
- Width = width,
- Height = height,
- };
- for (int y = 0; y < data.Size; y++)
- {
- int w = y * multiple;
- for (int x = 0; x < data.Size; x++)
- {
- int h = x * multiple;
- for (int j = w; j < w + multiple; j++)
- {
- for (int i = h; i < h + multiple; i++)
- {
- qrData[i, j] = data[x, y];
- }
- }
- }
- }
- return qrData;
- }
- /// <summary>
- /// 直接绘制条码
- /// </summary>
- /// <param name="contents"></param>
- /// <param name="options"></param>
- /// <param name="encodingOptions"></param>
- public static void DrawQRCode(string contents, QRCodeDrawingOptions options,
- QRCodeEncodingOptions encodingOptions = null)
- {
- if (options?.DrawGraphics == null)
- {
- throw new ArgumentNullException("QRCodeDrawingOptions.DrawGraphics");
- }
- QRCodeData data = Encode(contents, encodingOptions);
- // 条码范围
- int width = options.ImageRect.Width - options.Margin.Horizontal;
- int height = options.ImageRect.Height - options.Margin.Vertical;
- data = Encode(data, width, height);
- DrawQRCode(data, options.DrawGraphics, options);
- }
- /// <summary>
- /// 直接绘制条码
- /// </summary>
- /// <param name="data"></param>
- /// <param name="options"></param>
- public static void DrawQRCode(QRCodeData data, QRCodeDrawingOptions options)
- {
- if (options?.DrawGraphics == null)
- {
- throw new ArgumentNullException("QRCodeDrawingOptions.DrawGraphics");
- }
- //// 条码范围
- //int width = options.ImageRect.Width - options.Margin.Horizontal;
- //int height = options.ImageRect.Height - options.Margin.Vertical;
- //if (data.Width != width || data.Height != height)
- //{
- // data = Encode(data, width, height);
- //}
- DrawQRCode(data, options.DrawGraphics, options);
- }
- /// <summary>
- /// 直接绘制条码
- /// </summary>
- /// <param name="imageData"></param>
- /// <param name="graphics"></param>
- /// <param name="options"></param>
- private static void DrawQRCode(QRCodeData imageData, Graphics graphics, QRCodeDrawingOptions options)
- {
- // 条码范围
- using (Image image = GetQRCodeSource(imageData, options))
- {
- Rectangle rect = new Rectangle(
- options.ImageRect.Left + options.Margin.Left,
- options.ImageRect.Top + options.Margin.Top,
- //imageData.Width,
- //imageData.Height);
- options.ImageRect.Width - options.Margin.Horizontal,
- options.ImageRect.Height - options.Margin.Vertical);
- if (options.ShowType == BarcodeShowType.Zoom)
- {
- graphics.DrawImage(image, rect);
- }
- else if (options.ShowType == BarcodeShowType.Show)
- {
- ImageHelper.Show(image, graphics, rect, ContentAlignment.MiddleCenter, false);
- }
- else
- {
- ImageHelper.Show(image, graphics, rect, ContentAlignment.TopLeft, false);
- }
- // TODO LOGO
- // TODO TEXT
- }
- }
- /// <summary>
- /// 条码图片
- /// </summary>
- /// <param name="contents"></param>
- /// <param name="options"></param>
- /// <param name="encodingOptions"></param>
- /// <returns></returns>
- public static Image GetQRCodeImage(string contents, QRCodeDrawingOptions options, QRCodeEncodingOptions encodingOptions = null)
- {
- if (options == null)
- {
- throw new ArgumentNullException("QRCodeDrawingOptions");
- }
- QRCodeData data = Encode(contents, encodingOptions);
- // 条码范围
- int width = options.ImageRect.Width - options.Margin.Horizontal;
- int height = options.ImageRect.Height - options.Margin.Vertical;
- QRCodeData imageData = Encode(data, width, height);
- return GetQRCodeImage(imageData, options);
- }
- /// <summary>
- /// 条码图片
- /// </summary>
- /// <param name="data"></param>
- /// <param name="options"></param>
- /// <returns></returns>
- public static Image GetQRCodeImage(QRCodeData data, QRCodeDrawingOptions options)
- {
- if (options == null)
- {
- throw new ArgumentNullException("QRCodeDrawingOptions");
- }
- if (options.ShowType == BarcodeShowType.Original)
- {
- return GetQRCodeSource(data, options);
- }
- Bitmap dataImage = new Bitmap(options.ImageRect.Width, options.ImageRect.Height);
- if (options.DpiX.HasValue)
- {
- dataImage.SetResolution(options.DpiX.Value, (options.DpiY) ?? options.DpiX.Value);
- }
- using (Graphics graphics = Graphics.FromImage(dataImage))
- {
- graphics.Clear(options.BackColor);
- DrawQRCode(data, graphics, options);
- }
- return dataImage;
- }
- /// <summary>
- /// 原始条码图片
- /// </summary>
- /// <param name="data"></param>
- /// <param name="options"></param>
- /// <returns></returns>
- public static Image GetQRCodeSource(QRCodeData data, QRCodeDrawingOptions options)
- {
- Bitmap dataImage = new Bitmap(data.Size, data.Size);
- if (options != null && options.DpiX.HasValue)
- {
- dataImage.SetResolution(options.DpiX.Value, (options.DpiY) ?? options.DpiX.Value);
- }
- Rectangle rectImage = new Rectangle(0, 0, data.Size, data.Size);
- BitmapData bmpData = dataImage.LockBits(rectImage, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
- try
- {
- byte[] pixels = new byte[bmpData.Stride * bmpData.Height];
- int index = 0;
- for (int y = 0; y < data.Size; y++)
- {
- for (int x = 0; x < data.Size; x++)
- {
- Color color = (data[x, y] ? options.ForeColor : options.BackColor);
- pixels[index++] = color.B;
- pixels[index++] = color.G;
- pixels[index++] = color.R;
- pixels[index++] = color.A;
- }
- }
- Marshal.Copy(pixels, 0, bmpData.Scan0, pixels.Length);
- }
- finally
- {
- dataImage.UnlockBits(bmpData);
- }
- return dataImage;
- }
- /// <summary>
- /// 转换为zxing Level
- /// </summary>
- /// <param name="level"></param>
- /// <returns></returns>
- private static ErrorCorrectionLevel GetErrorCorrectionLevel(QRECLevel level)
- {
- switch (level)
- {
- case QRECLevel.H:
- return ErrorCorrectionLevel.H;
- case QRECLevel.L:
- return ErrorCorrectionLevel.L;
- case QRECLevel.Q:
- return ErrorCorrectionLevel.Q;
- case QRECLevel.M:
- return ErrorCorrectionLevel.M;
- default:
- return ErrorCorrectionLevel.H;
- }
- }
- /// <summary>
- /// 二维码版本对应像素
- /// </summary>
- /// <param name="version"></param>
- /// <returns></returns>
- public static int VersionToPixel(int version)
- {
- return (version - 1) * 4 + 21;
- }
- }
- }
|