liu
9 小时以前 514f372270b181f82e4deff98f8d0f38ace63183
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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;
    }
}