"""CoCo 3 GIME monochrome: 640x192, 2 colours (black + white) -- the highest- resolution CoCo 3 mode, tone carried by dithering. ``--mono-base`` tints the second tone.""" from __future__ import annotations import numpy as np from ... import dither, palette as c64pal from ...convert.base import Conversion, perceptual_error from .. import palette as g from . import _common WIDTH, HEIGHT = 640, 192 PIXEL_ASPECT = 0.5 CRES = 0 def convert(img_rgb, palette_name="gime", dither_mode="floyd", intensive=False, base_color=None): plab = g.palette_lab() black = min(g.GREYS, key=lambda i: plab[i, 0]) if base_color in range(64) and base_color != black: ramp = sorted({black, int(base_color)}, key=lambda i: plab[i, 0]) else: ramp = sorted(g.GREYS, key=lambda i: plab[i, 0]) ramp = [ramp[0], ramp[-1]] # black + white img_lab = c64pal.srgb_to_lab(img_rgb) mono_lab = np.zeros_like(img_lab); mono_lab[..., 0] = img_lab[..., 0] plab_mono = np.zeros_like(plab); plab_mono[:, 0] = plab[:, 0] allowed = np.tile(np.array(ramp), (*mono_lab.shape[:2], 1)) idx = dither.quantize(mono_lab, allowed, plab_mono, dither_mode).astype(np.int64) lut = {p: k for k, p in enumerate(ramp)} pen = np.vectorize(lut.get)(idx).astype(np.uint8) screen = _common.PACK[CRES](pen) prgb = g.get_palette().astype(np.uint8) return Conversion( mode="mono", width=WIDTH, height=HEIGHT, pixel_aspect=PIXEL_ASPECT, index_image=idx.astype(np.uint16), data=screen, data_addr=0x4000, viewer="coco3", preview_rgb=prgb[idx.astype(np.uint16)], error=perceptual_error(idx, mono_lab, plab_mono), meta={"palette": "gime", "dither": dither_mode, "cres": CRES, "inks": ramp, "border": ramp[0]}, )