主要的api
- 生成二维码
- 生成中间嵌套图片的二维码
- 解析二维码
导入依赖
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.1</version>
</dependency>
代码
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.List;
import java.util.*;
/**
* 二维码生成器
*
* @author common
*/
@Slf4j
public class QrCodeUtil {
private QrCodeUtil() {
throw new UnsupportedOperationException("cannot be instantiated");
}
/**
* 二维码尺寸List
*/
public static final List<Integer> SIZE_LIST = Collections.unmodifiableList(Arrays.asList(258, 344, 430, 860, 1280));
/**
* 图片的默认设置
*/
private static final int IMAGE_WIDTH = 100;
private static final int IMAGE_HEIGHT = 100;
private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH / 2;
private static final int FRAME_WIDTH = 2;
/**
* 二维码写码器
*/
private static MultiFormatWriter multiWriter = new MultiFormatWriter();
/**
* 生成中间嵌套图片的二维码(写入文件)
*
* @param content 二维码显示的文本
* @param width 二维码的宽度
* @param height 二维码的高度
* @param srcImageInput 中间嵌套的图片流
* @param destImagePath 二维码生成的地址
*/
@SneakyThrows
public static void writeScrQrCode(String content, int width, int height,
InputStream srcImageInput, String destImagePath, String fileName) {
BufferedImage srcImage = ImageIO.read(srcImageInput);
//创建文件
File file = createFile(destImagePath, fileName);
// ImageIO.write 参数 1、BufferedImage 2、输出的格式 3、输出的文件
//创建二维码
BufferedImage image = genBarcode(content, width, height, srcImage);
//写入文件
ImageIO.write(image, "png", file);
}
/**
* 生成中间嵌套图片的二维码(写入流)
*
* @param content 二维码显示的文本
* @param width 二维码的宽度
* @param height 二维码的高度
* @param srcImageInput 中间嵌套的图片流
* @param stream
*/
@SneakyThrows
public static void writeScrQrCode(String content, int width, int height,
InputStream srcImageInput, OutputStream stream) {
BufferedImage srcImage = ImageIO.read(srcImageInput);
//创建二维码
BufferedImage image = genBarcode(content, width, height, srcImage);
//写入流
ImageIO.write(image, "png", stream);
}
/**
* 生成二维码(写到磁盘上)
* filePath 存放图片的路径
* fileName 图片的名称
* info 内容
* width 图片的宽度
* height 图片的高度
*
* @return 图片路径
*/
@SneakyThrows
public static String writeQrCode(String filePath, String fileName, String info, int width, int height) {
//创建文件路径
Path path = createPath(filePath, fileName);
//生成二维码
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
//生成矩阵
BitMatrix bitMatrix = new MultiFormatWriter().encode(info,
BarcodeFormat.QR_CODE, width, height, hints);
//输出图像
MatrixToImageWriter.writeToPath(bitMatrix, "png", path);
return path.toString();
}
/**
* 生成二维码图片(写到流中)
*
* @param stream 流
* @param info 内容
* @param width 宽
* @param height 高
*/
@SneakyThrows
public static void writeQrCode(OutputStream stream, String info, int width, int height) {
//生成二维码
EnumMap<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
hints.put(EncodeHintType.MARGIN, 0);
//生成矩阵
BitMatrix bitMatrix = new MultiFormatWriter().encode(info,
BarcodeFormat.QR_CODE, width, height, hints);
//去白边
bitMatrix = deleteWhite(bitMatrix);
BufferedImage bi = MatrixToImageWriter.toBufferedImage(bitMatrix);
//调整大小
bi = zoomInImage(bi, width, height);
//输出图像
ImageIO.write(bi, "png", stream);
}
/**
* 解析二维码
*/
public static String decodeQrCode(InputStream inputStream) {
try {
BufferedImage image = ImageIO.read(inputStream);
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
EnumMap<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
hints.put(DecodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
// 对图像进行解码
Result result = new MultiFormatReader().decode(binaryBitmap, hints);
log.info("图片中内容:{}", result.getText());
return result.getText();
} catch (Exception e) {
log.warn("解析二维码失败,异常信息:{}", e.getMessage());
throw new IllegalArgumentException("解析二维码失败");
}
}
/**
* 去除白边
*
* @param matrix 矩阵
* @return
*/
private static BitMatrix deleteWhite(BitMatrix matrix) {
int[] rec = matrix.getEnclosingRectangle();
int resWidth = rec[2] + 1;
int resHeight = rec[3] + 1;
BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
resMatrix.clear();
for (int i = 0; i < resWidth; i++) {
for (int j = 0; j < resHeight; j++) {
if (matrix.get(i + rec[0], j + rec[1])) {
resMatrix.set(i, j);
}
}
}
return resMatrix;
}
/**
* 将图像调整为指定的宽度和高度
*
* @param originalImage 员图像
* @param width 新的宽度
* @param height 新的高度
* @return 调整后的图像
*/
private static BufferedImage zoomInImage(BufferedImage originalImage, int width, int height) {
BufferedImage newImage = new BufferedImage(width, height, originalImage.getType());
Graphics g = newImage.getGraphics();
g.drawImage(originalImage, 0, 0, width, height, null);
g.dispose();
return newImage;
}
private static File createFile(String path, String fileName) {
File dir = new File(path);
if (!dir.exists()) {
boolean result = dir.mkdirs();
log.info("mkdirs result:{}", result);
}
return new File(path + fileName);
}
/**
* 创建文件路径
*
* @param filePath 路径
* @param fileName 文件名
* @return
*/
private static Path createPath(String filePath, String fileName) {
Path path = FileSystems.getDefault().getPath(filePath, fileName);
File dir = new File(filePath);
if (!dir.exists()) {
boolean result = dir.mkdirs();
log.info("mkdirs result:{}", result);
}
return path;
}
/**
* 补白
*
* @param destImage 原图片
* @param height 高
* @param width 宽
* @return
*/
private static BufferedImage repairWhite(Image destImage, int height,
int width) {
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D graphic = image.createGraphics();
graphic.setColor(Color.white);
graphic.fillRect(0, 0, width, height);
if (width == destImage.getWidth(null)) {
graphic.drawImage(destImage, 0, (height - destImage
.getHeight(null)) / 2, destImage.getWidth(null),
destImage.getHeight(null), Color.white, null);
} else {
graphic.drawImage(destImage,
(width - destImage.getWidth(null)) / 2, 0, destImage
.getWidth(null), destImage.getHeight(null),
Color.white, null);
}
graphic.dispose();
return image;
}
/**
* 生成带有中间嵌套图片的二维码
*
* @param content 内容
* @param width 宽
* @param height 高
* @param srcImage 中间图片
* @return
*/
@SneakyThrows
private static BufferedImage genBarcode(String content, int width,
int height, BufferedImage srcImage) {
// 缩放中间嵌套的图片
BufferedImage scaleImage = scale(srcImage, IMAGE_HEIGHT, IMAGE_WIDTH, false);
int[] srcPixels = scaleImage.getRGB(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null, 0, IMAGE_WIDTH);
// 设置二维码生成的参数
Map<EncodeHintType, Object> hint = new EnumMap<>(EncodeHintType.class);
hint.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hint.put(EncodeHintType.MARGIN, 1);
// 生成二维码
BitMatrix matrix = multiWriter.encode(content, BarcodeFormat.QR_CODE,
width, height, hint);
int[] pixels = new int[width * height];
int halfW = matrix.getWidth() / 2;
int halfH = matrix.getHeight() / 2;
// 设置嵌套图片的边框大小
int[] frame = {halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH, halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH,
halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH, halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH};
for (int y = 0; y < matrix.getHeight(); y++) {
for (int x = 0; x < matrix.getWidth(); x++) {
if (x > frame[0] && x < frame[1] && y > frame[2] && y < frame[3]) {
// 填充嵌套图片
pixels[y * width + x] = srcPixels[(y - halfH + IMAGE_HALF_WIDTH) * IMAGE_WIDTH + x - halfW + IMAGE_HALF_WIDTH];
} else if (x <= frame[0] || x >= frame[1] || y <= frame[2] || y >= frame[3]) {
// 填充二维码
pixels[y * width + x] = matrix.get(x, y) ? 0xff000000 : 0xffffffff;
}
}
}
return createImage(width, height, pixels);
}
/**
* 将像素数组转换为BufferedImage对象
*
* @param width 宽
* @param height 高
* @param pixels 像素数组
* @return
*/
private static BufferedImage createImage(int width, int height, int[] pixels) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
image.setRGB(0, 0, width, height, pixels, 0, width);
return image;
}
/**
* 把传入的原始图像按高度和宽度进行缩放,生成符合要求的图标
*
* @param originalImage 源文件
* @param height 目标高度
* @param width 目标宽度
* @param hasFiller 比例不对时是否需要补白:true为补白; false为不补白;
*/
@SneakyThrows
public static BufferedImage scale(BufferedImage originalImage, int height,
int width, boolean hasFiller) {
// 缩放比例
double ratio;
Image destImage = originalImage.getScaledInstance(width, height,
Image.SCALE_SMOOTH);
// 计算比例
if ((originalImage.getHeight() > height) || (originalImage.getWidth() > width)) {
if (originalImage.getHeight() > originalImage.getWidth()) {
ratio = (double) height
/ originalImage.getHeight();
} else {
ratio = (double) width
/ originalImage.getWidth();
}
AffineTransformOp op = new AffineTransformOp(AffineTransform
.getScaleInstance(ratio, ratio), null);
destImage = op.filter(originalImage, null);
}
// 补白
if (hasFiller) {
return repairWhite(destImage, height, width);
}
return (BufferedImage) destImage;
}
@SneakyThrows
@SuppressWarnings("all")
public static void main(String[] args) {
//生成中间镶嵌图片的二维码
String content = "https://www.cnblogs.com/lyn8100/";
int width = 300;
int height = 300;
InputStream scrImageInput = new FileInputStream(new File("E:\\project\\scr.png"));
String path = "E:\\project\\";
String fileName = "testQrCode2.jpg";
writeScrQrCode(content, width, height, scrImageInput, path, fileName);
//解析二维码
// InputStream scrImageInput = new FileInputStream(new File("E:\\project\\testQrCode.jpg"));
// //"E:\\project\\testQrCode.jpg"
// System.out.println(decodeQrCode(scrImageInput));
}
}
标签:int,生成器,BufferedImage,param,height,width,二维码
From: https://www.cnblogs.com/lyn8100/p/17307313.html