1.寫這個部落格的目的
解決JAVA生成二維碼(一)中的一些問題。
2.解讀排錯率,編碼模式,版本問題.以下都是自己測試中存在的問題
1.排錯率
排錯的原理是二維碼在編碼過程中進行了備援,就像是123被編碼成123123,這樣隻要掃描到一部分二維碼圖檔,二維碼内容還是可以被全部讀到。
設定二維碼排錯率,可選L(7%)、M(15%)、Q(25%)、H(30%),排錯率越高可存儲的資訊越少,但對二維碼清晰度的要求越小,即是指二維碼圖示被遮擋多少後,仍可以被掃描出來的能力。排錯率越高,則二維碼圖檔能被遮擋的部分越多。
2.編碼模式
編碼模式:Numeric(N-數字):Binary(B-二進制):Alphanumeric(A-英文字母)
不同的内容使用對應的編碼格式
3.版本問題(1-40)
即二維碼的規格,QR碼符号共有40種規格的矩陣(一般為黑白色),從21x21(版本1),到177x177(版本40),每一版本符号比前一版本每邊增加4個子產品。
問題一:排錯率選太高導緻内容過長,二維碼生成失敗
如運作如下代碼:
package com.wangcong;
import com.swetake.util.Qrcode;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
public class two {
public static void main(String[] args) {
String imgPath = "E:/code.png"; // 二維碼儲存路徑
// 跳轉的内容,如果http://則當做文字處理
String content = "好好學習,天天向上,努力敲代碼學JAVA";
// 建立封裝類
QrCodeAssis assis = new QrCodeAssis(imgPath, content);
boolean result = assis.createCode(480, 480);
if (result) {
System.out.println("二維碼生成成功!");
} else {
System.out.println("二維碼生成失敗!");
}
}
}
/**
* 使用QRCode生成二維碼
*/
class QrCodeAssis{
private String imgPath; // 二維碼儲存路徑
private String content; // 二維碼内容
/**
* imgPath 二維碼儲存路徑, content 二維碼内容]
*/
QrCodeAssis(String imgPath, String content) {
this.imgPath = imgPath;
this.content = content;
}
/**
* boolean 二維碼是否生成成功
*/
boolean createCode(int width, int height) {
boolean flag = true;
try {
Qrcode qrcode = new Qrcode(); // 建立Qrcode對象
// 排錯率可選(%)-L(7):M(15):Q(25):H(30)
qrcode.setQrcodeErrorCorrect('Q');
// 編碼模式-Numeric(N-數字):Binary(B-二進制):Alphanumeric(A-英文字母)
qrcode.setQrcodeEncodeMode('B');
qrcode.setQrcodeVersion(3); // 設定版本(可選)
width = width >= 100 ? width : 100; // 寬度至少100
height = height >= 100 ? height: 100; // 高度至少100
// 建立畫布和畫圖裝置
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
Graphics2D draw = img.createGraphics();
draw.setBackground(Color.WHITE); // 設定背景色
draw.clearRect(0, 0, width, height); // 清空原始内容
draw.setColor(Color.BLACK); // 設定前景色
int posOff = 2; // 設定偏移量,避免輸出點重疊
// 設定内容編碼
byte[] codeContent = this.content.getBytes("utf-8");
// 生成二維數組,500是内容大小,根據自己的内容大小進行設定
if (codeContent.length > 0 && codeContent.length < 600) {
boolean[][] qrcodeOut = qrcode.calQrcode(codeContent);
// 将内容寫入到圖檔中
for (int i = 0; i < qrcodeOut.length; i++) {
for (int j = 0; j < qrcodeOut.length; j++) {
// 如果目前位置有像素點
if (qrcodeOut[j][i]){
// 寫入圖檔
draw.fillRect(j * 16 + posOff, i * 16 + posOff, 16, 16);
}
}
}
}
draw.dispose(); // 關閉畫圖裝置
img.flush(); // 重新整理緩沖區
File file = new File(imgPath);
ImageIO.write(img, "png", file); // 儲存圖檔
} catch (Exception e) {
e.printStackTrace();
flag = false;
}
return flag;
}
}
運作結果如下;
解決方案:可适當将版本調大,(類似與擴大二維碼容器,讓二維碼能存放更多的内容)
問題二:将版本調大之後,導緻生成的二維碼不全,掃描沒反應(問題一的一個并發問題)問題一生成的二維碼如下圖:
掃描二維碼不會有反應
解決方案:認真解讀代碼會發現提供的createCode方法有兩個參數,分别代表的是圖檔的畫布BufferedImage的寬和高隻需要适當調整一下代碼boolean result = assis.createCode(480, 480);内的2個參數即可:如下代碼:
package com.wangcong;
import com.swetake.util.Qrcode;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
public class two {
public static void main(String[] args) {
String imgPath = "E:/code.png"; // 二維碼儲存路徑
// 跳轉的内容,如果http://則當做文字處理
String content = "好好學習,天天向上,努力敲代碼學JAVA";
// 建立封裝類
QrCodeAssis assis = new QrCodeAssis(imgPath, content);
boolean result = assis.createCode(700, 700);
if (result) {
System.out.println("二維碼生成成功!");
} else {
System.out.println("二維碼生成失敗!");
}
}
}
/**
* 使用QRCode生成二維碼
*/
class QrCodeAssis{
private String imgPath; // 二維碼儲存路徑
private String content; // 二維碼内容
/**
* imgPath 二維碼儲存路徑, content 二維碼内容]
*/
QrCodeAssis(String imgPath, String content) {
this.imgPath = imgPath;
this.content = content;
}
/**
* boolean 二維碼是否生成成功
*/
boolean createCode(int width, int height) {
boolean flag = true;
try {
Qrcode qrcode = new Qrcode(); // 建立Qrcode對象
// 排錯率可選(%)-L(7):M(15):Q(25):H(30)
qrcode.setQrcodeErrorCorrect('Q');
// 編碼模式-Numeric(N-數字):Binary(B-二進制):KanJi(K-漢字):Alphanumeric(A-英文字母)
qrcode.setQrcodeEncodeMode('B');
qrcode.setQrcodeVersion(5); // 設定版本(可選)
width = width >= 100 ? width : 100; // 寬度至少100
height = height >= 100 ? height: 100; // 高度至少100
// 建立畫布和畫圖裝置
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
Graphics2D draw = img.createGraphics();
draw.setBackground(Color.WHITE); // 設定背景色
draw.clearRect(0, 0, width, height); // 清空原始内容
draw.setColor(Color.BLACK); // 設定前景色
int posOff = 2; // 設定偏移量,避免輸出點重疊
// 設定内容編碼
byte[] codeContent = this.content.getBytes("utf-8");
// 生成二維數組,500是内容大小,根據自己的内容大小進行設定
if (codeContent.length > 0 && codeContent.length < 600) {
boolean[][] qrcodeOut = qrcode.calQrcode(codeContent);
// 将内容寫入到圖檔中
for (int i = 0; i < qrcodeOut.length; i++) {
for (int j = 0; j < qrcodeOut.length; j++) {
// 如果目前位置有像素點
if (qrcodeOut[j][i]){
// 寫入圖檔
draw.fillRect(j * 16 + posOff, i * 16 + posOff, 16, 16);
}
}
}
}
draw.dispose(); // 關閉畫圖裝置
img.flush(); // 重新整理緩沖區
File file = new File(imgPath);
ImageIO.write(img, "png", file); // 儲存圖檔
} catch (Exception e) {
e.printStackTrace();
flag = false;
}
return flag;
}
}
生成的二維碼如下圖:
掃描結果如下圖:
問題三:編碼模式選擇錯誤:導緻生成的二維碼掃描沒結果(生成了一個本人部落格的網址卻不能掃描)例如如下代碼:
package com.wangcong;
import com.swetake.util.Qrcode;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
public class two {
public static void main(String[] args) {
String imgPath = "E:/code.png"; // 二維碼儲存路徑
// 跳轉的内容,如果http://則當做文字處理
String content = "https://blog.csdn.net/weixin_44255950";
// 建立封裝類
QrCodeAssis assis = new QrCodeAssis(imgPath, content);
boolean result = assis.createCode(480,480);
if (result) {
System.out.println("二維碼生成成功!");
} else {
System.out.println("二維碼生成失敗!");
}
}
}
/**
* 使用QRCode生成二維碼
*/
class QrCodeAssis{
private String imgPath; // 二維碼儲存路徑
private String content; // 二維碼内容
/**
* imgPath 二維碼儲存路徑, content 二維碼内容]
*/
QrCodeAssis(String imgPath, String content) {
this.imgPath = imgPath;
this.content = content;
}
/**
* boolean 二維碼是否生成成功
*/
boolean createCode(int width, int height) {
boolean flag = true;
try {
Qrcode qrcode = new Qrcode(); // 建立Qrcode對象
// 排錯率可選(%)-L(7):M(15):Q(25):H(30)
qrcode.setQrcodeErrorCorrect('L');
// 編碼模式-Numeric(N-數字):Binary(B-二進制):KanJi(K-漢字):Alphanumeric(A-英文字母)
qrcode.setQrcodeEncodeMode('N');
qrcode.setQrcodeVersion(3); // 設定版本(可選)
width = width >= 100 ? width : 100; // 寬度至少100
height = height >= 100 ? height: 100; // 高度至少100
// 建立畫布和畫圖裝置
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
Graphics2D draw = img.createGraphics();
draw.setBackground(Color.WHITE); // 設定背景色
draw.clearRect(0, 0, width, height); // 清空原始内容
draw.setColor(Color.BLACK); // 設定前景色
int posOff = 2; // 設定偏移量,避免輸出點重疊
// 設定内容編碼
byte[] codeContent = this.content.getBytes("utf-8");
// 生成二維數組,500是内容大小,根據自己的内容大小進行設定
if (codeContent.length > 0 && codeContent.length < 600) {
boolean[][] qrcodeOut = qrcode.calQrcode(codeContent);
// 将内容寫入到圖檔中
for (int i = 0; i < qrcodeOut.length; i++) {
for (int j = 0; j < qrcodeOut.length; j++) {
// 如果目前位置有像素點
if (qrcodeOut[j][i]){
// 寫入圖檔
draw.fillRect(j * 16 + posOff, i * 16 + posOff, 16, 16);
}
}
}
}
draw.dispose(); // 關閉畫圖裝置
img.flush(); // 重新整理緩沖區
File file = new File(imgPath);
ImageIO.write(img, "png", file); // 儲存圖檔
} catch (Exception e) {
e.printStackTrace();
flag = false;
}
return flag;
}
}
生成的二維碼如下圖:
内容存放的是本人的部落格網址,但是掃描沒有結果:
解決方案:講編碼模式改成B
生成的二維碼如下圖:
掃描結果為: