krz/krz.sh

clone: git clone https://gitbay.org/krz/krz.sh.git

main: assets/mark.py · raw

 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")