Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_graphics/tests/png/gen.py

2.5 KiB, 1 run

created by r1870400018:14157, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1#!/usr/bin/env python3
2"""Generate tRNS-bearing PNGs with PIL, and record what PIL says each pixel means.
3
4PIL writes the files and PIL says what they decode to. Our decoder is not consulted,
5so agreeing with this file is agreement with an implementation that is not ours.
6"""
7import json
8import os
9
10from PIL import Image, ImagePalette
11
12OUT = os.path.dirname(os.path.abspath(__file__))
13cases = {}
14
15
16def record(name, img):
17 """Write the PNG, then record PIL's own RGBA reading of it."""
18 path = os.path.join(OUT, name + ".png")
19 img.save(path)
20 # Re-open from disk, so we record what the *file* says, not what we held in memory.
21 reopened = Image.open(path).convert("RGBA")
22 w, h = reopened.size
23 cases[name] = {
24 "w": w,
25 "h": h,
26 "rgba": [list(px) for px in reopened.getdata()],
27 }
28
29
30# 1. Palette image with a tRNS chunk: per-entry alpha, some fully transparent.
31pal_img = Image.new("P", (4, 4))
32palette = []
33for i in range(256):
34 palette += [(i * 7) % 256, (i * 13) % 256, (i * 29) % 256]
35pal_img.putpalette(palette)
36pal_img.putdata([0, 1, 2, 3] * 4)
37# Entry 0 fully transparent, entry 1 half, entries 2+ opaque.
38pal_img.info["transparency"] = bytes([0, 128, 255, 255])
39record("palette_trns", pal_img)
40
41# 2. Greyscale image with a tRNS chunk: one luminance value is the transparent one.
42grey = Image.new("L", (4, 4))
43grey.putdata([0, 64, 128, 255] * 4)
44grey.info["transparency"] = 128 # Every pixel of luminance 128 is transparent.
45record("grey_trns", grey)
46
47# 3. Truecolour image with a tRNS chunk: one RGB triple is the transparent one.
48rgb = Image.new("RGB", (4, 4))
49rgb.putdata([(255, 0, 0), (0, 255, 0), (0, 0, 255), (10, 20, 30)] * 4)
50rgb.info["transparency"] = (0, 255, 0) # Every pure-green pixel is transparent.
51record("rgb_trns", rgb)
52
53# 4. Controls: images with no tRNS at all must stay fully opaque.
54plain_rgb = Image.new("RGB", (4, 4))
55plain_rgb.putdata([(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12)] * 4)
56record("rgb_plain", plain_rgb)
57
58rgba = Image.new("RGBA", (4, 4))
59rgba.putdata([(1, 2, 3, 0), (4, 5, 6, 85), (7, 8, 9, 170), (10, 11, 12, 255)] * 4)
60record("rgba_plain", rgba)
61
62with open(os.path.join(OUT, "expected.json"), "w") as f:
63 json.dump(cases, f, indent=1)
64
65print("wrote {} cases: {}".format(len(cases), ", ".join(sorted(cases))))
66for name, c in sorted(cases.items()):
67 alphas = [px[3] for px in c["rgba"]]
68 print(" {:14s} transparent px = {:2d}/{:2d}".format(
69 name, sum(1 for a in alphas if a == 0), len(alphas)))