Files
kicad2msla/diagnose/decode_rle_blocks.py

76 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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)