feat(platform): migrate LCD assets to PNG and expand flash partitions
This commit is contained in:
@@ -1,76 +0,0 @@
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
LCD_ROOT = Path(r"D:\Code\chaowan\lcd\main")
|
||||
OUT_DIR = ROOT / "components" / "platform" / "assets" / "lcd"
|
||||
|
||||
IMAGE_SOURCES = {
|
||||
"qianzhiwuxing": ["qianzhiwuxing0"],
|
||||
"shui": ["shui1", "shui2"],
|
||||
"mu": ["mu1", "mu2"],
|
||||
"huo": ["huo1", "huo2"],
|
||||
"tu": ["tu1", "tu2"],
|
||||
"jin": ["jin1", "jin2"],
|
||||
"caiwei": ["bei0", "dongbei0", "dong0", "dongnan0", "nan0", "xinan0", "xi0", "xibei0"],
|
||||
"chouqian_qianzhi": ["chouqianqianzhi0", "chouqianqianzhi1", "chouqianqianzhi2"],
|
||||
"chouqian_buyun": ["shangshangqian0", "buyunqian1", "buyunqian2"],
|
||||
"chouqian_heping": [None, "hepingqian1", "hepingqian2"],
|
||||
"chouqian_shangshang": [None, "shangshangqian1", "shangshangqian2"],
|
||||
"chouqian_xiaoji": [None, "xiaojiqian1", "xiaojiqian2"],
|
||||
"chouqian_zhongshang": [None, "zhongshangqian1", "zhongshangqian2"],
|
||||
}
|
||||
|
||||
|
||||
def extract_arrays(source_text):
|
||||
arrays = {}
|
||||
pattern = re.compile(
|
||||
r"static\s+const\s+(?:rle_structure_t|eye_image_frame_t)\s+([A-Za-z0-9_]+)\[\]\s*=\s*\{",
|
||||
re.MULTILINE,
|
||||
)
|
||||
for match in pattern.finditer(source_text):
|
||||
name = match.group(1)
|
||||
cursor = match.end()
|
||||
depth = 1
|
||||
while cursor < len(source_text) and depth > 0:
|
||||
if source_text[cursor] == "{":
|
||||
depth += 1
|
||||
elif source_text[cursor] == "}":
|
||||
depth -= 1
|
||||
cursor += 1
|
||||
arrays[name] = source_text[match.end(): cursor - 1]
|
||||
return arrays
|
||||
|
||||
|
||||
def parse_runs(body):
|
||||
runs = []
|
||||
for color, count in re.findall(r"\{\s*0x([0-9A-Fa-f]+)\s*,\s*(\d+)\s*\}", body):
|
||||
runs.append((int(color, 16), int(count)))
|
||||
if not runs:
|
||||
raise ValueError("no runs parsed")
|
||||
return runs
|
||||
|
||||
|
||||
def write_rle(path, runs):
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with path.open("wb") as f:
|
||||
for color, count in runs:
|
||||
f.write(struct.pack("<HH", color, count))
|
||||
|
||||
|
||||
def main():
|
||||
eye_arrays = extract_arrays((LCD_ROOT / "eye_image.c").read_text(encoding="utf-8"))
|
||||
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
for asset_dir, frames in IMAGE_SOURCES.items():
|
||||
for index, array_name in enumerate(frames):
|
||||
if array_name is None:
|
||||
continue
|
||||
write_rle(OUT_DIR / f"{asset_dir}{index}.rle", parse_runs(eye_arrays[array_name]))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,83 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Convert PNG images to standard TGA RLE image files."""
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def iter_inputs(input_path, recursive):
|
||||
if input_path.is_file():
|
||||
if input_path.suffix.lower() != ".png":
|
||||
raise SystemExit(f"input file is not a PNG: {input_path}")
|
||||
yield input_path
|
||||
return
|
||||
|
||||
pattern = "**/*.png" if recursive else "*.png"
|
||||
yield from sorted(input_path.glob(pattern))
|
||||
|
||||
|
||||
def output_path_for(input_file, input_root, output):
|
||||
if output is None:
|
||||
return input_file.with_suffix(".rle")
|
||||
|
||||
if input_root.is_file():
|
||||
return output
|
||||
|
||||
relative = input_file.relative_to(input_root)
|
||||
return (output / relative).with_suffix(".rle")
|
||||
|
||||
|
||||
def convert_file(input_file, input_root, output):
|
||||
try:
|
||||
from PIL import Image
|
||||
except ImportError as exc:
|
||||
raise SystemExit(
|
||||
"Pillow is required. Install it with: python -m pip install Pillow"
|
||||
) from exc
|
||||
|
||||
out_path = output_path_for(input_file, input_root, output)
|
||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with Image.open(input_file) as image:
|
||||
converted = image.convert("RGBA")
|
||||
width, height = converted.size
|
||||
converted.save(out_path, format="TGA", compression="tga_rle")
|
||||
print(f"{input_file} -> {out_path} ({width}x{height})")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Convert PNG files to standard TGA RLE files using Pillow.",
|
||||
)
|
||||
parser.add_argument("input", type=Path, help="PNG file or directory containing PNG files.")
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--output",
|
||||
type=Path,
|
||||
help="Output .rle file for one input file, or output directory for an input directory.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--recursive",
|
||||
action="store_true",
|
||||
help="Recursively convert PNG files when input is a directory.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
input_path = args.input.resolve()
|
||||
if not input_path.exists():
|
||||
raise SystemExit(f"input path does not exist: {input_path}")
|
||||
|
||||
output = args.output.resolve() if args.output is not None else None
|
||||
inputs = list(iter_inputs(input_path, args.recursive))
|
||||
if not inputs:
|
||||
raise SystemExit(f"no PNG files found in: {input_path}")
|
||||
|
||||
if input_path.is_file() and output is not None and output.suffix.lower() != ".rle":
|
||||
raise SystemExit("single-file output must use a .rle suffix")
|
||||
|
||||
for input_file in inputs:
|
||||
convert_file(input_file, input_path, output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user