Files
ZXCLI 948c9d5d3d tools: 照片差异定位三件套(帧剖面 / NUC 直出 / 条纹量化)+ 忽略 .tmp-* 对比目录
为"我们的照片与官方照片到底差在哪"提供可量化的手段,而不是靠肉眼看图:

- FrameProfile:对 160x120 载荷算行/列均值的步进与 3 抽头高频,并给出
  「列高频 / 行高频」比值——列固定图案噪声会表现为该比值显著 >1,场景内容则接近 1。
  同时对压缩块与"官方布局"(DDT 头 + 884B BasePara + 帧)都能定位载荷。
- NucDump:把 NUC 块按线性映射直出 PNG,用来判断成品图里的结构是"数据里有"
  还是"显示级引入的"。
- StripeCheck:在成品图的平坦区域量列抖动,并给出它占局部量程的百分比。

实测结论(本轮):我们的原始帧列高频 675 counts(列噪声主导,符合未校正预期),
而我们的 NUC 块只有 4.1 counts、行/列比 1.25,且成品图上平坦区列抖动仅为局部量程的
0.1% —— 即**校正后没有残留列噪声**,肉眼以为的竖纹是场景纹理。官方的成品帧(其文件
存的是校正后数据)同样干净(colHF 5.5、比值 1.39),两边校正质量等价。

.tmp-*/ 加入忽略:对比用的用户照片与中间产物放在那里,不入库。
2026-10-06 00:46:27 +08:00

37 lines
1.7 KiB
Java

import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.Files;
import javax.imageio.ImageIO;
/** Render a 160x120 payload (NUC block) with a straight linear map, to see whether
* structure in the final JPEG is in the DATA or added by the display stage. */
public class NucDump {
public static void main(String[] a) throws Exception {
byte[] b = Files.readAllBytes(new File(a[0]).toPath());
ByteBuffer bb = ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN);
int t = b.length - 152, ddt = bb.getInt(t + 4), bodySize = bb.getInt(ddt + 4);
int p = ddt + 0x88, end = p + bodySize, off = -1;
while (p + 8 <= end) {
int m = bb.getInt(p), len = bb.getInt(p + 4);
if (len < 0 || p + 8 + len > end) break;
if (m == 0x5BB5B560 && len >= 38400) { off = p + 8; break; }
p += 8 + len;
}
if (off < 0) { System.out.println("no NUC block"); return; }
int W = 160, H = 120;
int[] v = new int[W * H];
for (int i = 0; i < W * H; i++) v[i] = (b[off + 2 * i] & 0xFF) | ((b[off + 2 * i + 1] & 0xFF) << 8);
int lo = Integer.MAX_VALUE, hi = Integer.MIN_VALUE;
for (int x : v) { if (x < lo) lo = x; if (x > hi) hi = x; }
BufferedImage im = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < H; y++)
for (int x = 0; x < W; x++) {
int g = (int) Math.round(255.0 * (v[y * W + x] - lo) / Math.max(1, hi - lo));
im.setRGB(x, y, (g << 16) | (g << 8) | g);
}
ImageIO.write(im, "png", new File(a[1]));
System.out.println("wrote " + a[1] + " range " + lo + ".." + hi);
}
}