LaJiFenLei/Nirvana.Common/Barcode/BarcodeHelper.cs

191 lines
7.6 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Text;
using ZXing;
using ZXing.Common;
using ZXing.QrCode;
using ZXing.QrCode.Internal;
namespace Nirvana.Common
{
/// <summary>
/// 条形码和二维码帮助类
/// </summary>
public class BarcodeHelper
{
/// <summary>
/// 生成二维码
/// </summary>
/// <param name="text">内容</param>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <returns></returns>
public static Bitmap QrCode(string text, int width, int height, int margin = 1)
{
var writer = new BarcodeWriterPixelData();
writer.Format = BarcodeFormat.QR_CODE;
QrCodeEncodingOptions options = new QrCodeEncodingOptions()
{
DisableECI = true,//设置内容编码
CharacterSet = "UTF-8",
Width = width,//设置二维码的宽度和高度
Height = height,
Margin = margin//设置二维码的边距,单位不是固定像素
};
writer.Options = options;
var pixdata = writer.Write(text);
Bitmap map = PixToBitmap(pixdata.Pixels, pixdata.Width, pixdata.Height);
return map;
}
/// <summary>
/// 将一个字节数组转换为位图
/// </summary>
/// <param name="pixValue">显示字节数组</param>
/// <param name="width">图像宽度</param>
/// <param name="height">图像高度</param>
/// <returns></returns>
private static Bitmap PixToBitmap(byte[] pixValue,int width,int height)
{
//// 申请目标位图的变量,并将其内存区域锁定
var m_currBitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
var m_rect = new Rectangle(0, 0, width, height);
var m_bitmapData = m_currBitmap.LockBits(m_rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);
IntPtr iptr = m_bitmapData.Scan0; // 获取bmpData的内存起始位置
//// 用Marshal的Copy方法将刚才得到的内存字节数组复制到BitmapData中
System.Runtime.InteropServices.Marshal.Copy(pixValue, 0, iptr, pixValue.Length);
m_currBitmap.UnlockBits(m_bitmapData);
//// 算法到此结束,返回结果
return m_currBitmap;
}
/// <summary>
/// 生成一维条形码
/// </summary>
/// <param name="text">内容</param>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <returns></returns>
public static Bitmap BarCode(string text, int width, int height)
{
var writer = new BarcodeWriter<Bitmap>();
//使用ITF 格式,不能被现在常用的支付宝、微信扫出来
//如果想生成可识别的可以使用 CODE_128 格式
//writer.Format = BarcodeFormat.ITF;
writer.Format = BarcodeFormat.CODE_39;
EncodingOptions options = new EncodingOptions()
{
Width = width,
Height = height,
Margin = 2
};
writer.Options = options;
Bitmap map = writer.Write(text);
return map;
}
/// <summary>
/// 生成带Logo的二维码
/// </summary>
/// <param name="text">内容</param>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <param name="db">true表示删除白边</param>
public static Bitmap QrCodeLogo(string text, int width, int height, bool db = false)
{
//Logo 图片
string logoPath = System.AppDomain.CurrentDomain.BaseDirectory + @"\img\logo.png";
Bitmap logo = new Bitmap(logoPath);
//构造二维码写码器
MultiFormatWriter writer = new MultiFormatWriter();
Dictionary<EncodeHintType, object> hint = new Dictionary<EncodeHintType, object>();
hint.Add(EncodeHintType.CHARACTER_SET, "UTF-8");
hint.Add(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//hint.Add(EncodeHintType.MARGIN, 2);//旧版本不起作用,需要手动去除白边
width = width + 20;
height = height + 20;
//生成二维码
BitMatrix bm = writer.encode(text, BarcodeFormat.QR_CODE, width, height, hint);
if (db)
{
bm = deleteWhite(bm);
}
var barcodeWriter = new BarcodeWriter<Bitmap>();
Bitmap map = barcodeWriter.Write(bm);
//获取二维码实际尺寸(去掉二维码两边空白后的实际尺寸)
int[] rectangle = bm.getEnclosingRectangle();
//计算插入图片的大小和位置
int middleW = Math.Min((int)(rectangle[2] / 3.5), logo.Width);
int middleH = Math.Min((int)(rectangle[3] / 3.5), logo.Height);
int middleL = (map.Width - middleW) / 2;
int middleT = (map.Height - middleH) / 2;
// 将img转换成bmp格式否则后面无法创建Graphics对象
Bitmap bmpimg = new Bitmap(map.Width, map.Height, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(bmpimg))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.DrawImage(map, 0, 0, width, height);
//白底将二维码插入图片
g.FillRectangle(Brushes.White, middleL, middleT, middleW, middleH);
g.DrawImage(logo, middleL, middleT, middleW, middleH);
}
return bmpimg;
}
/// <summary>
/// 删除默认对应的空白
/// </summary>
/// <param name="matrix"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 读取二维码,读取失败,返回空字符串
/// </summary>
/// <param name="filename">指定二维码图片位置</param>
public static string ReadCodde(string filename)
{
BarcodeReader reader = new BarcodeReader();
reader.Options.CharacterSet = "UTF-8";
Bitmap map = new Bitmap(filename);
//MemoryStream ms = new MemoryStream();
//map.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
//byte[] bytes = ms.GetBuffer(); //byte[] bytes= ms.ToArray(); 这两句都可以,至于区别么,下面有解释
//ms.Close();
Result result = reader.Decode(map);
return result == null ? "" : result.Text;
}
}
}