47 lines
2 KiB
Python
47 lines
2 KiB
Python
"""CPC monochrome: Mode 2, 640x200, 2 colours (black + bright white) -- the
|
|
highest-resolution CPC mode, tone carried by dithering. ``--mono-base`` tints
|
|
the second tone to a chosen hue."""
|
|
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 cpcpal
|
|
from . import _common
|
|
|
|
WIDTH, HEIGHT = 640, 200
|
|
PIXEL_ASPECT = 0.5 # 640x200 on a 4:3 screen -> pixels half as wide
|
|
NCOL = 2
|
|
|
|
|
|
def convert(img_rgb, palette_name="cpc", dither_mode="floyd",
|
|
intensive=False, base_color=None):
|
|
plab = cpcpal.palette_lab()
|
|
# black + the lightest tone (bright white), or black + a tint
|
|
black = min(cpcpal.GREYS, key=lambda i: plab[i, 0])
|
|
if base_color in range(len(cpcpal.PALETTE)) and base_color != black:
|
|
ramp = sorted({black, int(base_color)}, key=lambda i: plab[i, 0])
|
|
else:
|
|
ramp = sorted(cpcpal.GREYS, key=lambda i: plab[i, 0])
|
|
ramp = [ramp[0], ramp[-1]] # black + brightest grey
|
|
# collapse to luminance so the two tones bracket the image's lightness
|
|
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)
|
|
inks = [cpcpal.ink_byte(p) for p in ramp]
|
|
|
|
screen = _common.PACK[2](pen)
|
|
prgb = cpcpal.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=0xC000,
|
|
viewer="cpc", preview_rgb=prgb[idx.astype(np.uint16)],
|
|
error=perceptual_error(idx, mono_lab, plab_mono),
|
|
meta={"palette": "cpc", "dither": dither_mode, "cpc_mode": 2, "inks": inks},
|
|
)
|