krz/krz.sh
clone: git clone https://gitbay.org/krz/krz.sh.git
1#!/usr/bin/env python3
2"""Render the krz frame mark to RGBA PNG at exact integer pixel boundaries."""
3import struct, zlib, sys
4
5GRID = 32
6# (x, y, w, h) in grid units
7FRAME = [(4, 4, 24, 4), (4, 24, 24, 4), (4, 8, 4, 16), (24, 8, 4, 16)]
8BLOCK = (12, 12, 8, 8)
9
10INKS = {
11 "dark": ("#17171a", "#2f6bd6"), # for light backgrounds
12 "light": ("#f1f1ef", "#6f9dff"), # for dark backgrounds
13}
14
15
16def rgba(hexstr):
17 h = hexstr.lstrip("#")
18 return (int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16), 255)
19
20
21def chunk(tag, data):
22 return (struct.pack(">I", len(data)) + tag + data
23 + struct.pack(">I", zlib.crc32(tag + data) & 0xFFFFFFFF))
24
25
26def render(size, fg_hex, ac_hex, path):
27 if size % GRID:
28 sys.exit(f"size {size} must be a multiple of {GRID}")
29 s = size // GRID
30 fg, ac = rgba(fg_hex), rgba(ac_hex)
31 # transparent canvas
32 px = bytearray(size * size * 4)
33
34 def fill(rect, color):
35 x, y, w, h = (v * s for v in rect)
36 row = bytes(color) * w
37 for yy in range(y, y + h):
38 off = (yy * size + x) * 4
39 px[off:off + w * 4] = row
40
41 for r in FRAME:
42 fill(r, fg)
43 fill(BLOCK, ac)
44
45 # filter byte 0 per scanline
46 raw = b"".join(b"\x00" + bytes(px[r * size * 4:(r + 1) * size * 4])
47 for r in range(size))
48 png = (b"\x89PNG\r\n\x1a\n"
49 + chunk(b"IHDR", struct.pack(">IIBBBBB", size, size, 8, 6, 0, 0, 0))
50 + chunk(b"IDAT", zlib.compress(raw, 9))
51 + chunk(b"IEND", b""))
52 with open(path, "wb") as f:
53 f.write(png)
54 return len(png)
55
56
57if __name__ == "__main__":
58 for name, (fg, ac) in INKS.items():
59 for size in (1024, 512):
60 p = f"krz-mark-{size}-{name}.png"
61 n = render(size, fg, ac, p)
62 print(f"{p:28} {size}x{size} {n:,}b")