Files
llamamod/tools/png2cor.py
T

69 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Packt ein Bild als Argonaut-.cor (Gegenstück zu cor2png.py).
Das Bild wird auf 640x480 RGB gebracht und mit dem LZ-Schema des Spiels
komprimiert:
n < 0x80 -> n Bytes Rohdaten folgen (n = 1..127)
1LLL oooo oooooooo -> kopiere L+3 Bytes (3..10) ab o Bytes (1..4095) zurück
Aufruf: png2cor.py eingabe.png ausgabe.cor (benötigt Pillow)
"""
import struct
import sys
MAGIC = bytes.fromhex('1798af89fe42d112')
MAXOFF, MINLEN, MAXLEN = 0x0FFF, 3, 10
def pack(raw):
out = bytearray()
lit = bytearray()
last = {} # 3-Byte-Präfix -> Liste letzter Positionen
def flush():
for k in range(0, len(lit), 127):
part = lit[k:k + 127]
out.append(len(part))
out.extend(part)
lit.clear()
i, n = 0, len(raw)
while i < n:
best_len, best_off = 0, 0
if i + MINLEN <= n:
key = raw[i:i + 3]
for p in reversed(last.get(key, ())):
off = i - p
if off > MAXOFF:
break
ln = 3
while ln < MAXLEN and i + ln < n and raw[p + ln] == raw[i + ln]:
ln += 1
if ln > best_len:
best_len, best_off = ln, off
if ln == MAXLEN:
break
step = best_len if best_len >= MINLEN else 1
for j in range(i, min(i + step, n - 2)):
lst = last.setdefault(raw[j:j + 3], [])
lst.append(j)
if len(lst) > 16:
del lst[0]
if best_len >= MINLEN:
flush()
out.append(0x80 | ((best_len - 3) << 4) | (best_off >> 8))
out.append(best_off & 0xFF)
i += best_len
else:
lit.append(raw[i])
i += 1
flush()
return MAGIC + struct.pack('<III', 1, len(raw), len(out)) + bytes(out)
if __name__ == '__main__':
from PIL import Image
img = Image.open(sys.argv[1]).convert('RGB').resize((640, 480), Image.LANCZOS)
data = pack(img.tobytes())
open(sys.argv[2], 'wb').write(data)
print(f'{sys.argv[2]}: {len(data)} Bytes')