45 lines
1.4 KiB
Python
45 lines
1.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Unpacks Argonaut .cor images (Ein Königreich für ein Lama) to PNG.
|
|
|
|
Layout: 8-byte signature 17 98 AF 89 FE 42 D1 12, u32 version (1),
|
|
u32 unpacked size, u32 packed size, then LZ data:
|
|
n < 0x80 -> n bytes of raw data follow
|
|
1LLL oooo oooooooo -> copy L+3 bytes from o bytes back
|
|
The result is 640x480 pixels at 3 bytes (RGB) or 1 byte (greyscale, e.g. 151.cor).
|
|
Usage: cor2png.py input.cor output.png (requires Pillow)
|
|
"""
|
|
import struct
|
|
import sys
|
|
|
|
MAGIC = bytes.fromhex('1798af89fe42d112')
|
|
|
|
|
|
def unpack(data):
|
|
if data[:8] != MAGIC:
|
|
raise ValueError('not a COR file')
|
|
_, size, packed = struct.unpack_from('<III', data, 8)
|
|
src = data[20:20 + packed]
|
|
out = bytearray()
|
|
i = 0
|
|
while i < len(src) and len(out) < size:
|
|
b = src[i]
|
|
if b < 0x80:
|
|
out += src[i + 1:i + 1 + b]
|
|
i += 1 + b
|
|
else:
|
|
length = ((b >> 4) & 7) + 3
|
|
off = ((b & 0x0F) << 8) | src[i + 1]
|
|
i += 2
|
|
for _ in range(length):
|
|
out.append(out[-off])
|
|
return bytes(out), size
|
|
|
|
|
|
if __name__ == '__main__':
|
|
raw, size = unpack(open(sys.argv[1], 'rb').read())
|
|
print(f'{sys.argv[1]}: {len(raw)} of {size} bytes')
|
|
if len(sys.argv) > 2:
|
|
from PIL import Image
|
|
mode = {640 * 480 * 3: 'RGB', 640 * 480: 'L'}[size]
|
|
Image.frombytes(mode, (640, 480), raw).save(sys.argv[2])
|