loyung

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

其实现在二维码越来越流行,网上也有很多生成二维码的类库。写一下WEB生成二维码注意事项吧!

目前C#生成二维码大部分都是使用ThoughtWorks.QRCode或者ZXing类库生成,主要说一下ThoughtWorks,因为第一个找到的是这个类库的代码。

第一步:下载ThoughtWorks类库

搜一下“QRCode.net源码”会有很多,下载完后可以看到“QRCodeSample_DLL”文件,喜欢的话先运行看一下效果,了解一下二维码的生成需要哪些基本参数。

参数说明:

Data:需要进行二维码显示的文字

Encoding:编码方式,主要还得看二维码要显示的文字,中文就选择BYTE吧。

Correction Level:设置编码错误纠正级别

Version:版本验证

Size:画二维码时使用,值越大生成的二维码图片像素越高

运行效果:

第二步:查看源码文件
源码文件夹中主要的就在“QRCodeLib”中了,有兴趣可以研究一下每一个类的写法。

这里只说一下用法:

将“QRCodeLib”程序集生成dll放入项目或者直接将程序集放入项目,新建一个Web页面“CreatQRCode.aspx”

页面代码:

<body style="background:#fff; width:690px; margin-left:auto; margin-right:auto;">
    <form id="form1" runat="server">
      <h2>
        QRCODE二维码生成DEMO</h2>
    <h3>
        生成二维码显示区:</h3>
    <div style="width: 600px; height: 200px; border: 1px solid #ccc">
        <asp:Image ID="picEncode" runat="server" Style="margin-left: auto; margin-right: auto;"
             />
    </div>
    <h3>
        二维码参数配置区:</h3>
    <dl>
        <dt>明文数据</dt><dd style="width: 400px; height: 25px;"><input type="text" runat="server"
            id="txtEncodeData" style="width: 400px; height: 25px;" /></dd></dl>
    <dl>
        <dt>编码类型</dt>
        <dd>
            <asp:DropDownList ID="Encoding" runat="server">
                <asp:ListItem Text="字母数字" Value="AlphaNumeric"></asp:ListItem>
                <asp:ListItem Text="数字" Value="Numeric"></asp:ListItem>
                <asp:ListItem Selected="True" Text="字节" Value="Byte"></asp:ListItem>
            </asp:DropDownList>
        </dd>
        <dt>校正水平</dt>
        <dd>
            <asp:DropDownList ID="Correction_Level" runat="server">
                <asp:ListItem Text="L" Value="L"></asp:ListItem>
                <asp:ListItem Selected="True" Text="M" Value="M"></asp:ListItem>
                <asp:ListItem Text="Q" Value="Q"></asp:ListItem>
                <asp:ListItem Text="H" Value="H"></asp:ListItem>
            </asp:DropDownList>
        </dd>
    </dl>
    <dl>
        <dt>版本0~40</dt>
        <dd>
            <asp:TextBox ID="cboVersion" runat="server" Text="5"></asp:TextBox>
        </dd>
        <dt>图片大小</dt>
        <dd>
            <asp:TextBox ID="size" runat="server" Text="4"></asp:TextBox></dd>
    </dl>
    <dl>
        <dd style="text-align: center;">
            <asp:Button ID="Encode" runat="server" Text="生成" CssClass="btn_style" OnClick="Encode_Click" /></dd>
        <dd style="text-align: center;">
            <asp:Button ID="save" runat="server" Text="保存" CssClass="btn_style" /></dd></dl>
    </form>
</body>

