#!/usr/bin/env python3 """Preview the exact Ch437 separable-linear SH3 scanout map.""" import math import sys from PIL import Image def blend(a, b, frac, denom): return tuple(((denom - frac) * x + frac * y + denom // 2) // denom for x, y in zip(a, b)) def score(a, b): ae = 0 se = 0 n = a.width * a.height * 3 for pa, pb in zip(a.getdata(), b.getdata()): for ca, cb in zip(pa, pb): d = int(ca) - int(cb) ae += abs(d) se += d * d return ae / n, math.sqrt(se / n) def main(argv): if len(argv) != 4: raise SystemExit( "usage: preview_scanout_ch437.py " ) src = Image.open(argv[1]).convert("RGB") if src.size != (640, 480): raise SystemExit(f"expected 640x480 framebuffer, got {src.size}") ref = Image.open(argv[2]).convert("RGB").resize( (640, 480), Image.Resampling.BILINEAR ) out = Image.new("RGB", (640, 480)) px = out.load() for y in range(480): yn = y * 14 y0 = 32 + yn // 15 yf = yn % 15 y1 = min(y0 + 1, 479) for x in range(640): xn = x * 4 x0 = xn // 5 xf = xn % 5 x1 = min(x0 + 1, 511) left = blend(src.getpixel((x0, y0)), src.getpixel((x0, y1)), yf, 15) right = blend(src.getpixel((x1, y0)), src.getpixel((x1, y1)), yf, 15) px[x, y] = blend(left, right, xf, 5) out.save(argv[3]) mae, rmse = score(out, ref) print(f"bilinear MAE={mae:.4f} RMSE={rmse:.4f}") print(f"wrote {argv[3]}") if __name__ == "__main__": main(sys.argv)