adeed manual processing using UVtools

This commit is contained in:
cpu
2026-06-12 13:36:22 +02:00
parent a731b064b6
commit 9a8635aa98
11 changed files with 340 additions and 38 deletions

71
diagnose/decode_prev.py Normal file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/env python3
"""
Decode the PREV (preview thumbnail) section from a pm4n file and save as PNG.
Run: python3 decode_prev.py <file.pm4n>
"""
import struct, sys
from pathlib import Path
path = sys.argv[1]
data = open(path, 'rb').read()
prev_off = data.find(b'PREV')
print(f"PREV at 0x{prev_off:06X}")
# PREV section layout (from ANYCUBIC format docs and common reverse-engineering):
# +0x00 "PREV"
# +0x04 u32 section_length
# +0x08 u32 image_width
# +0x0C u32 image_height
# +0x10 u32 image_data_length
# +0x14 image data (RGB565 or RLE)
for hdr_size in [0x14, 0x18, 0x10, 0x0C]:
w = struct.unpack_from('<I', data, prev_off + 0x08)[0]
h = struct.unpack_from('<I', data, prev_off + 0x0C)[0]
dlen = struct.unpack_from('<I', data, prev_off + 0x10)[0]
print(f" PREV+0x08: w={w}, h={h}, dlen={dlen}")
if 100 < w < 2000 and 100 < h < 2000:
print(f" -> plausible dimensions {w}x{h}, data at +0x14, {dlen} bytes")
break
# Show first 64 bytes of PREV section
print(f"\nPREV raw (first 64 bytes):")
chunk = data[prev_off:prev_off+64]
for i in range(0, 64, 16):
row = chunk[i:i+16]
hex_p = ' '.join(f'{b:02X}' for b in row)
u_vals = [struct.unpack_from('<I', row, j)[0] for j in range(0, min(16,len(row))-3, 4)]
print(f" +0x{i:02X} {hex_p:<48} {u_vals}")
# Try to decode as RGB565 (common for ANYCUBIC previews)
# Each pixel = 2 bytes, little-endian RGB565
# R = bits[15:11], G = bits[10:5], B = bits[4:0]
img_data_off = prev_off + 0x14
img_data_len = struct.unpack_from('<I', data, prev_off + 0x10)[0]
w = struct.unpack_from('<I', data, prev_off + 0x08)[0]
h = struct.unpack_from('<I', data, prev_off + 0x0C)[0]
print(f"\nAttempting RGB565 decode: {w}x{h}, {img_data_len} bytes at 0x{img_data_off:06X}")
if 0 < w < 2000 and 0 < h < 2000 and img_data_len == w * h * 2:
print(f" Size matches RGB565 ({w}*{h}*2={w*h*2}) ✓")
try:
from PIL import Image
pixels = []
raw = data[img_data_off:img_data_off + img_data_len]
for i in range(0, len(raw)-1, 2):
px = raw[i] | (raw[i+1] << 8)
r = ((px >> 11) & 0x1F) << 3
g = ((px >> 5) & 0x3F) << 2
b = (px & 0x1F) << 3
pixels.append((r, g, b))
img = Image.new('RGB', (w, h))
img.putdata(pixels)
out = Path(path).with_suffix('.prev_thumb.png')
img.save(out)
print(f" Saved thumbnail to {out}")
except Exception as e:
print(f" Error: {e}")
else:
print(f" Size mismatch or bad dims, skipping decode")
print(f" Expected {w*h*2} bytes for RGB565, got {img_data_len}")