生成二维码事件:

        /// <summary>
        /// 生成二维码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Encode_Click(object sender, EventArgs e)
        {
            string message = "";
            //验证加密数据不能为空
            if (txtEncodeData.Value.Trim() == String.Empty)
            {
                message += "明文数据不能为空;";
                return;
            }
            QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
            //获取编码方式
            String encoding = Encoding.SelectedItem.Value;
            if (encoding == "Byte")
            {
                qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
            }
            else if (encoding == "AlphaNumeric")
            {
                qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.ALPHA_NUMERIC;
            }
            else if (encoding == "Numeric")
            {
                qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.NUMERIC;
            }
            //验证图片大小参数(值越大生成的二维码图片像素越高)
            try
            {
                int scale = Convert.ToInt16(size.Text);
                qrCodeEncoder.QRCodeScale = scale;
            }
            catch (Exception ex)
            {
                message += "图片大小非法输入";
                return;
            }
            //版本验证
            try
            {
                int version = Convert.ToInt16(cboVersion.Text);
                //设置为0主要是防止编码的字符串太长时发生错误
                qrCodeEncoder.QRCodeVersion = version;
            }
            catch (Exception ex)
            {
                message += "版本大小非法输入";
            }
            //设置编码错误纠正级别
            string errorCorrect = Correction_Level.SelectedItem.Value;
            if (errorCorrect == "L")
                qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.L;
            else if (errorCorrect == "M")
                qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
            else if (errorCorrect == "Q")
                qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.Q;
            else if (errorCorrect == "H")
                qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;

            if (message == "")
            {
                //验证文件路径是否存在
                if (!File.Exists(Server.MapPath("~/Upload/QRCode/QRCode.jpg")))
                {
                    File.Create(Server.MapPath("~/Upload/QRCode/QRCode.jpg"));
                }
                Bitmap image;
                String data = txtEncodeData.Value;
                image = qrCodeEncoder.Encode(data);
                image.Dispose();
                image.Save(Server.MapPath("~/Upload/QRCode/QRCode.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);
                picEncode.ImageUrl = "~/Upload/QRCode/QRCode.jpg";
            }
            else
            {
                Master.Page.ClientScript.RegisterStartupScript(Page.GetType(), "aa", "alert('" + message + "')", true);
            }
        }

第三步:此时编译应该会出现“索引超出了数组界限”

错位位置:rsTemp[rsBlockNumber][j] = codewords[i2];

这个地方刚开始比较难搞,调试发现缺少“qrcode_data”文件夹下资源。

调试中当前环境运行路径为:C:\Program Files\Common Files\Microsoft Shared\DevServer\10.0\qrcode_data

那么把读取的资源放到指定位置即可。

1.找到“QRCodeLib”下“Resources”

2.在读取文件的指定目录下创建文件夹“qrcode_data”

3.将"Resources"文件内容拷贝到新建的“qrcode_data”

以上三个操作即可排除“索引超出了数组界限”的错误

在Web中或者通过修改一下修改“QRCodeEncoder.cs”文件,在构造函数中对“QRCODE_DATA_PATH”进行初始化。

1.修改构造函数

 

//修改构造函数       
 public QRCodeEncoder(string qrcode_data)
        {
            qrcodeErrorCorrect = ERROR_CORRECTION.M;
            qrcodeEncodeMode = ENCODE_MODE.BYTE;
            qrcodeVersion = 7;

            qrcodeStructureappendN = 0;
            qrcodeStructureappendM = 0;
            qrcodeStructureappendParity = 0;
            qrcodeStructureappendOriginaldata = "";

            qrCodeScale = 4;
            qrCodeBackgroundColor = Color.White;
            qrCodeForegroundColor = Color.Black;

            QRCODE_DATA_PATH = qrcode_data;
            //QRCODE_DATA_PATH = Environment.CurrentDirectory + @"\qrcode_data";

        }

 

2.将“qrcode_data”放在站点根目录

3.实例化QRCodeEncoder类时进行“qrcode”路径参数传递

QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(Server.MapPath("~/qrcode_data"));

 

第四步:这时会发现如果要生成中文二维码会出现乱码,那么请在“QRCodeLib”程序集中,修改编码方式未UTF-8即可。

public virtual Bitmap Encode(String content)
        {
            if (QRCodeUtility.IsUniCode(content))
            {
                //return Encode(content, Encoding.Unicode);
                //支持中文
                return Encode(content, Encoding.UTF8);
            }
            else
            {
                return Encode(content, Encoding.ASCII);
            }
        }

运行查看效果:

如果需要在二维码中心加上自己的小图标,可以把两个图层合并在一起。

判断如果传入Image对象,则叠加绘制。

 //绘制中心图标
            if (CenterImage != null)
            {
                if (CenterImage.Height != 65 || CenterImage.Width != 65)
                {
                    CenterImage = KiResizeImage(CenterImage, 65, 65, 0);
                }
                Graphics gr = Graphics.FromImage(image);
                gr.DrawImage(image, 0, 0, image.Width, image.Height);
                int s_x = (image.Width / 2 - (CenterImage.Width / 2));
                int s_y = (image.Width / 2 - (CenterImage.Width / 2));
                int size_width = CenterImage.Width;
                int size_height = CenterImage.Height;

          //绘制边框
          //gr.FillRectangle(System.Drawing.Brushes.White, s_x-1, s_y-1, size_width+2, size_height+2);

                gr.DrawImage(CenterImage, s_x, s_y, size_width, size_height);
                GC.Collect();
            }

处理中心图标大小

        /// <summary>    
        /// Resize图片    
        /// </summary>    
        /// <param name="bmp">原始Bitmap</param>    
        /// <param name="newW">新的宽度</param>    
        /// <param name="newH">新的高度</param>    
        /// <param name="Mode">保留着,暂时未用</param>    
        /// <returns>处理以后的图片</returns>    
        public static Image KiResizeImage(Image bmp, int newW, int newH, int Mode)
        {
            try
            {
                Image b = new Bitmap(newW, newH);
                Graphics g = Graphics.FromImage(b);
                // 插值算法的质量    
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.DrawImage(bmp, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
                g.Dispose();
                return b;
            }
            catch
            {
                return null;
            }
        }

效果:

 

 

实现过程中也非常感谢这些博友的奉献

果子:http://www.cnblogs.com/tianguook/p/3513497.html

毅无涯:http://www.cnblogs.com/yiwuya/archive/2012/08/13/3018795.html

posted on 2015-12-11 15:33  loyung  阅读(7591)  评论(0编辑  收藏  举报