1
0
mirror of synced 2025-02-02 12:47:25 +01:00
bemaniutils/bemani/utils/tdxtutils.py

118 lines
2.9 KiB
Python
Raw Normal View History

#! /usr/bin/env python3
import argparse
import io
import json
import math
import os
import os.path
import sys
import textwrap
from PIL import Image, ImageDraw
from typing import Any, Dict, List, Optional, Tuple, TypeVar
from bemani.format import TDXT
def extract_texture(
fname: str,
output_fname: Optional[str],
) -> int:
with open(fname, "rb") as bfp:
tdxt = TDXT.fromBytes(bfp.read())
if output_fname is None:
output_fname = os.path.splitext(os.path.abspath(fname))[0] + ".png"
if not output_fname.lower().endswith(".png"):
raise Exception("Invalid output file format!")
# Actually place the files down.
output_dir = os.path.dirname(os.path.abspath(output_fname))
os.makedirs(output_dir, exist_ok=True)
print(f"Extracting texture from {os.path.abspath(fname)} to {os.path.abspath(output_fname)}")
with open(output_fname, "wb") as bfp:
tdxt.img.save(bfp, format="PNG")
return 0
def update_texture(
fname: str,
input_fname: str,
) -> int:
with open(fname, "rb") as bfp:
tdxt = TDXT.fromBytes(bfp.read())
if not input_fname.lower().endswith(".png"):
raise Exception("Invalid output file format!")
with open(input_fname, "rb") as bfp:
img = Image.open(io.BytesIO(bfp.read()))
tdxt.img = img
print(f"Updating texture in {os.path.abspath(fname)} from {os.path.abspath(input_fname)}")
with open(fname, "wb") as bfp:
bfp.write(tdxt.toBytes())
return 0
def main() -> int:
parser = argparse.ArgumentParser(
description="Konami TDXT graphic file unpacker/repacker."
)
subparsers = parser.add_subparsers(help="Action to take", dest="action")
unpack_parser = subparsers.add_parser(
"unpack",
help="Unpack texture data into a PNG file.",
)
unpack_parser.add_argument(
"infile",
metavar="INFILE",
help="The TDXT container to unpack the texture from.",
)
unpack_parser.add_argument(
"outfile",
metavar="OUTFILE",
nargs="?",
default=None,
help="The PNG file to unpack the texture to.",
)
update_parser = subparsers.add_parser(
"update",
help="Update texture data from a PNG file.",
)
update_parser.add_argument(
"outfile",
metavar="OUTFILE",
help="The TDXT container to update the texture to, must already exist.",
)
update_parser.add_argument(
"infile",
metavar="INFILE",
help="The PNG file to update the texture from.",
)
args = parser.parse_args()
if args.action == "unpack":
return extract_texture(
args.infile,
args.outfile,
)
elif args.action == "update":
return update_texture(
args.outfile,
args.infile,
)
else:
raise Exception(f"Invalid action {args.action}!")
if __name__ == "__main__":
sys.exit(main())