#!/usr/bin/env python3
"""Convert bg.png into an RGB565 PROGMEM header for the display HUD.

Run with the local venv:
    ./.venv/bin/python convert.py

Output: ../display_proto/background.h
"""

from PIL import Image, ImageOps

SRC = "bg.png"
OUT = "../display_proto/background.h"

# Panel geometry (must match display_proto.ino: setRotation(0) -> 172x320).
W, H = 172, 320

# How to map a non-matching source aspect ratio onto the panel:
#   "cover"   -> fill the screen, center-crop the overflow (no bars)
#   "contain" -> show the whole image, letterbox the remainder with FLATTEN_BG
#   "stretch" -> distort to exactly WxH
FIT = "cover"

# Color that transparent pixels (and any letterbox bars) become. Black matches
# the HUD background.
FLATTEN_BG = (0, 0, 0)


def to_rgb(img):
    """Flatten any alpha channel onto FLATTEN_BG and return an RGB image."""
    img = img.convert("RGBA")
    bg = Image.new("RGBA", img.size, FLATTEN_BG + (255,))
    return Image.alpha_composite(bg, img).convert("RGB")


def fit(img):
    if FIT == "cover":
        return ImageOps.fit(img, (W, H), method=Image.LANCZOS, centering=(0.5, 0.5))
    if FIT == "contain":
        out = Image.new("RGB", (W, H), FLATTEN_BG)
        c = img.copy()
        c.thumbnail((W, H), Image.LANCZOS)
        out.paste(c, ((W - c.width) // 2, (H - c.height) // 2))
        return out
    if FIT == "stretch":
        return img.resize((W, H), Image.LANCZOS)
    raise ValueError(f"unknown FIT mode: {FIT}")


def main():
    img = fit(to_rgb(Image.open(SRC)))
    px = img.load()

    with open(OUT, "w") as f:
        f.write("// Auto-generated by bgimage/convert.py -- do not edit by hand.\n")
        f.write(f"// Source: {SRC}, fit={FIT}, {W}x{H} RGB565.\n")
        f.write("#pragma once\n#include <Arduino.h>\n\n")
        f.write(f"#define BG_WIDTH  {W}\n#define BG_HEIGHT {H}\n\n")
        f.write("const uint16_t background[BG_WIDTH * BG_HEIGHT] PROGMEM = {\n")
        for i in range(W * H):
            r, g, b = px[i % W, i // W]
            v = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)
            f.write(f"0x{v:04X},")
            f.write("\n" if (i + 1) % 12 == 0 else " ")
        f.write("\n};\n")

    print(f"Wrote {OUT}: {W}x{H} = {W * H} px ({W * H * 2} bytes in flash)")


if __name__ == "__main__":
    main()
