1、常見二維碼碼制
2、常用二維碼:
QR Code |
PDF417 |
漢信碼 |
|
|
|
3、常用二維碼對比(QR、PDF417、DM、漢信碼)
|
|
QR(日)
|
PDF417(美)
|
DM(韓)
|
漢信碼(中)
|
備注
|
發(fā)明時間
|
|
1994年
|
1992年
|
1989年
|
2005年
|
|
是否中國國家標(biāo)準(zhǔn)
|
|
是
|
是
|
否
|
是
|
|
是否國際標(biāo)準(zhǔn)
|
|
是
|
是
|
是
|
是
|
|
面積
(mm*mm)
|
最小
|
21*21
|
90*9
|
10*10
|
有84個版本供自主選擇,最小碼僅有指甲大小
|
|
|
最大
|
177*177
|
853*270
|
144*144
|
|
|
信息存儲量
|
|
大
|
最小
|
小
|
大
|
|
|
字節(jié)/平方英寸
|
2953(7%糾錯信息)
|
1106(0.2%糾錯信息)
|
1556(14%糾錯信息)
|
4350
|
|
|
數(shù)字
|
4296
|
2710
|
3116
|
7829
|
|
|
字符
|
7089
|
1850
|
235
|
4350
|
|
|
漢字
|
1817
|
|
|
2174
|
|
|
二進(jìn)制
|
2953
|
1556
|
|
3262
|
|
糾錯能力
|
糾錯分級
|
4級
|
9
|
非離散分級
|
4級
|
糾錯能力越強,可以存儲的有效信息越少
|
|
最高糾錯信息
|
30%
|
46.20%
|
25%
|
30%
|
|
|
最低糾錯信息
|
7%
|
0.20%
|
14%
|
8%
|
|
表示中文
|
|
優(yōu)
|
差
|
一般
|
優(yōu)
|
|
解碼速度
|
|
快
|
慢
|
一般
|
快
|
|
抗畸變、污損能力
|
|
較弱
|
一般
|
超強
|
強
|
|
識別方向性
|
|
全方向性
|
單方向
|
單方向
|
全方向性
|
|
識別設(shè)備
|
|
支持手機、PAD、攝像頭
|
限專用設(shè)備
|
支持手機、PAD、攝像頭
|
限專用設(shè)備
|
目前大部分手機二維碼軟件僅支持QR碼
|
結(jié)論:上述資料中,最重要的一條“目前大部分手機二維碼軟件僅支持QR碼”。所以,碼制方式選用QR。
QR二維碼是目前最常用二維碼
是把字符串編碼后通過二維圖片的黑白兩色模塊顯示出來
可表示的字符串長度和 容錯率(ECC) 顯示編碼模式(EncodeMode)及版本(Version)有關(guān)
容錯率共四檔:
注:7% --> 7%的字碼可被修正。
QR碼有容錯能力,QR碼圖形如果有破損,仍然可以被機器讀取內(nèi)容,最高可以到7%~30%面積破損仍可被讀取。
編碼模式:
每增加一個版本每邊增加4個模塊 ,如: 版本2 為25x25模塊
以下幾張圖片是字符串'www.sohu.com'的二維碼使用了不同的版本的效果
5、QR碼具體java代碼。
可以通過以下方法設(shè)置容錯、編碼模式、版本
setQrcodeErrorCorrect L M Q H
setQrcodeEncodeMode N數(shù)字 A英文 其他為Binary
setQrcodeVersion 不設(shè)置會自動選擇適當(dāng)?shù)陌姹?/p>
這個庫只是通過calQrcode方法返回表示二維碼的數(shù)組,圖像需要自己處理
boolean[][] s = testQrcode.calQrcode(d);
通過開源的java 程序生成二維碼。
1、SwetakeQRCode 一個日本人寫的。
2、google開源 ZXing。
參考鏈接:http://ylq365./blog/1160635
1)SwetakeQRCode Demo(創(chuàng)建二維碼以及解析二維碼):
需要的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("二維碼內(nèi)容為:"+decodeMsg);
- }
-
-
- /**
- * 創(chuàng)建二維碼
- *
- * @param sms_info 信息內(nèi)容 如: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');//設(shè)置錯誤容錯率 L(7%) M(15%) Q(25%) H(30%)
- testQrcode.setQrcodeEncodeMode('B');//設(shè)置編碼模式 N數(shù)字 A英文 其他為Binary (設(shè)置為A的時候生成的二維碼異常)
- testQrcode.setQrcodeVersion(7);//設(shè)置版本 (1~40)
- String testString = sms_info;
- byte[] d = testString.getBytes("UTF-8");
- System.out.println("信息編碼后長度:"+d.length);
-
- // 限制最大字節(jié)數(shù)為120。容錯率、編碼模式、版本 這幾個參數(shù)決定了這個二維碼能存儲多少字節(jié)。
- 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();//釋放此圖形的上下文以及它使用的所有系統(tǒng)資源。調(diào)用 dispose 之后,就不能再使用 Graphics 對象。
- bi.flush();
- File f = new File(filePath);
- if (!f.exists()) {
- f.createNewFile();
- }
-
- // 圖像縮放
- bi=resize(bi,width,height);
-
- // 創(chuàng)建圖片
- 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 二維碼內(nèi)容
- */
- 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(創(chuàng)建二維碼以及解析二維碼):
優(yōu)點:
qrcode有1-40個version
version愈大,容錯越高,像素愈多
qrcode的api把version給屏蔽掉了。
它自己根據(jù)輸入的文字量和容錯級別,
算出來需要多少bit來存數(shù)據(jù)。
然后循環(huán)所有的version,
看哪個能放下這么多字,就用哪個version。
這樣的話,優(yōu)勢是生成的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 二維碼文字內(nèi)容
- * @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); //互聯(lián)網(wǎng)應(yīng)用二維碼不會破損,L容錯即可,易識別
- BitMatrix matrix = null;
- try {
- //BarcodeFormat.QR_CODE:設(shè)置條行碼類型
- /*
- 支持如下幾種條形碼
- 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大?。咀⒁狻勘M量不要使用黑白logo,影響識別。
- * @param @param content 二維碼內(nèi)容
- * @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,所以容錯率調(diào)高(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的。所以把方法全部取出構(gòu)建該類。
- * @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(關(guān)鍵部分)
- * @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
|