目的:
记录可行可用方案,方便下次取用。
1、maven工程pom.xml引入
<!-- 二维码 begin-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<!-- 二维码end -->2、工具类QRCodeUtils.java
package com.common.utils;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.imageio.ImageIO;
import com.baidu.aip.util.Base64Util;
import com.github.binarywang.utils.qrcode.BufferedImageLuminanceSource;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import sun.misc.BASE64Decoder;
/**
* 二维码识别(图片)
*
*/
public class QRCodeUtils {
private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;
private static final int margin = 0;
private static final int LogoPart = 4;
/**
* 解析二维码解析,此方法是解析Base64格式二维码图片 baseStr:base64字符串,data:image/png;base64开头的
*/
public static String deEncodeByBase64(String baseStr) {
String content = null;
BufferedImage image;
BASE64Decoder decoder = new BASE64Decoder();
byte[] b = null;
try {
int i = baseStr.indexOf("data:image/png;base64,");
if (i != -1) {
baseStr = baseStr.substring(i + "data:image/png;base64,".length());// 去掉base64图片的data:image/png;base64,部分才能转换为byte[]
}
b = decoder.decodeBuffer(baseStr);// baseStr转byte[]
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(b);// byte[] 转BufferedImage
image = ImageIO.read(byteArrayInputStream);
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 解码
content = result.getText();
} catch (IOException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
}
return content;
}
/**
* 解析二维码,此方法解析一个路径的二维码图片 path:图片路径
*/
public static String deEncodeByPath(String path) {
String content = null;
BufferedImage image;
try {
image = ImageIO.read(new File(path));
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 解码
System.out.println("图片中内容: ");
System.out.println("content: " + result.getText());
content = result.getText();
} catch (IOException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
}
return content;
}
/**
* 生成二维码矩阵信息
*
* @param content 二维码图片内容
* @param width 二维码图片宽度
* @param height 二维码图片高度
*/
public static BitMatrix setBitMatrix(String content, int width, int height) {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,防止中文乱码
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 指定纠错等级
hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小
BitMatrix bitMatrix = null;
try {
bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
} catch (WriterException e) {
e.printStackTrace();
}
return bitMatrix;
}
/**
* 将二维码图片输出
*
* @param matrix 二维码矩阵信息
* @param format 图片格式
* @param outStream 输出流
* @param logoPath logo图片路径
*/
public static void writeToFile(BitMatrix matrix, String format, OutputStream outStream, String logoPath)
throws IOException {
BufferedImage image = toBufferedImage(matrix);
// 加入LOGO水印效果
if (StringUtils.isNotBlank(logoPath)) {
image = addLogo(image, logoPath);
}
ImageIO.write(image, format, outStream);
}
/**
* 生成二维码图片
*
* @param matrix 二维码矩阵信息
*/
public static BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
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;
}
/**
* 在二维码图片中添加logo图片
*
* @param image 二维码图片
* @param logoPath logo图片路径
*/
public static BufferedImage addLogo(BufferedImage image, String logoPath) throws IOException {
Graphics2D g = image.createGraphics();
BufferedImage logoImage = ImageIO.read(new File(logoPath));
// 计算logo图片大小,可适应长方形图片,根据较短边生成正方形
int width = image.getWidth() < image.getHeight() ? image.getWidth() / LogoPart : image.getHeight() / LogoPart;
int height = width;
// 计算logo图片放置位置
int x = (image.getWidth() - width) / 2;
int y = (image.getHeight() - height) / 2;
// 在二维码图片上绘制logo图片
g.drawImage(logoImage, x, y, width, height, null);
// 绘制logo边框,可选
// g.drawRoundRect(x, y, logoImage.getWidth(), logoImage.getHeight(), 10, 10);
g.setStroke(new BasicStroke(2)); // 画笔粗细
g.setColor(Color.WHITE); // 边框颜色
g.drawRect(x, y, width, height); // 矩形边框
logoImage.flush();
g.dispose();
return image;
}
/**
* 为图片添加文字
*
* @param pressText 文字
* @param newImage 带文字的图片
* @param targetImage 需要添加文字的图片
* @param fontStyle 字体风格
* @param color 字体颜色
* @param fontSize 字体大小
* @param width 图片宽度
* @param height 图片高度
*/
public static void pressText(String pressText, String newImage, String targetImage, int fontStyle, Color color,
int fontSize, int width, int height) {
// 计算文字开始的位置
// x开始的位置:(图片宽度-字体大小*字的个数)/2
int startX = (width - (fontSize * pressText.length())) / 2;
// y开始的位置:图片高度-(图片高度-图片宽度)/2
int startY = height - (height - width) / 2 + fontSize;
try {
File file = new File(targetImage);
BufferedImage src = ImageIO.read(file);
int imageW = src.getWidth(null);
int imageH = src.getHeight(null);
BufferedImage image = new BufferedImage(imageW, imageH, BufferedImage.TYPE_INT_RGB);
Graphics g = image.createGraphics();
g.drawImage(src, 0, 0, imageW, imageH, null);
g.setColor(color);
g.setFont(new Font(null, fontStyle, fontSize));
g.drawString(pressText, startX, startY);
g.dispose();
FileOutputStream out = new FileOutputStream(newImage);
ImageIO.write(image, "png", out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//TODO ---生成二维码图片--
/** String content = "1e84fc3ea0c111eaa083002324ddfb32";
String format = "jpg";
int width = 100;
int height = 100;
BitMatrix bitMatrix = setBitMatrix(content, width, height);
// 可通过输出流输出到页面,也可直接保存到文件
OutputStream outStream = null;
String path = "C:/Users/Administrator/Desktop/" + new Date().getTime() + ".png";
try {
outStream = new FileOutputStream(new File(path));
writeToFile(bitMatrix, format, outStream, null);
outStream.close();
} catch (Exception e) {
e.printStackTrace();
}
*/
// 添加文字效果
//int fontSize = 12; // 字体大小
//int fontStyle = 1; // 字体风格
//String text = "测试二维码";
//String withTextPath = "c:/text" + new Date().getTime() + ".png";
//pressText(text, withTextPath, path, fontStyle, Color.BLUE, fontSize, width, height);
//TODO ---解码生成图片或者拍照后的图片---
//String file_src = "C:/Users/Administrator/Desktop/1592359181441.png";
String file_src = "C:/Users/Administrator/Desktop/1592359858.jpg";
byte[] from;
try {
from = FileUtil.readFileByBytes(file_src);
String image = Base64Util.encode(from);
String code = deEncodeByBase64(image);
System.out.println("code:"+code);
} catch (IOException e) {
e.printStackTrace();
}
}
}