本文内容
- QR 码介绍
- QR 码容量
- 确定 QR 码大小
- QR 码纠错率
- QR 码应用
- 演示 Ext.Net+QR 码封装二维条形码控件
- 参考资料
QR 码介绍
QR(Quick Response)码是一种 Matrix 类型的二维条码,可以被快速解码。比一维条码储存更多信息,无需在扫描时垂直对准扫描仪。
图 1 QR 码结构:高亮的功能元素
QR 码使用红外光来增强摄像头,而不是线性扫描,大大降低对反射角度的要求。可直接识别图像中的 QR 码,甚至能对液晶屏幕上显示的条码进行识别。
QR 码呈正方形,只有黑白两色。4 个角中的 3 个用于帮助解码软件定位,以任何角度扫描,都可正确读取。
QR 码于 1994 年由日本 Denso-Wave 公司发明,2000 年 6 月 ISO 将其标准化。
QR 码容量
数据类型 | 最大数据量 |
数字 | 7,089 字符。包括 0-9 |
字母数字 | 4,296 字符。包括 0–9 A–Z(仅大写) space $ % * + - . / : |
二进制/字节数组 | 2,953 字符。8 比特字节,共 23624 比特 |
至于中文,你可以自己算,反正中文字符是要按字节数组生成 QR 码的。
QR 码有 40 个版本,版本越大,支持的数据量越大,同时,二维码图片也越大。上表是 QR 码版本 40,参看各个版本的最大数据容量。
另外,没有必要根据数据量(字符个数或字节数组大小)动态判断使用 QR 码的哪个版本。尽管 QR 码自己有动态计算版本的公式,因为,既然要针对某个需求生成 QR 码,那么这个数据量虽然会有浮动,但基本固定。事前根据需求,比如数据量、使用环境,以及打印机和扫描仪的情况,选择一个版本就好。
如何确定 QR 码大小
QR 码的大小是由基于数据量、数据类型(数字、字母数字、二进制/字节数组)、纠错率来确定 QR 码版本;基于打印机打印或扫描仪的性能来设置 QR 码模块大小。
QR 码纠错率
图 2 纠错率:可被修复的比率
QR 码应用
QR 码原是为了在汽车制造厂便于追踪零件而设计,现在 QR 码已广泛使用在各行各业的存货管理。使用者可通过设有 RS-232C 界面的个人电脑及解码程式,连接扫描器或摄影机读取 QR 码。
近年,QR 码在日本、韩国的应用越来越普及。手机内置 QR 码解码软件让更多人了解和使用基于 QR 码所提供的服务,中国移动也推出了QR码的离线业务。尤其是日本的居酒屋、美容院,杂志,宣传海报等,用自己的手机对 QR 码进行识别,就可以方便的获取各家店铺的优惠信息。再就是电子票务领域。一般通过短信方式发送一张包含相关信息的二维码图片到用户手机,使用时只需在二维码识别终端上照一下,相关信息被读取出来。2009 年广州机场开始使用电子机票,无需登机牌,一条二维码短信就可以登机。铁道部于 2009 年新版车票采用 QR 码作为防伪措施。
演示 Ext.Net+QR 码封装二维条形码控件
概述
本文演示如何利用 Ext.Net.Panel 和 QRCodeLib 项目创建条形码。封装后如下所示:
<cc1:MyQRCode ID="MyQRCode1" Height="100" Width="100" runat="server" Title="名片" CustomData="A:张三;B:经理;C:开发;D:某某软件公司;E:北京;F:86000000;G:15800000000;H:zhangsan@hotmail.com;I:海淀区;;">
</cc1:MyQRCode>
其中,
- MyQRCode 控件为自定义二维条形码控件;
- CustomData 属性是要生成条形码的字符串。
如下图所示:
图 3 自定义 MyQRCode 控件
解决方案结构
图 4 解决方案结构
程序效果
图 5 将名片生成 QRCode 码
图 6 将短信生成 QRCode 码
图 7 将电子邮件生成 QRCode 码
图 8 将标签生成 QRCode 码
自定义 MyQRCode UI
using System;
using Ext.Net;
using System.ComponentModel;
namespace MyExtNet.Control
{
public partial class MyQRCode
{
[DefaultValue("")]
[Description("数据")]
public string CustomData
{
get
{
return (string)this.ViewState["CustomData"] ?? "";
}
set { this.ViewState["CustomData"] = value; }
}
public MyQRCode()
{
this.AnimCollapse = false;
this.AutoDataBind = false;
}
protected override void OnPreRender(EventArgs e)
{
this.AutoLoad.Url = "~/QRCodeHandler.ashx";
this.AutoLoad.Mode = Ext.Net.LoadMode.IFrame;
this.AutoLoad.Method = Ext.Net.HttpMethod.GET;
this.AutoLoad.Params.Add(new Parameter() { Name = "Data", Value = this.CustomData, Mode = Ext.Net.ParameterMode.Value });
}
}
}
自定义 MyQRCode Logic
using System;
using Ext.Net;
using System.Web;
namespace MyExtNet.Control
{
public partial class MyQRCode : Ext.Net.Panel
{
}
}
自定义处理程序 QRCodeHandler.ashx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using ThoughtWorks.QRCode.Codec;
using System.Text;
namespace ExtNetQRCode
{
/// <summary>
/// $codebehindclassname$ 的摘要说明
/// </summary>
//[WebService(Namespace = "http://tempuri.org/")]
//[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class QRCodeHandler : IHttpHandler
{
HttpResponse _response;
HttpRequest _request;
public void ProcessRequest(HttpContext context)
{
_response = context.Response;
_request = context.Request;
try
{
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
//qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.ALPHA_NUMERIC;
//qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.NUMERIC;
qrCodeEncoder.QRCodeScale = 4;
qrCodeEncoder.QRCodeVersion = 7;
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
//qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.L;
//qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.Q;
//qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;
String data = _request.QueryString["Data"].ToString();
Bitmap bitMap = qrCodeEncoder.Encode(data, Encoding.GetEncoding("UTF-8"));
WriteImageToStream(bitMap);
}
catch (Exception ex)
{
WriteImageToStream(CreateErrorBitmap(ex.Message));
}
}
private Bitmap CreateErrorBitmap(string errMessage)
{
int width = 300;
int height = 150;
Bitmap errBitmap = new Bitmap(width, height);
Graphics g = Graphics.FromImage(errBitmap);
StringFormat strFormat = new StringFormat();
strFormat.Alignment = StringAlignment.Center;
strFormat.LineAlignment = StringAlignment.Center;
g.FillRectangle(Brushes.White, 0, 0, width, height);
g.DrawRectangle(new Pen(Brushes.LightGray, 1), new Rectangle(0, 28, width - 1, height - 33));
strFormat.Alignment = StringAlignment.Center;
strFormat.LineAlignment = StringAlignment.Near;
g.DrawString("QRCode Generator Error", new Font("Arial", 10, FontStyle.Bold), Brushes.Red, new Rectangle(0, 5, width, 15), strFormat);
strFormat.Alignment = StringAlignment.Center;
strFormat.LineAlignment = StringAlignment.Center;
g.DrawString(errMessage, new Font("Arial", 10), Brushes.Red, new Rectangle(8, 28, width - 16, height - 35), strFormat);
return errBitmap;
}
private void WriteImageToStream(Bitmap bitMap)
{
_response.ClearContent();
_response.AddHeader("Content-type", "image/jpeg");
bitMap.Save(_response.OutputStream, ImageFormat.Jpeg);
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
创建页面
以“短信”为例,生成 QR 码,其他情况类似,都是以键和值的方式。其实,不以键值方式也行,只是为了解码后容易处理。
<%@ Page Language="C#" %>
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<%@ Register Assembly="MyExtNet.Control" Namespace="MyExtNet.Control" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script runat="server">1:
2: protected void EncodeClick(object sender, DirectEventArgs e)3: {
4: string value = null;5: for (int i = 0; i < this.FormPanel_Card.Items.Count; i++)6: {
7: Ext.Net.TextField txt = (Ext.Net.TextField)this.FormPanel_Card.Items[i];8: value += txt.DataIndex + ":" + txt.Text + ";";9: }
10: value += ";";11: this.MyQRCode_Message.CustomData = value;12: this.MyQRCode_Message.Render();13: }
14:
</script>
</head>
<body>
<form id="form1" runat="server">
<ext:ResourceManager ID="ResourceManager1" runat="server">
</ext:ResourceManager>
<ext:Panel ID="Panel_Card" runat="server" Title="短信" Layout="ColumnLayout" Height="150"
Width="500">
<Items>
<ext:FormPanel ID="FormPanel_Card" runat="server" ColumnWidth="0.6" Padding="5">
<Items>
<ext:TextField ID="txt_sm" runat="server" FieldLabel="手机号码" Text="158000000" DataIndex="SM">
</ext:TextField>
<ext:TextField ID="txt_txt" runat="server" FieldLabel="内容" Text="cnblog" DataIndex="TXT">
</ext:TextField>
</Items>
<Buttons>
<ext:Button ID="btn_cardqrcode" runat="server" Text="生成二维码">
<DirectEvents>
<Click OnEvent="EncodeClick">
</Click>
</DirectEvents>
</ext:Button>
</Buttons>
</ext:FormPanel>
<cc1:MyQRCode ID="MyQRCode_Message" Width="100" Height="150" runat="server">
</cc1:MyQRCode>
</Items>
</ext:Panel>
</form>
</body>
</html>