44 lines
1.5 KiB
Python
44 lines
1.5 KiB
Python
"""CoCo PMODE 3: 128x192, 4 colours from one MC6847 colour set.
|
|
|
|
128 wide on a 4:3 screen -> 2:1 pixels (like C64 multicolor). The 4 colours are
|
|
fixed per CSS set (green/yellow/blue/red or buff/cyan/magenta/orange); we dither
|
|
to whichever set reproduces the image with lower error and tell the viewer which.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import numpy as np
|
|
|
|
from ... import dither
|
|
from ...convert.base import Conversion, perceptual_error
|
|
from ...palette import srgb_to_lab
|
|
from .. import palette as cpal
|
|
|
|
WIDTH, HEIGHT = 128, 192
|
|
PIXEL_ASPECT = 2.0
|
|
|
|
|
|
def convert(img_rgb, palette_name="mc6847", dither_mode="floyd",
|
|
intensive=False, base_color=None):
|
|
img_lab = srgb_to_lab(img_rgb)
|
|
allowed = np.tile(np.array([0, 1, 2, 3]), (HEIGHT, WIDTH, 1))
|
|
|
|
best = None
|
|
for vdg, rgb in cpal.PMODE3_SETS.items():
|
|
plab = srgb_to_lab(rgb)
|
|
idx = dither.quantize(img_lab, allowed, plab, dither_mode).astype(np.uint8)
|
|
err = perceptual_error(idx, img_lab, plab)
|
|
if best is None or err < best[0]:
|
|
best = (err, vdg, rgb, plab, idx)
|
|
|
|
err, vdg, rgb, plab, idx = best
|
|
data = cpal.pack_pmode3(idx) # 6144-byte video buffer
|
|
preview = rgb.astype(np.uint8)[idx]
|
|
|
|
return Conversion(
|
|
mode="pmode3", width=WIDTH, height=HEIGHT, pixel_aspect=PIXEL_ASPECT,
|
|
index_image=idx.astype(np.uint16), data=data, data_addr=0,
|
|
viewer="pmode3", preview_rgb=preview,
|
|
error=err,
|
|
meta={"palette": "mc6847", "dither": dither_mode, "vdg": vdg},
|
|
)
|