依賴準備
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.5.1</version>
</dependency>
生成 QR Code
public void generateQR(String content, String filePath) throws Exception {
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 1); // 邊距
BitMatrix matrix = new MultiFormatWriter()
.encode(content, BarcodeFormat.QR_CODE, 400, 400, hints);
MatrixToImageWriter.writeToPath(matrix, "PNG", Paths.get(filePath));
}
MatrixToImageWriter 輔助類(官方未打包,需自行複製)
public final class MatrixToImageWriter {
private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;
public static BufferedImage toBufferedImage(BitMatrix matrix) {
int w = matrix.getWidth(), h = matrix.getHeight();
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++)
img.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
return img;
}
public static void writeToFile(BitMatrix matrix, String format, File file) throws IOException {
if (!ImageIO.write(toBufferedImage(matrix), format, file))
throw new IOException("Could not write " + format + " to " + file);
}
public static void writeToStream(BitMatrix matrix, String format, OutputStream stream) throws IOException {
if (!ImageIO.write(toBufferedImage(matrix), format, stream))
throw new IOException("Could not write " + format);
}
public static void writeToPath(BitMatrix matrix, String format, Path path) throws IOException {
try (OutputStream os = Files.newOutputStream(path)) { writeToStream(matrix, format, os); }
}
}
解析 QR Code
public String decodeQR(String imagePath) throws Exception {
BufferedImage img = ImageIO.read(new File(imagePath));
LuminanceSource source = new BufferedImageLuminanceSource(img);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
Result result = new MultiFormatReader().decode(bitmap, hints);
return result.getText();
}
BufferedImageLuminanceSource 輔助類(官方未打包,需自行複製)
public final class BufferedImageLuminanceSource extends LuminanceSource {
private final BufferedImage image;
private final int left, top;
public BufferedImageLuminanceSource(BufferedImage image) {
this(image, 0, 0, image.getWidth(), image.getHeight());
}
public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height) {
super(width, height);
this.image = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
this.image.getGraphics().drawImage(image, 0, 0, null);
this.left = left; this.top = top;
}
@Override public byte[] getRow(int y, byte[] row) {
if (y < 0 || y >= getHeight()) throw new IllegalArgumentException();
int w = getWidth();
if (row == null || row.length < w) row = new byte[w];
image.getRaster().getDataElements(left, top + y, w, 1, row);
return row;
}
@Override public byte[] getMatrix() {
byte[] m = new byte[getWidth() * getHeight()];
image.getRaster().getDataElements(left, top, getWidth(), getHeight(), m);
return m;
}
@Override public boolean isCropSupported() { return true; }
@Override public LuminanceSource crop(int l, int t, int w, int h) {
return new BufferedImageLuminanceSource(image, left + l, top + t, w, h);
}
@Override public boolean isRotateSupported() { return true; }
@Override public LuminanceSource rotateCounterClockwise() {
int sw = image.getWidth(), sh = image.getHeight();
AffineTransform at = new AffineTransform(0, -1, 1, 0, 0, sw);
BufferedImage rot = new BufferedImage(sh, sw, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g = rot.createGraphics();
g.drawImage(image, at, null); g.dispose();
return new BufferedImageLuminanceSource(rot, top, sw - (left + getWidth()), getHeight(), getWidth());
}
}