import com.google.zxing.BarcodeFormat;
|
import com.google.zxing.EncodeHintType;
|
import com.google.zxing.common.BitMatrix;
|
import com.google.zxing.qrcode.QRCodeWriter;
|
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
|
import javax.imageio.ImageIO;
|
import java.awt.image.BufferedImage;
|
import java.io.File;
|
import java.util.EnumMap;
|
import java.util.Map;
|
|
/**
|
* 判定"解不开的标签"到底是标签坏了,还是解码器的局限
|
*
|
* 用法:java CompareQrRender <标签目录> <文件名1> [文件名2 ...]
|
*
|
* 做法:用与导出完全相同的编码参数(纠错级别 H、静区 4、边长 260)重新生成同一码值的二维码,
|
* 再与标签图片中的二维码区域逐像素比对。
|
* - 完全一致 → 标签是该码值的忠实渲染,二维码数据有效,解不出是解码器的问题
|
* - 存在差异 → 标签渲染环节确实出了问题
|
*/
|
public class CompareQrRender {
|
|
/** 与 QrCodeImageUtils 保持一致 */
|
private static final int PADDING = 16;
|
private static final int QR_SIZE = 260;
|
/** 与 MesProQrLabelBuilder 一致:二维码内容为追溯网址 + code 参数 */
|
private static final String TRACE_BASE = "http://192.168.0.10:48080/trace.html";
|
|
public static void main(String[] args) throws Exception {
|
File dir = new File(args[0]);
|
for (int i = 1; i < args.length; i++) {
|
File f = new File(dir, args[i]);
|
String name = args[i];
|
String code = name.endsWith(".png") ? name.substring(0, name.length() - 4) : name;
|
BufferedImage label = ImageIO.read(f);
|
if (label == null) {
|
System.out.println(name + " -> 无法读取");
|
continue;
|
}
|
BufferedImage expect = generate(code);
|
BufferedImage actual = label.getSubimage(PADDING, PADDING, QR_SIZE, QR_SIZE);
|
if (expect.getWidth() != actual.getWidth() || expect.getHeight() != actual.getHeight()) {
|
System.out.println(name + " -> 尺寸不一致,无法比对");
|
continue;
|
}
|
long diff = 0;
|
for (int y = 0; y < QR_SIZE; y++) {
|
for (int x = 0; x < QR_SIZE; x++) {
|
if (expect.getRGB(x, y) != actual.getRGB(x, y)) {
|
diff++;
|
}
|
}
|
}
|
long total = (long) QR_SIZE * QR_SIZE;
|
System.out.printf("%s%n 重新生成与标签二维码区域逐像素比对:不一致 %d / %d (%.4f%%)%n",
|
name, diff, total, diff * 100.0 / total);
|
System.out.println(" 判定:" + (diff == 0
|
? "标签为该码值的忠实渲染 → 二维码数据有效,解不出属解码端问题"
|
: "标签渲染与预期不符 → 渲染环节存在问题"));
|
}
|
}
|
|
private static BufferedImage generate(String code) throws Exception {
|
String content = TRACE_BASE + "?code=" + code;
|
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
|
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
|
hints.put(EncodeHintType.MARGIN, 4);
|
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
BitMatrix matrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, QR_SIZE, QR_SIZE, hints);
|
int w = matrix.getWidth();
|
int h = matrix.getHeight();
|
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
|
for (int y = 0; y < h; y++) {
|
for (int x = 0; x < w; x++) {
|
img.setRGB(x, y, matrix.get(x, y) ? 0x000000 : 0xFFFFFF);
|
}
|
}
|
return img;
|
}
|
}
|