1、常见二维码码制
2、常用二维码:
QR Code |
PDF417 |
汉信码 |
|
|
|
3、常用二维码对比(QR、PDF417、DM、汉信码)
|
|
QR(日)
|
PDF417(美)
|
DM(韩)
|
汉信码(中)
|
备注
|
发明时间
|
|
1994年
|
1992年
|
1989年
|
2005年
|
|
是否中国国家标准
|
|
是
|
是
|
否
|
是
|
|
是否国际标准
|
|
是
|
是
|
是
|
是
|
|
面积
(mm*mm)
|
最小
|
21*21
|
90*9
|
10*10
|
有84个版本供自主选择,最小码仅有指甲大小
|
|
|
最大
|
177*177
|
853*270
|
144*144
|
|
|
信息存储量
|
|
大
|
最小
|
小
|
大
|
|
|
字节/平方英寸
|
2953(7%纠错信息)
|
1106(0.2%纠错信息)
|
1556(14%纠错信息)
|
4350
|
|
|
数字
|
4296
|
2710
|
3116
|
7829
|
|
|
字符
|
7089
|
1850
|
235
|
4350
|
|
|
汉字
|
1817
|
|
|
2174
|
|
|
二进制
|
2953
|
1556
|
|
3262
|
|
纠错能力
|
纠错分级
|
4级
|
9
|
非离散分级
|
4级
|
纠错能力越强,可以存储的有效信息越少
|
|
最高纠错信息
|
30%
|
46.20%
|
25%
|
30%
|
|
|
最低纠错信息
|
7%
|
0.20%
|
14%
|
8%
|
|
表示中文
|
|
优
|
差
|
一般
|
优
|
|
解码速度
|
|
快
|
慢
|
一般
|
快
|
|
抗畸变、污损能力
|
|
较弱
|
一般
|
超强
|
强
|
|
识别方向性
|
|
全方向性
|
单方向
|
单方向
|
全方向性
|
|
识别设备
|
|
支持手机、PAD、摄像头
|
限专用设备
|
支持手机、PAD、摄像头
|
限专用设备
|
目前大部分手机二维码软件仅支持QR码
|
结论:上述资料中,最重要的一条“目前大部分手机二维码软件仅支持QR码”。所以,码制方式选用QR。
QR二维码是目前最常用二维码
是把字符串编码后通过二维图片的黑白两色模块显示出来
可表示的字符串长度和 容错率(ECC) 显示编码模式(EncodeMode)及版本(Version)有关
容错率共四档:
注:7% --> 7%的字码可被修正。
QR码有容错能力,QR码图形如果有破损,仍然可以被机器读取内容,最高可以到7%~30%面积破损仍可被读取。
编码模式:
每增加一个版本每边增加4个模块 ,如: 版本2 为25x25模块
以下几张图片是字符串'www.sohu.com'的二维码使用了不同的版本的效果
5、QR码具体java代码。
可以通过以下方法设置容错、编码模式、版本
setQrcodeErrorCorrect L M Q H
setQrcodeEncodeMode N数字 A英文 其他为Binary
setQrcodeVersion 不设置会自动选择适当的版本
这个库只是通过calQrcode方法返回表示二维码的数组,图像需要自己处理
boolean[][] s = testQrcode.calQrcode(d);
通过开源的java 程序生成二维码。
1、SwetakeQRCode 一个日本人写的。
2、google开源 ZXing。
参考链接:http://ylq365./blog/1160635
1)SwetakeQRCode Demo(创建二维码以及解析二维码):
需要的jar包:http://download.csdn.net/detail/wojiao555555/7578417
类:QRCodeSwetakeDemo.java
- package ljk.QRcode.swetake;
-
- import java.awt.Color;
- import java.awt.Graphics2D;
- import java.awt.geom.AffineTransform;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.IOException;
-
- import javax.imageio.ImageIO;
-
- import jp.sourceforge.qrcode.QRCodeDecoder;
- import jp.sourceforge.qrcode.exception.DecodingFailedException;
-
- import com.swetake.util.Qrcode;
-
- /**
- * 二维码生成demo 使用 swetake开源工具
- *
- * link:http://blog.csdn.net/wojiao555555/article/details/36184705
- */
- public class QRCodeSwetakeDemo {
-
- public static void main(String args[]) throws Exception{
-
- String sms = "http://www.";
- String filePath = "C:\\Users\\Administrator\\Desktop\\QRcode124.png";
-
- //QR码是正方形的,所以最好宽度和高度值相同
- int width = 500;
- int height = 500;
-
- createrImage(sms, filePath, width, height);
-
- String decodeMsg = decoderImage(filePath);
- System.out.println("二维码内容为:"+decodeMsg);
- }
-
-
- /**
- * 创建二维码
- *
- * @param sms_info 信息内容 如:www.
- * @param filePath 输出路径 如:"C:\\Users\\Administrator\\Desktop\\QRcode124.png"
- * @param width 宽度 生成二维码的宽度
- * @param height 高度 生成二维码的高度
- * @throws Exception
- */
- public static void createrImage(String sms_info,String filePath,int width,int height) throws Exception {
- try {
- Qrcode testQrcode = new Qrcode();
- testQrcode.setQrcodeErrorCorrect('M');//设置错误容错率 L(7%) M(15%) Q(25%) H(30%)
- testQrcode.setQrcodeEncodeMode('B');//设置编码模式 N数字 A英文 其他为Binary (设置为A的时候生成的二维码异常)
- testQrcode.setQrcodeVersion(7);//设置版本 (1~40)
- String testString = sms_info;
- byte[] d = testString.getBytes("UTF-8");
- System.out.println("信息编码后长度:"+d.length);
-
- // 限制最大字节数为120。容错率、编码模式、版本 这几个参数决定了这个二维码能存储多少字节。
- if (d.length > 0 && d.length < 120) {
- boolean[][] s = testQrcode.calQrcode(d);
- BufferedImage bi = new BufferedImage(s.length, s[0].length,
- BufferedImage.TYPE_BYTE_BINARY);
- Graphics2D g = bi.createGraphics();
- g.setBackground(Color.WHITE);
- g.clearRect(0, 0, s.length, s[0].length);
- g.setColor(Color.BLACK);
- int mulriple=1; // 1像素
- for (int i = 0; i < s.length; i++) {
- for (int j = 0; j < s.length; j++) {
- if (s[j][i]) {
- g.fillRect(j * mulriple, i * mulriple, mulriple, mulriple);
- }
- }
- }
- g.dispose();//释放此图形的上下文以及它使用的所有系统资源。调用 dispose 之后,就不能再使用 Graphics 对象。
- bi.flush();
- File f = new File(filePath);
- if (!f.exists()) {
- f.createNewFile();
- }
-
- // 图像缩放
- bi=resize(bi,width,height);
-
- // 创建图片
- ImageIO.write(bi, "png", f);
- }else {
- System.out.println("信息编码后长度过长,请升高版本值(比如 testQrcode.setQrcodeVersion(10)),或降低容错率(比如:testQrcode.setQrcodeErrorCorrect(L))");
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- /**
- * 图像缩放
- * @param source
- * @param targetW
- * @param targetH
- * @return
- */
- public static BufferedImage resize(BufferedImage source, int targetW,
- int targetH) {
- int type = source.getType();
- BufferedImage target = null;
- double sx = (double) targetW / source.getWidth();
- double sy = (double) targetH / source.getHeight();
- target = new BufferedImage(targetW, targetH, type);
- Graphics2D g = target.createGraphics();
- g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
- g.dispose();
- return target;
- }
-
- /**
- * 解析二维码
- * @param imgPath 二维码路径
- * @return 二维码内容
- */
- public static String decoderImage(String imgPath){
- File imageFile = new File(imgPath);
- BufferedImage bufImg = null;
- String content = null;
- try {
- bufImg = ImageIO.read(imageFile);
- QRCodeDecoder decoder = new QRCodeDecoder();
- content = new String(decoder.decode(new TwoDimensionCodeImage(bufImg)), "UTF-8");
- } catch (IOException e) {
- System.out.println("Error: " + e.getMessage());
- e.printStackTrace();
- } catch (DecodingFailedException dfe) {
- System.out.println("Error: " + dfe.getMessage());
- dfe.printStackTrace();
- }
- return content;
- }
- }
类:TwoDimensionCodeImage.java
- package ljk.QRcode.swetake;
-
- import java.awt.image.BufferedImage;
-
- import jp.sourceforge.qrcode.data.QRCodeImage;
-
- public class TwoDimensionCodeImage implements QRCodeImage {
-
- BufferedImage bufImg;
-
- public TwoDimensionCodeImage(BufferedImage bufImg) {
- this.bufImg = bufImg;
- }
-
- @Override
- public int getHeight() {
- return bufImg.getHeight();
- }
-
- @Override
- public int getPixel(int x, int y) {
- return bufImg.getRGB(x, y);
- }
-
- @Override
- public int getWidth() {
- return bufImg.getWidth();
- }
-
- }
生成的二维码:
尺寸:500 X 500 像素。
2)ZXingQRCode Demo(创建二维码以及解析二维码):
优点:
qrcode有1-40个version
version愈大,容错越高,像素愈多
qrcode的api把version给屏蔽掉了。
它自己根据输入的文字量和容错级别,
算出来需要多少bit来存数据。
然后循环所有的version,
看哪个能放下这么多字,就用哪个version。
这样的话,优势是生成的qrcode一直最小。
一个牛掰的作者生成的二维码链接:http://blog.csdn.net/kimmking/article/details/8244552
参考链接:http://blog.csdn.net/yangdong0906/article/details/8558871
ZXing jar包获取步骤:http://blog.csdn.net/chonbj/article/details/17913577
http://www.cnblogs.com/tankaixiong/archive/2010/10/31/1865807.html
jar包简化:http://www.cnblogs.com/keyindex/archive/2011/06/08/2074900.html
需要的jar包:http://download.csdn.net/detail/wojiao555555/7606799
类:QRCodeZXingDemo.java
- package ljk.QRcode.ZXing.ok;
-
- import java.awt.Graphics2D;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.IOException;
- import java.util.Hashtable;
-
- import javax.imageio.ImageIO;
-
- import ljk.QRcode.ZXing.addImage.MatrixToImageConfigEx;
- import ljk.QRcode.ZXing.addImage.MatrixToImageWriterEx;
-
- import com.google.zxing.BarcodeFormat;
- import com.google.zxing.EncodeHintType;
- import com.google.zxing.MultiFormatWriter;
- import com.google.zxing.WriterException;
- import com.google.zxing.client.j2se.MatrixToImageWriter;
- import com.google.zxing.common.BitMatrix;
- import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
-
- /**
- * @Description 二维码demo 包含生成、解析、生成带logo图片的二维码。
- * @version 1.0 2014-07-03
- * @author LJK
- */
- public class QRCodeZXingDemo {
- public QRCodeZXingDemo() {}
-
- /**
- * @Title: createQRCode
- * @Description: 生成二维码图片
- * @param @param content 二维码文字内容
- * @param @param width 二维码图片宽度
- * @param @param height 二维码图片高度
- * @param @param imageSavePath 二维码图片保存路径
- * @param @param imgFormat 二维码图片格式, jpg/png 等
- * @param @throws IOException
- * @return void
- * @throws
- */
- public void createQRCode(String content, int width, int height, String imageSavePath, String imgFormat) throws IOException{
- Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
- hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
-
- //指定错误纠正级别 共四个级别:
- /*
- L 7%
- M 15%
- Q 25%
- H 30%
- */
- hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); //互联网应用二维码不会破损,L容错即可,易识别
- BitMatrix matrix = null;
- try {
- //BarcodeFormat.QR_CODE:设置条行码类型
- /*
- 支持如下几种条形码
- public static final BarcodeFormat AZTEC;
- public static final BarcodeFormat CODABAR;
- public static final BarcodeFormat CODE_39;
- public static final BarcodeFormat CODE_93;
- public static final BarcodeFormat CODE_128;
- public static final BarcodeFormat DATA_MATRIX;
- public static final BarcodeFormat EAN_8;
- public static final BarcodeFormat EAN_13;
- public static final BarcodeFormat ITF;
- public static final BarcodeFormat MAXICODE;
- public static final BarcodeFormat PDF_417;
- public static final BarcodeFormat QR_CODE;
- public static final BarcodeFormat RSS_14;
- public static final BarcodeFormat RSS_EXPANDED;
- public static final BarcodeFormat UPC_A;
- public static final BarcodeFormat UPC_E;
- public static final BarcodeFormat UPC_EAN_EXTENSION;
- */
- matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
- writeToFile(matrix, imgFormat, imageSavePath);
- } catch (WriterException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * @Title: createQrCode
- * @Description: 生成二维码图片,并添加 logo (logo自动缩放为 二维码图片的 1/4大小)【注意】尽量不要使用黑白logo,影响识别。
- * @param @param content 二维码内容
- * @param @param width 二维码宽度
- * @param @param height 二维码高度
- * @param @param imageSavePath 二维码保存路径
- * @param @param imgFormat 二维码图片格式, jpg/png 等
- * @param @param logoPath logo 路径
- * @return void
- * @throws
- */
- public void createQrCode(String content, int width, int height, String imageSavePath, String imgFormat, String logoPath){
- Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
- hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
- hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); //之后要破坏图片添加logo,所以容错率调高(H),防止不能识别。
-
- BitMatrix matrix = null;
- try {
- matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
- writeToFile(matrix, imgFormat, imageSavePath, logoPath);
- } catch (WriterException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * @Title: writeToFile
- * @Description: 写出二维码到磁盘,包含logo
- * @param @param matrix 二维码 bit矩阵
- * @param @param imgFormat 二维码图片格式, jpg/png 等
- * @param @param imageSavePath 二维码保存路径
- * @param @param logoPath logo 路径
- * @return void
- * @throws
- */
- public void writeToFile(BitMatrix matrix, String imgFormat,String imageSavePath, String logoPath) {
- try {
- //写出图片
- BufferedImage image = writeToFile(matrix, imgFormat, imageSavePath);
- // //添加logo
- MatrixToImageWriterExtend.overlapImage(image, imageSavePath, logoPath, imgFormat);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * @Title: writeToFile
- * @Description: 写出图片到磁盘
- * @param @param matrix 二维码 bit 矩阵
- * @param @param imgFormat 二维码图片格式,jpg/png 等
- * @param @param imageSavePath 二维码保存路径
- * @param @throws IOException
- * @return BufferedImage 二维码缓存
- * @throws
- */
- public BufferedImage writeToFile(BitMatrix matrix, String imgFormat,
- String imageSavePath) throws IOException {
- File file = new File(imageSavePath);
- BufferedImage image = MatrixToImageWriterExtend.writeToFile(matrix, imgFormat, file);
- return image;
- }
-
- /**
- * @Title: main
- * @Description: 测试
- * @param @param args
- * @return void
- * @throws
- */
- public static void main(String[] args) {
- String content = "http://www.";
- String imageSavePath = "C:/Users/Administrator/Desktop/testode.png";
- String logoPath = "C:/Users/Administrator/Desktop/logo2.jpg";
- String imgFormat = "png";
- int width = 200;
- int height = 200;
-
- QRCodeZXingDemo qrCode = new QRCodeZXingDemo();
- try {
- //写出二维码
- // qrCode.createQRCode(content, width, height, imageSavePath, imgFormat);
- //写出带logo 的二维码
- qrCode.createQrCode(content, width, height, imageSavePath, imgFormat, logoPath);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
类:MatrixToImageWriterExtend.java
- package ljk.QRcode.ZXing.ok;
-
- import java.awt.Graphics2D;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.IOException;
- import java.io.OutputStream;
-
- import javax.imageio.ImageIO;
-
- import com.google.zxing.common.BitMatrix;
-
- /**
- * @ClassName: MatrixToImageWriterExtend
- * @Description: 继承源代码中 MatrixToImageWriter 类,但该类是final的。所以把方法全部取出构建该类。
- * @author LJK
- * @date 2014-7-7 下午12:17:50
- *
- */
- public class MatrixToImageWriterExtend {
-
- private static final int BLACK = 0xFF000000;
- private static final int WHITE = 0xFFFFFFFF;
-
- private MatrixToImageWriterExtend() {
- }
-
- public static BufferedImage toBufferedImage(BitMatrix matrix) {
- int width = matrix.getWidth();
- int height = matrix.getHeight();
- BufferedImage image = new BufferedImage(width, height,
- BufferedImage.TYPE_INT_RGB);
- for (int x = 0; x < width; x++) {
- for (int y = 0; y < height; y++) {
- image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
- }
- }
- return image;
- }
-
- /**
- * @Title: writeToFile
- * @Description: ZXing 的源代码,只不过把 BufferedImage 对象返回了。
- * @param @param matrix
- * @param @param format
- * @param @param file
- * @param @return
- * @param @throws IOException
- * @return BufferedImage
- * @throws
- */
- public static BufferedImage writeToFile(BitMatrix matrix, String format, File file)
- throws IOException {
- BufferedImage image = toBufferedImage(matrix);
- if (!ImageIO.write(image, format, file)) {
- throw new IOException("Could not write an image of format "
- + format + " to " + file);
- }
- return image;
- }
-
- /**
- * @Title: overlapImage
- * @Description: 二维码添加自定义logo(关键部分)
- * @param @param image 二维码缓存
- * @param @param imgSavePath 二维码保存路径
- * @param @param logoPath logo 路径
- * @param @param formate 二维码图片格式,jpg/png 等
- * @return void
- * @throws
- */
- public static void overlapImage(BufferedImage image, String imgSavePath, String logoPath, String formate) {
- try {
- BufferedImage logo = ImageIO.read(new File(logoPath));
-
- Graphics2D g = image.createGraphics();
- // logo宽高
- double logoWidth = logo.getWidth();
- double logoHeight = logo.getHeight();
-
- //logo 等比缩放
- while(logoWidth>image.getWidth()/2.5){
- logoWidth /= 1.25;
- logoHeight /= 1.25;
- }
-
- int width = (int)logoWidth;
- int height = (int)logoHeight;
-
- // logo起始位置,此目的是为logo居中显示
- int x = (image.getWidth() - width) / 2;
- int y = (image.getHeight() - height) / 2;
- g.drawImage(logo, x, y, width, height, null);
- g.dispose();
- ImageIO.write(image, formate, new File(imgSavePath));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public static void writeToStream(BitMatrix matrix, String format,
- OutputStream stream) throws IOException {
- BufferedImage image = toBufferedImage(matrix);
- if (!ImageIO.write(image, format, stream)) {
- throw new IOException("Could not write an image of format "
- + format);
- }
- }
- }
生成的二维码:
尺寸:500 X 500 像素。
注意:ZXing 生成的二维码是有白边的,并且生成图像哪块代码不用自己写,很方便。
完事了~~
上述demo的地址:http://download.csdn.net/detail/wojiao555555/7606829
|