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); } }