二维码生成读取
使用java進行二維碼的生成與讀取使用到了谷歌的zxing.jar
第一步 導入,maven依賴或者下載指定jar包
<!-- https://mvnrepository.com/artifact/com.google.zxing/javase --> <dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.2.1</version> </dependency>第二步 書寫二維碼生成器的工具類
import java.awt.Color; import java.io.File; import java.util.Hashtable; import com.google.zxing.EncodeHintType; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; /*** QRCode 生成器的格式* * @author ai(ahx.show)*/ public class QRCodeFormat {/** 圖片大小 */private int size;/** 內容編碼格式 */private String encode;/** 錯誤修正等級 (Error Collection Level) */private ErrorCorrectionLevel errorCorrectionLevel;/** 錯誤修正等級的具體值 */private double errorCorrectionLevelValue;/** 前景色 */private Color foreGroundColor;/** 背景色 */private Color backGroundColor;/** 圖片的文件格式 */private String imageFormat;/** 圖片的外邊距大小 (Quiet Zone) */private int margin;/** 提供給編碼器額外的參數 */private Hashtable<EncodeHintType, Object> hints;/** 需要添加的圖片 */private File icon;/*** 創建一個帶有默認值的 QRCode 生成器的格式。默認值如下* * <ul>* <li>圖片大小: 256px</li>* <li>內容編碼格式: UTF-8</li>* <li>錯誤修正等級: Level M (有15% 的內容可被修正)</li>* <li>前景色: 黑色</li>* <li>背景色: 白色</li>* <li>輸出圖片的文件格式: png</li>* <li>圖片空白區域大小: 0個單位</li>* </ul>* * @return QRCode 生成器格式*/public static QRCodeFormat NEW() {return new QRCodeFormat();}private QRCodeFormat() {this.size = 256;this.encode = "utf-8";this.errorCorrectionLevel = ErrorCorrectionLevel.M;this.errorCorrectionLevelValue = 0.15;this.foreGroundColor = Color.BLACK;this.backGroundColor = Color.WHITE;this.imageFormat = "png";this.margin = 0;this.hints = new Hashtable<EncodeHintType, Object>();}/*** 返回圖片的大小。* * @return 圖片的大小*/public int getSize() {return this.size;}/*** 設置圖片的大小。圖片的大小等于實際內容與外邊距的值(建議設置成偶數值)。* * @param size* 圖片的大小* * @return QRCode生成器的格式*/public QRCodeFormat setSize(int size) {this.size = size;return this;}/*** 返回內容編碼格式。* * @return 內容編碼格式*/public String getEncode() {return encode;}/*** 設置內容編碼格式。* * @param encode* 內容編碼格式* * @return QRCode生成器的格式*/public QRCodeFormat setEncode(String encode) {this.encode = encode;return this;}/*** 返回錯誤修正等級。* * @return 錯誤修正等級*/public ErrorCorrectionLevel getErrorCorrectionLevel() {return errorCorrectionLevel;}/*** 返回錯誤修正等級的具體值。* * @return 錯誤修正等級的具體值*/public double getErrorCorrectionLevelValue() {return errorCorrectionLevelValue;}/*** 設置錯誤修正等級。其定義如下* * <ul>* <li>L: 有 7% 的內容可被修正</li>* <li>M: 有15% 的內容可被修正</li>* <li>Q: 有 25% 的內容可被修正</li>* <li>H: 有 30% 的內容可被修正</li>* </ul>* * @param errorCorrectionLevel* 錯誤修正等級* * @return QRCode生成器的格式*/public QRCodeFormat setErrorCorrectionLevel(char errorCorrectionLevel) {switch (Character.toUpperCase(errorCorrectionLevel)) {case 'L':this.errorCorrectionLevel = ErrorCorrectionLevel.L;this.errorCorrectionLevelValue = 0.07;break;case 'M':this.errorCorrectionLevel = ErrorCorrectionLevel.M;this.errorCorrectionLevelValue = 0.15;break;case 'Q':this.errorCorrectionLevel = ErrorCorrectionLevel.Q;this.errorCorrectionLevelValue = 0.25;break;case 'H':this.errorCorrectionLevel = ErrorCorrectionLevel.H;this.errorCorrectionLevelValue = 0.3;break;default:this.errorCorrectionLevel = ErrorCorrectionLevel.M;}return this;}/*** 返回前景色。* * @return 前景色*/public Color getForeGroundColor() {return foreGroundColor;}/*** 設置前景色。值為十六進制的顏色值(與 CSS 定義顏色的值相同,不支持簡寫),可以忽略「#」符號。* * @param foreGroundColor* 前景色的值* * @return QRCode生成器的格式*/public QRCodeFormat setForeGroundColor(String foreGroundColor) {try {this.foreGroundColor = getColor(foreGroundColor);}catch (NumberFormatException e) {this.foreGroundColor = Color.BLACK;}return this;}/*** 設置前景色。* * @param foreGroundColor* 前景色的值* * @return QRCode生成器的格式*/public QRCodeFormat setForeGroundColor(Color foreGroundColor) {this.foreGroundColor = foreGroundColor;return this;}/*** 返回背景色。* * @return 背景色*/public Color getBackGroundColor() {return backGroundColor;}/*** 設置背景色。值為十六進制的顏色值(與 CSS 定義顏色的值相同,不支持簡寫),可以忽略「#」符號。* * @param backGroundColor* 前景色的值* * @return QRCode生成器的格式*/public QRCodeFormat setBackGroundColor(String backGroundColor) {try {this.backGroundColor = getColor(backGroundColor);}catch (NumberFormatException e) {this.backGroundColor = Color.WHITE;}return this;}/*** 設置背景色。* * @param backGroundColor* 前景色的值* * @return QRCode生成器的格式*/public QRCodeFormat setBackGroundColor(Color backGroundColor) {this.backGroundColor = backGroundColor;return this;}/*** 返回圖片的文件格式。* * @return 圖片的文件格式*/public String getImageFormat() {return imageFormat.toUpperCase();}/*** 設置圖片的文件格式 。* * @param imageFormat* 圖片的文件格式* * @return QRCode生成器的格式*/public QRCodeFormat setImageFormat(String imageFormat) {this.imageFormat = imageFormat;return this;}/*** 返回圖片的外邊距大小。* * @return 圖片的外邊距大小*/public int getMargin() {return margin;}/*** 設置圖片的外邊距大小 。* * @param margin* 圖片的外邊距大小* * @return QRCode生成器的格式*/public QRCodeFormat setMargin(int margin) {this.margin = margin;return this;}/*** 返回提供給編碼器額外的參數。* * @return 提供給編碼器額外的參數*/public Hashtable<EncodeHintType, ?> getHints() {hints.clear();hints.put(EncodeHintType.ERROR_CORRECTION, getErrorCorrectionLevel());hints.put(EncodeHintType.CHARACTER_SET, getEncode());hints.put(EncodeHintType.MARGIN, getMargin());return hints;}/*** 返回添加的圖片。* * @return 添加的圖片*/public File getIcon() {return icon;}/*** 設置添加的圖片 。* * @param icon* 添加的圖片* * @return QRCode生成器的格式*/public QRCodeFormat setIcon(File icon) {this.icon = icon;return this;}/*** 設置添加的圖片 。* * @param iconPath* 添加的圖片* * @return QRCode生成器的格式*/public QRCodeFormat setIcon(String iconPath) {return setIcon(new File(iconPath));}private Color getColor(String hexString) {if (hexString.charAt(0) == '#') {return new Color(Long.decode(hexString).intValue());} else {return new Color(Long.decode("0xFF" + hexString).intValue());}} }第三步 使用生成器對象按照指定格式進行生成讀取二維碼
import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.Charset;import javax.imageio.ImageIO;import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; import com.google.zxing.ChecksumException; import com.google.zxing.FormatException; import com.google.zxing.LuminanceSource; import com.google.zxing.NotFoundException; import com.google.zxing.Result; import com.google.zxing.WriterException; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.QRCodeReader; import com.google.zxing.qrcode.QRCodeWriter;/*** QRCode 處理器* @ClassName: QRCode * @Description: TODO* @author: ai(ahx.show)* @date: 2016年12月18日 下午1:22:50*/ public final class QRCode {/** QRCode 生成器格式 */private QRCodeFormat format = null;/** 生成的 QRCode 圖像對象 */private BufferedImage qrcodeImage = null;/** 生成的 QRCode 圖片文件 */private File qrcodeFile = null;/*** 返回生成的 QRCode 圖像對象** @return 生成的 QRCode 圖像對象*/public BufferedImage getQrcodeImage() {return qrcodeImage;}/*** 返回生成的 QRCode 圖片文件** @return 生成的 QRCode 圖片文件*/public File getQrcodeFile() {return qrcodeFile;}private QRCode() {}/*** 使用帶默認值的「QRCode 生成器格式」來創建一個 QRCode 處理器。** @param content* 所要生成 QRCode 的內容** @return QRCode 處理器*/public static QRCode NEW(final String content) {return NEW(content, QRCodeFormat.NEW());}/*** 使用指定的「QRCode 生成器格式」來創建一個 QRCode 處理器。** @param content* 所要生成 QRCode 的內容* @param format* QRCode 生成器格式** @return QRCode 處理器*/public static QRCode NEW(final String content, QRCodeFormat format) {QRCode qrcode = new QRCode();qrcode.format = format;qrcode.qrcodeImage = toQRCode(content, format);return qrcode;}/*** 把指定的內容生成為一個 QRCode 的圖片,之后保存到指定的文件中。** @param f* 指定的文件** @return QRCode 處理器*/public QRCode toFile(String f) {return toFile(new File(f), this.format.getIcon());}/*** 把指定的內容生成為一個 QRCode 的圖片,之后保存到指定的文件中。** @param qrcodeFile* 指定的文件** @return QRCode 處理器*/public QRCode toFile(File qrcodeFile) {return toFile(qrcodeFile, this.format.getIcon());}/*** 把指定的內容生成為一個 QRCode 的圖片,并在該圖片中間添加上指定的圖片;之后保存到指定的文件內。** @param qrcodeFile* QRCode 圖片生成的指定的文件* @param appendFile* 需要添加的圖片。傳入的文件路徑如果沒有(null 或者為空)的時候將忽略該參數** @return QRCode 處理器*/public QRCode toFile(String qrcodeFile, String appendFile) {if (null == appendFile || appendFile.length() == 0) {return toFile(new File(qrcodeFile));}return toFile(new File(qrcodeFile), new File(appendFile));}/*** 把指定的內容生成為一個 QRCode 的圖片,并在該圖片中間添加上指定的圖片;之后保存到指定的文件內。** @param qrcodeFile* QRCode 圖片生成的指定的文件* @param appendFile* 需要添加的圖片。傳入的圖片不存在的時候將忽略該參數** @return QRCode 處理器*/public QRCode toFile(File qrcodeFile, File appendFile) {try {if (!qrcodeFile.exists()) {qrcodeFile.getParentFile().mkdirs();qrcodeFile.createNewFile();}if (null != appendFile && appendFile.isFile() && appendFile.length() != 0) {appendImage(ImageIO.read(appendFile));}if (!ImageIO.write(this.qrcodeImage, getSuffixName(qrcodeFile), qrcodeFile)) {throw new RuntimeException("Unexpected error writing image");}}catch (IOException e) {throw new RuntimeException(e);}this.qrcodeFile = qrcodeFile;return this;}private void appendImage(BufferedImage appendImage) {appendImage(this.qrcodeImage, appendImage, this.format);}private static void appendImage(BufferedImage qrcodeImage, BufferedImage appendImage, QRCodeFormat format) {int baseWidth = qrcodeImage.getWidth();int baseHeight = qrcodeImage.getHeight();// 計算 icon 的最大邊長// 公式為 二維碼面積*錯誤修正等級*0.4 的開方int maxWidth = (int) Math.sqrt(baseWidth * baseHeight * format.getErrorCorrectionLevelValue() * 0.4);int maxHeight = maxWidth;// 獲取 icon 的實際邊長int roundRectWidth = (maxWidth < appendImage.getWidth()) ? maxWidth : appendImage.getWidth();int roundRectHeight = (maxHeight < appendImage.getHeight()) ? maxHeight : appendImage.getHeight();BufferedImage roundRect = new BufferedImage(roundRectWidth, roundRectHeight, BufferedImage.TYPE_INT_ARGB);Graphics2D g2 = roundRect.createGraphics();g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);g2.setColor(Color.WHITE);g2.fillRoundRect(0, 0, roundRectWidth, roundRectHeight, 27, 27);g2.setComposite(AlphaComposite.SrcAtop);g2.drawImage(appendImage, 0, 0, roundRectWidth, roundRectHeight, null);g2.dispose();Graphics gc = qrcodeImage.getGraphics();gc.setColor(format.getBackGroundColor());gc.drawImage(roundRect, (baseWidth - roundRectWidth) / 2, (baseHeight - roundRectHeight) / 2, null);gc.dispose();}/*** 使用帶默認值的「QRCode 生成器格式」,把指定的內容生成為一個 QRCode 的圖像對象。** @param content* 所需生成 QRCode 的內容** @return QRCode 的圖像對象*/public static BufferedImage toQRCode(String content) {return toQRCode(content, null);}/*** 使用指定的「QRCode生成器格式」,把指定的內容生成為一個 QRCode 的圖像對象。** @param content* 所需生成 QRCode 的內容* @param format* QRCode 生成器格式* @return QRCode 的圖像對象*/public static BufferedImage toQRCode(String content, QRCodeFormat format) {if (format == null) {format = QRCodeFormat.NEW();}content = new String(content.getBytes(Charset.forName(format.getEncode())));BitMatrix matrix = null;try {matrix = new QRCodeWriter().encode(content,BarcodeFormat.QR_CODE,format.getSize(),format.getSize(),format.getHints());}catch (WriterException e) {throw new RuntimeException(e);}int width = matrix.getWidth();int height = matrix.getHeight();int fgColor = format.getForeGroundColor().getRGB();int bgColor = format.getBackGroundColor().getRGB();BufferedImage image = new BufferedImage(width, height, ColorSpace.TYPE_RGB);for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {image.setRGB(x, y, matrix.get(x, y) ? fgColor : bgColor);}}File appendFile = format.getIcon();if (null != appendFile && appendFile.isFile() && appendFile.length() != 0) {BufferedImage appendImage = null;try {appendImage = ImageIO.read(appendFile);}catch (IOException e) {throw new RuntimeException(e);}appendImage(image, appendImage, format);}return image;}/*** 從指定的 QRCode 圖片文件中解析出其內容。** @param qrcodeFile* QRCode 文件** @return QRCode 中的內容*/public static String from(String qrcodeFile) {if (qrcodeFile.startsWith("http://") || qrcodeFile.startsWith("https://")) {try {return from(new URL(qrcodeFile));}catch (MalformedURLException e) {throw new RuntimeException(e);}} else {return from(new File(qrcodeFile));}}/*** 從指定的 QRCode 圖片文件中解析出其內容。** @param qrcodeFile* QRCode 圖片文件** @return QRCode 中的內容*/public static String from(File qrcodeFile) {try {BufferedImage image = ImageIO.read(qrcodeFile);return from(image);}catch (IOException e) {throw new RuntimeException(e);}}/*** 從指定的 QRCode 圖片鏈接中解析出其內容。** @param qrcodeUrl* QRCode 圖片鏈接** @return QRCode 中的內容*/public static String from(URL qrcodeUrl) {try {BufferedImage image = ImageIO.read(qrcodeUrl);return from(image);}catch (IOException e) {throw new RuntimeException(e);}}/*** 從指定的 QRCode 圖像對象中解析出其內容。** @param qrcodeImage* QRCode 圖像對象** @return QRCode 中的內容*/public static String from(BufferedImage qrcodeImage) {LuminanceSource source = new BufferedImageLuminanceSource(qrcodeImage);BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));String content = null;try {Result result = new QRCodeReader().decode(bitmap);content = result.getText();}catch (NotFoundException e) {throw new RuntimeException(e);}catch (ChecksumException e) {throw new RuntimeException(e);}catch (FormatException e) {throw new RuntimeException(e);}return content;}private String getSuffixName(File file) {String path = file.getAbsolutePath();if (null == path) {return this.format.getImageFormat();}int pos = path.lastIndexOf('.');if (-1 == pos) {return this.format.getImageFormat();}return path.substring(pos + 1).toUpperCase();}public static void main(String[] args) throws IOException {String str="不會永遠的平靜如水陽光明媚,將自信、善良、堅定、無悔融于生命之中,走成屬于自己的風景。總感覺自己走過了一條很簡單很長遠的路程。期間那一段心靈的荒蕪常常想起,一個人的日子,一次次問自己,如果可以,我能否在從前里尋找現在的自己?拄筆前行,是我心靈的皈依";QRCode.NEW(str).toFile("d:\\2.jpg");//使用指定字符串生成二維碼System.out.println(QRCode.from("d:/2.jpg"));//讀取解析指定二維碼}}第四步 使用
工具類中的方法使用的靜態方法,可以直接使用QRCode.方法進行執行
生成二維碼方法
QRCode.NEW(str).toFile(url);
str:二維碼中包含的字符串(如果包含地址前綴添加http或https 否則不能自動跳轉 會解析地址字符串)
url:二維碼圖片生成位置
?
QRCode.from(url);
url:要解析二維碼圖片位置
?
?
總結
- 上一篇: 无人机遥感测绘服务:主要应用于航空摄影测
- 下一篇: 如何使用python快速读取tsv文件