二维码终于火了,现在大街小巷大小商品广告上的二维码标签都随处可见,而且大都不是简单的纯二维码,而是中间有个性图标的二维码。

我之前做了一个使用google开源项目zxing实现二维码、一维码编码解码的程序并开放了源码(用C#实现的条形码和二维码编码解码器),今天继续在此程序基础上,实现二维码中间加小图片。

背景知识

QRcode使用里德-所罗门码来进行错误修正。对于我们来说,里德-所罗门编码有两个非常重要的特性。第一,它是一种显式系统码,也就是说,你可以在最终的编码中直接看到原有的信息。就好比我们对”hello world”进行编码,最终看到的是”hello world”以及其后面跟随的几个容错码。第二点,里德-所罗门编码是可以被”异或”的,将两个不同里德-所罗门编码得到的结果异或运算后会得到一个新的里德-所罗门码,并且这个新码的原码即是原来两个原码的异或。如果你想知道为什么这两个特性会成立,请看Finite Field Arithmetic and Reed-Solomon Coding.

QRcode

一副QRcode图像会定义一些独特的描述符来帮助人们或者电脑识别出自己是一张QRcode。这种描述符随着QRcode的大小不同而略有区别——越大的QRcode图像拥有越多的描述符。但是对于人的识别来说,特征最明显的还是图片的四个角的符号是固定的,看到这样的四个角人类就本能的反应:这是一个QRcode。

(实际上,我们可以通过读取图像最左上角的两个象素点来判断编码的冗余程度。定义黑色为0,白色为1,那么如果看到00则是L级别的冗余,01是M,10是Q,11则是最高的H级别冗余。

有了上面的这些工作,我们可以非常容易的知道原码信息在图像中的位置。然后通过改变自己的原码信息,就可以改变图像中的像素以至于可以在里面作图了。虽说如此,下面的一些情形可以让事情变得更有趣。

我做的二维码插入图片:

需要用到ZXing.Net库。

ZXing.Net 源代码地址:http://zxingnet.codeplex.com/

也可以使用Nuget包管理,添加如图:

之前我给大家免费提供了使用zxing开源项目改造而成的一二维码编码解码器,但未能插入图片。这次经过一番努力,成功将图片插入二维码,并能编码和解码。

插入图片的关键在于二维码容错系数的调整。

界面:

程序界面如下:

其中WinForm项目是我的Demo程序,zxing是Google的一个开源二维码项目。

生成二维码的代码:

               //构造二维码写码器MultiFormatWriter mutiWriter = new com.google.zxing.MultiFormatWriter();Hashtable hint=new Hashtable();hint.Add(EncodeHintType.CHARACTER_SET,"UTF-8");hint.Add(EncodeHintType.ERROR_CORRECTION,com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.H);//生成二维码ByteMatrix bm = mutiWriter.encode(txtMsg.Text, com.google.zxing.BarcodeFormat.QR_CODE, 300, 300,hint);Bitmap img = bm.ToBitmap();//要插入到二维码中的图片Image middlImg = QRMiddleImg.Image; //获取二维码实际尺寸(去掉二维码两边空白后的实际尺寸)System.Drawing.Size realSize = mutiWriter.GetEncodeSize(txtMsg.Text, com.google.zxing.BarcodeFormat.QR_CODE, 300, 300);//计算插入图片的大小和位置int middleImgW = Math.Min((int)(realSize.Width / 3.5), middlImg.Width);int middleImgH = Math.Min((int)(realSize.Height / 3.5),middlImg.Height);int middleImgL = (img.Width - middleImgW) / 2;int middleImgT = (img.Height - middleImgH) / 2;//将img转换成bmp格式,否则后面无法创建 Graphics对象Bitmap bmpimg = new Bitmap(img.Width, img.Height,System.Drawing.Imaging.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(img, 0, 0);}//在二维码中插入图片System.Drawing.Graphics MyGraphic = System.Drawing.Graphics.FromImage(bmpimg);//白底
                MyGraphic.FillRectangle(Brushes.White,middleImgL, middleImgT, middleImgW, middleImgH);MyGraphic.DrawImage(middlImg, middleImgL, middleImgT, middleImgW, middleImgH);pictureBox1.Image = bmpimg;//自动保存图片到当前目录string filename = System.Environment.CurrentDirectory + "\\QR" + DateTime.Now.Ticks.ToString() + ".jpg";bmpimg.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg);lbshow.Text = "图片已保存到:" + filename;

解析二维码的代码:

           //构建解码器MultiFormatReader mutiReader = new com.google.zxing.MultiFormatReader();Bitmap img = (Bitmap)Bitmap.FromFile(opFilePath);if (img == null)return;LuminanceSource ls = new RGBLuminanceSource(img, img.Width, img.Height);BinaryBitmap bb = new BinaryBitmap(new com.google.zxing.common.HybridBinarizer(ls));//注意  必须是Utf-8编码Hashtable hints = new Hashtable();hints.Add(EncodeHintType.CHARACTER_SET, "UTF-8");Result r = mutiReader.decode(bb, hints);txtmsg2.Text = r.Text;lbshow.Text = "解码成功!";

要在二维码中插入图片且可以正常解码,关键是要注意以下几个地方:

1、必须调整二维码的容错参数ErrorCorrectionLevel

Hashtable hint=new Hashtable();
hint.Add(EncodeHintType.CHARACTER_SET,"UTF-8");
hint.Add(EncodeHintType.ERROR_CORRECTION,com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.H);

hint是生成二维码的方法中最后一个参数,这个参数是一个hashtable,这里可以设置二维码的编码、容错系数等。

容错系数越高,生成的二维码图片越复杂,可以容忍二维码被污垢弄赃,甚至中间可以加一个小图片,识别也不受影响。

2、第二个要注意的地方是图片大小

从二维码的识别原理可以知道,二维码中原始信息被加密在下图黑色部分,而红色部分都是冗余信息,红色部分都是可以被自己的图片替换的。

为了插入图片的完整性,我们选择在最中间插入,而且长宽建议为整个二维码的3/7至1/3

//计算插入图片的大小和位置
int middleImgW = Math.Min((int)(realSize.Width / 3.5), middlImg.Width);
int middleImgH = Math.Min((int)(realSize.Height / 3.5),middlImg.Height);
int middleImgL = (img.Width - middleImgW) / 2;
int middleImgT = (img.Height - middleImgH) / 2;

我们的例子中用的就是2/7的比例。

3、扫描二维码时的卡顿问题

直接用MultiFormatReader 进行解码,既可以识别二维码,也可以识别条形码,但会出现卡顿现象。如果你的业务需求只需要识别二维码,请直接使用QRCodeReader类来解析,字符集采用utf-8,使用Harder模式,并且把可能的解析格式只定义为BarcodeFormat.QR_CODE,这对于直接二维码扫描解析无疑是帮助最大的。

    Map<DecodeHintType, Object> mHints;  mQrCodeReader = new QRCodeReader();  mHints = new Hashtable<>();  mHints.put(DecodeHintType.CHARACTER_SET, "utf-8");  mHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);  mHints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);

