zoukankan      html  css  js  c++  java
  • 二维码生成2

    上一篇二维码生成中介绍了通过类库ThoughtWorks.QRCode.dll生成二维码的简单应用,并对类库ThoughtWorks.QRCode.dll做了个简单的封装,这次在上次的基础上做修改,增加了可以在二维码中间增加自定义头像或图标。

    下面这篇文章详细介绍了二维码的原理,因为二维码中间大部分区域都是一些无用码,并不影响我们对二维码正常信息的读取,所以我们可以把一张自己的头像,或是公司商标等放在二维码的中间。

    http://developer.51cto.com/art/201310/414082_all.htm

    要在二维码中间放置商标,而不影响二维码的读取,我们必须设置二维码的纠错级别QRCodeErrorCorrect 为高:

    1 _QRCode.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;

    若不需要中间放图片,正常情况下,我们设置QRCodeErrorCorrect为M即可:

    1  _QRCode.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;

    要注意:当 _QRCode.QRCodeErrorCorrect级别不同时,二维码中可以包含的内容长度是不同的:

    当 _QRCode.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M时,最多可包含2332个字节数据,最少可包含15个字节数据;

    当 _QRCode.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H时,最多只可包含1274个字节数据,最少可包含8个字节数据;

    具体支持多少个字节数据,与属性QRCodeVersion数值有关。

    我们可以通过我简单类中的以下几个方法,来设置二维码的中间图片:

     1         /// <summary>
     2         /// 设置二维码中间图片
     3         /// </summary>
     4         /// <param name="fileName">图片文件名,包含路径</param>
     5         public void SetFillImage(string fileName)
     6         {
     7             SetFillImage(fileName, 100, 100);
     8         }
     9         /// <summary>
    10         /// 设置二维码中间图片
    11         /// </summary>
    12         /// <param name="fileName">图片文件名,包含路径</param>
    13         /// <param name="width">图片宽度</param>
    14         /// <param name="height">图片高度</param>
    15         public void SetFillImage(string fileName, int width, int height)
    16         {
    17             if (!string.IsNullOrEmpty(fileName)) {
    18                 if (File.Exists(fileName)) {
    19                     SetFillImage(Image.FromFile(fileName), width, height);
    20                 }
    21             }
    22         }
    23         /// <summary>
    24         /// 设置二维码中间图片
    25         /// </summary>
    26         /// <param name="bitmap">图上片IMAGE对象</param>
    27         public void SetFillImage(Image bitmap)
    28         {
    29             SetFillImage(bitmap, 100, 100);
    30         }
    31         /// <summary>
    32         /// 设置二维码中间图片
    33         /// </summary>
    34         /// <param name="bitmap">图上片IMAGE对象</param>
    35         /// <param name="width">图片宽度</param>
    36         /// <param name="height">图片高度</param>
    37         public void SetFillImage(Image bitmap, int width, int height)
    38         {
    39             fileImage = bitmap;
    40             _QRCode.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;
    41             this._maskWidth = width;
    42             this._maskHeight = height;
    43         }    

    设置图片时,会自动设置QRCodeErrorCorrect 属性为H。

    为了保证二维码能正确识别,中间图片的大小最好为二维码大小的1/3到3/7之间,我设置为1/3大小的样子:

    1         int maskWidth = Math.Min((int)(this.Width / 3), _maskWidth);     //最终图片宽度
    2         int maskHeight = Math.Min((int)(this.Height / 3), _maskHeight);  //最终图片高度
    3 
    4         int maskLeft = (this.Width - maskWidth) / 2;             //图片位置
    5         int maskTop = (this.Height - maskHeight) / 2;                  //图片位置

    这样在调用Encode方法生成二维码时,会自动将设置好的图片放到二维码的中间。

    具体调用方法:

    1             ErWeiMa.ErWeiMa er = new ErWeiMa.ErWeiMa();
    2             er.SetFillImage(Server.MapPath("~/t.jpg"));
    3             this.img1.Src = er.Encode("中华人民共和国");        

    生成的二维码如下所示:

    源代码:

      1     public class ErWeiMa
      2     {
      3         private QRCodeEncoder _QRCode;
      4         private Encoding encoding;
      5 
      6         public ErWeiMa()
      7         {
      8             _QRCode = new QRCodeEncoder();
      9             _QRCode.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
     10             _QRCode.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
     11             _QRCode.QRCodeScale = 4;
     12 
     13             encoding = Encoding.UTF8;
     14         }
     15 
     16         public static ErWeiMa GetInstance()
     17         {
     18             return new ErWeiMa();
     19         }
     20 
     21         /// <summary>
     22         /// 获取二维码图像base64字符串,可直接赋值给img对象的src显示
     23         /// 默认编码UTF8,QRCodeEncoder默认值为Unicode
     24         /// </summary>
     25         /// <param name="content">编码内容</param>
     26         /// <returns>二维码图像base64字符串</returns>
     27         public string Encode(string content)
     28         {
     29             return this.Encode(content, encoding);
     30         }
     31         /// <summary>
     32         /// 获取二维码图像base64字符串,可直接赋值给img对象的src显示
     33         /// </summary>
     34         /// <param name="content">编码内容</param>
     35         /// <param name="encoding">编码类型</param>
     36         /// <returns>二维码图像base64字符串</returns>
     37         public string Encode(string content,Encoding encoding)
     38         {
     39             this.encoding = encoding;
     40             this.InitVersion(content);
     41             using (var ms = new MemoryStream())
     42             using (Bitmap image = _QRCode.Encode(content, encoding))
     43             {
     44                 this.Width = image.Width;
     45                 this.Height = image.Height;
     46                 FileImage(image);
     47                 image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
     48                 return "data:image/jpeg;base64," + Convert.ToBase64String(ms.ToArray());
     49             }
     50         }
     51 
     52         private void FileImage(Bitmap source)
     53         {
     54             int maskWidth = Math.Min((int)(this.Width / 3), _maskWidth);
     55             int maskHeight = Math.Min((int)(this.Height / 3), _maskHeight);
     56 
     57             int maskLeft = (this.Width - maskWidth) / 2;
     58             int maskTop = (this.Height - maskHeight) / 2;
     59 
     60             using (Graphics g = Graphics.FromImage(source))
     61             {
     62                 g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
     63                 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
     64                 g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
     65                 //g.FillRectangle(new SolidBrush(Color.Red), maskLeft, maskTop, maskWidth, maskHeight);
     66                 ////g.DrawImage(
     67                 if (fileImage != null) {
     68                     g.DrawImage(fileImage, maskLeft, maskTop, maskWidth, maskHeight);
     69                 }
     70             }
     71         }
     72 
     73         /// <summary>
     74         /// 根据编码内容自动获取QRCodeVersion值
     75         /// </summary>
     76         /// <param name="content"></param>
     77         private void InitVersion(string content)
     78         {
     79             int length = encoding.GetByteCount(content);
     80 
     81             if (length > GetArray()[40]) {
     82                 throw new Exception("The content too length;Must be shorter than " + GetArray()[40].ToString() + "byte"); ;
     83             }
     84 
     85             _QRCode.QRCodeVersion = GetIndex(length);
     86         }
     87 
     88         /// <summary>
     89         /// 每个QRCodeVersion值对应支持最长字节数
     90         /// </summary>
     91         private int[] array = new int[41] {15,15,27,43,63,85,107,123,153,181,214,252,288,332,363,413,451,505,561,625,667,712,780,858,912,998,1060,1126,1191,1265,1371,1453,1539,1629,1723,1810,1912,1990,2100,2214,2332 };
     92         /// <summary>
     93         /// QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H时 每个QRCodeVersion值对应支持最长字节数
     94         /// </summary>
     95         private int[] array2 = new int[41] { 8, 8, 15, 25, 35, 45, 59, 65, 85, 99, 120, 138, 156, 178, 195, 221, 251, 281, 311, 339, 383, 404, 440, 462, 512, 536, 594, 626, 659, 699, 743, 791, 843, 899, 959, 984, 1052, 1094, 1140, 1220, 1274 };
     96 
     97         private int[] GetArray()
     98         {
     99             switch (_QRCode.QRCodeErrorCorrect)
    100             {
    101                 case QRCodeEncoder.ERROR_CORRECTION.H:
    102                     return array2;
    103                 case QRCodeEncoder.ERROR_CORRECTION.M:
    104                     return array;
    105                 default:
    106                     return array;
    107             }
    108         }
    109 
    110         private int GetIndex(int length)
    111         {
    112             if (length <= GetArray()[0]) {
    113                 return 0;
    114             }
    115             if (length == GetArray()[40]) {
    116                 return 40;
    117             }
    118 
    119             return FindIndex(GetArray(), length, 0, 40);
    120         }
    121 
    122         private int FindIndex(int[] sourceArray, int findValue, int startIndex, int endIndex)
    123         {
    124             int mid = (startIndex + endIndex) % 2 == 0 ? (startIndex + endIndex) / 2 : (startIndex + endIndex) / 2 + 1;
    125 
    126             if (startIndex >= endIndex) {
    127                 return startIndex;
    128             }
    129 
    130             if (findValue == sourceArray[mid])
    131             {
    132                 return mid;
    133             }
    134             else if (findValue < sourceArray[mid])
    135             {
    136                 if (findValue > sourceArray[mid - 1])
    137                 {
    138                     return mid;
    139                 }
    140                 return FindIndex(sourceArray,findValue, startIndex, mid - 1);
    141             }
    142             else {
    143                 if (findValue < sourceArray[mid + 1])
    144                 {
    145                     return mid + 1;
    146                 }
    147                 return FindIndex(sourceArray,findValue, mid + 1, endIndex);
    148             }
    149         }
    150 
    151         private Image fileImage = null;
    152 
    153         /// <summary>
    154         /// 设置二维码中间图片
    155         /// </summary>
    156         /// <param name="fileName">图片文件名,包含路径</param>
    157         public void SetFillImage(string fileName)
    158         {
    159             SetFillImage(fileName, 100, 100);
    160         }
    161         /// <summary>
    162         /// 设置二维码中间图片
    163         /// </summary>
    164         /// <param name="fileName">图片文件名,包含路径</param>
    165         /// <param name="width">图片宽度</param>
    166         /// <param name="height">图片高度</param>
    167         public void SetFillImage(string fileName, int width, int height)
    168         {
    169             if (!string.IsNullOrEmpty(fileName)) {
    170                 if (File.Exists(fileName)) {
    171                     SetFillImage(Image.FromFile(fileName), width, height);
    172                 }
    173             }
    174         }
    175         /// <summary>
    176         /// 设置二维码中间图片
    177         /// </summary>
    178         /// <param name="bitmap">图上片IMAGE对象</param>
    179         public void SetFillImage(Image bitmap)
    180         {
    181             SetFillImage(bitmap, 100, 100);
    182         }
    183         /// <summary>
    184         /// 设置二维码中间图片
    185         /// </summary>
    186         /// <param name="bitmap">图上片IMAGE对象</param>
    187         /// <param name="width">图片宽度</param>
    188         /// <param name="height">图片高度</param>
    189         public void SetFillImage(Image bitmap, int width, int height)
    190         {
    191             fileImage = bitmap;
    192             _QRCode.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;
    193             this._maskWidth = width;
    194             this._maskHeight = height;
    195         }
    196         /// <summary>
    197         /// 生成的二维码宽度
    198         /// </summary>
    199         public int Width { get; set; }
    200         /// <summary>
    201         /// 生成的二维码高度
    202         /// </summary>
    203         public int Height { get; set; }
    204 
    205         private int _maskWidth = 0;
    206         private int _maskHeight = 0;
    207     }
    View Code

    ThoughtWorks.QRCode.dll类库地址,请参见我上一篇笔记。

    如果写的内容对你有所帮助,请帮我点个赞吧,你的鼓励是对我最大的支持和动力
  • 相关阅读:
    利用FlashPaper实现类似百度文库功能
    浅谈Oracle函数返回Table集合
    Oracle 触发器在日志管理开发中的应用
    Putty 工具 保存配置的 小技巧
    java.util.Date转java.sql.Date丢失时间问题
    java String和Date转换
    springboot项目使用拦截器修改/添加前端传输到后台header和cookie参数
    Spring的使用及Spring3.2控制器增强@ControllerAdvice
    使用fastjson统一序列化响应格式
    【转】Elastic-Job
  • 原文地址:https://www.cnblogs.com/maerge/p/6445545.html
Copyright © 2011-2022 走看看