adeed manual processing using UVtools
This commit is contained in:
76
diagnose/decode_rle_blocks.py
Normal file
76
diagnose/decode_rle_blocks.py
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Decode the composite block and first layer block from a pm4n file,
|
||||
report pixel counts and first/last pixel values.
|
||||
Run: python3 decode_rle_blocks.py output/pm4n/Flow_Controller_Panel-Front.pm4n
|
||||
"""
|
||||
import struct, sys
|
||||
|
||||
path = sys.argv[1]
|
||||
data = open(path, 'rb').read()
|
||||
fsize = len(data)
|
||||
print(f"File: {path} ({fsize} bytes)\n")
|
||||
|
||||
LAYE_HDR = 0x20
|
||||
STRIDE = 0x20
|
||||
|
||||
laye = data.find(b'LAYE')
|
||||
n_entries = struct.unpack_from('<I', data, laye + 0x10)[0]
|
||||
composite_off = struct.unpack_from('<I', data, laye + 0x14)[0]
|
||||
block_size = struct.unpack_from('<I', data, laye + 0x18)[0]
|
||||
|
||||
print(f"LAYE n_entries={n_entries} composite_off=0x{composite_off:06X} block_size={block_size}")
|
||||
|
||||
def decode_rle(data, offset, max_bytes):
|
||||
"""Decode RLE starting at offset, stop after max_bytes read. Returns pixel list."""
|
||||
pixels = []
|
||||
i = offset
|
||||
end = min(offset + max_bytes, len(data))
|
||||
while i + 1 < end:
|
||||
b0 = data[i]; b1 = data[i+1]
|
||||
nibble = (b0 >> 4) & 0xF
|
||||
colour = 255 if nibble == 0xF else 0
|
||||
run = ((b0 & 0x0F) << 8) | b1
|
||||
run += 1
|
||||
pixels.extend([colour] * run)
|
||||
i += 2
|
||||
return pixels, i - offset
|
||||
|
||||
def summarize_block(name, offset, size):
|
||||
print(f"\n{name} at 0x{offset:06X}, {size} bytes:")
|
||||
if offset + size > fsize:
|
||||
print(f" *** PAST EOF (file ends at 0x{fsize:06X}) ***")
|
||||
size = max(0, fsize - offset)
|
||||
|
||||
# Show first 16 bytes raw
|
||||
raw = data[offset:offset+16]
|
||||
print(f" First 16 bytes: {raw.hex()}")
|
||||
|
||||
# Decode RLE
|
||||
pixels, bytes_consumed = decode_rle(data, offset, size)
|
||||
print(f" Decoded: {len(pixels)} pixels from {bytes_consumed} bytes")
|
||||
print(f" Expected: {9024*5120} pixels ({9024}×{5120})")
|
||||
|
||||
if pixels:
|
||||
whites = sum(1 for p in pixels if p >= 128)
|
||||
blacks = len(pixels) - whites
|
||||
print(f" White px: {whites} ({100*whites/len(pixels):.1f}%)")
|
||||
print(f" Black px: {blacks} ({100*blacks/len(pixels):.1f}%)")
|
||||
|
||||
# Check if it decodes to correct pixel count
|
||||
if len(pixels) == 9024 * 5120:
|
||||
print(f" ✓ Correct pixel count")
|
||||
else:
|
||||
print(f" *** WRONG pixel count (off by {len(pixels) - 9024*5120})")
|
||||
|
||||
# Show first few runs
|
||||
print(f" First pixels: {pixels[:20]}")
|
||||
|
||||
# Composite block
|
||||
summarize_block("Composite block (block 0)", composite_off, block_size)
|
||||
|
||||
# First entry block
|
||||
e0_base = laye + LAYE_HDR
|
||||
e0_data_off = struct.unpack_from('<I', data, e0_base + 0x14)[0]
|
||||
e0_data_sz = struct.unpack_from('<I', data, e0_base + 0x18)[0]
|
||||
summarize_block("Entry[0] block", e0_data_off, e0_data_sz)
|
||||
Reference in New Issue
Block a user