You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

53 lines
1.6 KiB

#!/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()