下载地址:

DEMO

源码下载地址:

CODE

QR二维码生成器源码(中间可插入小图片)相关推荐

  1. python用二维码共享文档_[源码和文档分享]基于Python的QR二维码的生成与识别程序...

    摘 要 进入二十一世纪之后,高新技术产业得到了极其迅速的发展.计算机.互联网.物联网.云计算等领域的发展,使得整个社会的信息化程度极大提高.随着技术的不断成熟,目前的一维条形码已逐渐向二维码过渡.本课 ...

  2. zxing Qr二维码(二维码颜色、logo)

    自己封装的二维码生成器,使用方便,案例代码如下 public static void main(String[] args) throws Exception {// logoBufferedImag ...

  3. 摄像头拍照及解析QR二维码

    此项目用C#实现了摄像头拍照及解析QR二维码,下面附上测试截图及部分源码: 拍照功能: 解析电脑拍摄的2D图片,能够正确显示文本信息 using System; using System.Collec ...

  4. Aztec 条码和 QR 二维码

    一个是有很多点的黑白方块,另一个是带有--更多点的黑白方块? 对于未受过训练的人来说, Aztec 条码和 QR 码在结构上看起来相似,但它们的设计和适用性却大不相同. 但这些区别是什么? 它们最常用 ...

  5. C# vb .NET生成QR二维码

    二维码比条形码具有更多优势,有些场合使用二维码比较多,比如支付.通过将某些数据生成二维码,就可以实现一码走天下.那么如何在C#,.Net平台代码里生成二维码呢?答案是使用SharpBarcode! S ...

  6. 【OpenCV 4开发详解】QR二维码检测

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  7. OpenCV4.0 快速QR二维码检测测试示例

    点击我爱计算机视觉标星,更快获取CVML新技术 近几年由于微信大力推广移动支付,二维码已经成为手机App的标配,在众多种类的二维码中,QR码是最为流行的. 刚刚发布的OpenCV4.0-Alpha新增 ...

  8. js 生成二维码_Node for Max 二维码生成器

    "Node for Max"是 Max8 的新功能,通过它可以在 Max 中方便的调用 NodeJS.充分利用 NodeJS 海量的 NPM 库,能大大扩展 Max 的可能性. 官 ...

  9. 永久免费的专业二维码生成器和二维码扫描器

    二维码服务平台.D客二维码.D客扫一扫.专业二维码生成器.专业二维码扫描器.网站/网址/产品/图片/名片/电话/E-Mail/文本/短信/文件/位置/活码二维码生成器.D客商城 PC端下载:http: ...

最新文章

  1. Linux 数据流重定向
  2. ICCV 2017 《Towards End-to-End Text Spotting with Convolutional Recurrent Neural Network》论文笔记
  3. Request processing failed; nested exception is feign.RetryableException: Read timed out
  4. Scala入门到精通——第十八节 隐式转换与隐式参数(一)
  5. 循环序列模型 —— 1.6 语言模型和序列生成
  6. DataList的使用,Repeater
  7. python 释放链表节点_redis:链表
  8. Linux命令详解词典
  9. FLTK学习笔记4-在FLTK中显示图片(上)
  10. 微型计算机原理与接口技术知识点
  11. 设置页数自增页眉/页脚——Word中page域代码的使用
  12. 区块链资产证券化调研整理
  13. hdu2079选课时间(动态规划母函数)
  14. 阿里云服务器ddos攻击防御
  15. 商淘软件多用户商城系统WSTMart v2.0.8程序发布
  16. 服务器管理员账号sa,一次利用MSSQL的SA账户提权获取服务器权限
  17. 教育部公布研考违规违法行为举报电话
  18. word彩色图片转黑白
  19. 用html做七巧板的方法,第一天:html、css的初步学习和制作七巧板
  20. 如何使用 javascript 获取语音数据并播放

热门文章

  1. 【英语学习】【WOTD】obsequious 释义/词源/示例
  2. 玩LOL切换界面黑屏卡住
  3. iPhone UITableViewCell 表格单元格类型
  4. 差速巡线机器人设计-及格(60+)的报告-2023
  5. EasuUI中的iconCls图标
  6. 子舱位看机票查询接口的质量
  7. 2018icpc青岛Books 思维
  8. 深入浅出讲解BANCOR算法
  9. 【splishsplash】PBD探究
  10. 中国无功补偿装置产业运行分析与投资前景预测报告2022-2028年