8bitlenser/lenser/iigs/palette.py
2026-07-03 19:35:35 -07:00

31 lines
1.2 KiB
Python

"""Apple IIGS Super Hi-Res colour helpers.
SHR colours are 12-bit ``$0RGB`` -- 4 bits per channel, each level scaled x17
(0->0, 15->255), exactly as MAME's apple2gs palette. There is no fixed master
palette: each of the 16 line-palettes holds 16 freely chosen 12-bit colours, so
the encoder works in the continuous 4096-colour space and quantises to 12-bit.
"""
from __future__ import annotations
import numpy as np
def quantize12(rgb):
"""Snap an RGB array (..,3) float 0-255 to the nearest 12-bit SHR colour."""
q4 = np.clip(np.rint(np.asarray(rgb) / 17.0), 0, 15).astype(np.int64)
return q4 * 17, q4 # (rgb 0..255 in x17 steps, 4-bit)
def color_word(r4: int, g4: int, b4: int) -> bytes:
"""16-bit little-endian SHR palette entry: low = (G<<4)|B, high = $0R."""
lo = ((g4 & 0x0F) << 4) | (b4 & 0x0F)
hi = r4 & 0x0F
return bytes([lo, hi])
def greys12(n: int = 16):
"""``n`` evenly spaced 12-bit greys, black..white (RGB array, 4-bit array)."""
lv4 = np.clip(np.rint(np.linspace(0, 15, n)), 0, 15).astype(np.int64)
rgb = np.stack([lv4 * 17] * 3, axis=1).astype(np.float64)
q4 = np.stack([lv4] * 3, axis=1)
return rgb, q4