02202e4d3d
- Added `image_clean.png` to the output directory for the clean image representation. - Added `image_clean_preview.png` for the preview of the clean image. - Introduced `image_svg_clean.png` for the SVG clean image representation.
53 lines
1.6 KiB
Python
53 lines
1.6 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from PIL import Image
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(
|
|
description="Convert a JSON RGBA matrix back into a PNG image."
|
|
)
|
|
parser.add_argument("input_json", type=Path, help="Source JSON path")
|
|
parser.add_argument("output_png", type=Path, help="Destination PNG path")
|
|
return parser.parse_args()
|
|
|
|
|
|
def load_matrix(json_path: Path) -> tuple[int, int, list[tuple[int, int, int, int]]]:
|
|
data = json.loads(json_path.read_text(encoding="utf-8"))
|
|
width = int(data["width"])
|
|
height = int(data["height"])
|
|
rows = data["pixels"]
|
|
|
|
if len(rows) != height:
|
|
raise ValueError(f"Expected {height} rows, found {len(rows)}")
|
|
|
|
flat_pixels: list[tuple[int, int, int, int]] = []
|
|
for row_index, row in enumerate(rows):
|
|
if len(row) != width:
|
|
raise ValueError(
|
|
f"Expected row {row_index} to contain {width} pixels, found {len(row)}"
|
|
)
|
|
for pixel in row:
|
|
if len(pixel) != 4:
|
|
raise ValueError("Each pixel must contain 4 RGBA channels")
|
|
flat_pixels.append(tuple(int(channel) for channel in pixel))
|
|
|
|
return width, height, flat_pixels
|
|
|
|
|
|
def main() -> None:
|
|
args = parse_args()
|
|
width, height, pixels = load_matrix(args.input_json)
|
|
image = Image.new("RGBA", (width, height))
|
|
image.putdata(pixels)
|
|
args.output_png.parent.mkdir(parents=True, exist_ok=True)
|
|
image.save(args.output_png, format="PNG")
|
|
print(f"Wrote {args.output_png} with {width}x{height} RGBA pixels")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |