forked from tsuki/openroller
40 lines
1.3 KiB
Python
Executable File
40 lines
1.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import struct
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Convert a GC menu DDS jacket to PSP RGBA4444")
|
|
parser.add_argument("input_dds")
|
|
parser.add_argument("output_orpj")
|
|
args = parser.parse_args()
|
|
|
|
command = [
|
|
"ffmpeg", "-hide_banner", "-loglevel", "error", "-i", args.input_dds,
|
|
"-vf", "crop=197:197:0:0,scale=128:128:flags=lanczos",
|
|
"-frames:v", "1", "-f", "rawvideo", "-pix_fmt", "rgba", "-",
|
|
]
|
|
result = subprocess.run(command, stdout=subprocess.PIPE, check=False)
|
|
expected = 128 * 128 * 4
|
|
if result.returncode != 0 or len(result.stdout) != expected:
|
|
raise SystemExit(f"ffmpeg produced {len(result.stdout)} bytes, expected {expected}")
|
|
|
|
pixels = bytearray(128 * 128 * 2)
|
|
for index in range(128 * 128):
|
|
r, g, b, a = result.stdout[index * 4:index * 4 + 4]
|
|
value = (r >> 4) | ((g >> 4) << 4) | ((b >> 4) << 8) | ((a >> 4) << 12)
|
|
struct.pack_into("<H", pixels, index * 2, value)
|
|
|
|
output = Path(args.output_orpj)
|
|
output.parent.mkdir(parents=True, exist_ok=True)
|
|
header = struct.pack("<4sHHHHI", b"ORPJ", 1, 128, 128, 0, len(pixels))
|
|
output.write_bytes(header + pixels)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|