"""app.html_render's shared ordered-dithering primitives -- ordered_dither and ordered_dither_regions -- exercised directly against synthetic images, no Chromium/Playwright involved (these two functions run purely on whatever Image render_html_to_image already handed back).""" from __future__ import annotations from PIL import Image from app import html_render from app.image_pipeline import DEFAULT_PALETTE_RGB _PALETTE = set(DEFAULT_PALETTE_RGB) # A muddy hue nowhere near any of the 6 exact palette colors -- at the # "modern" style's tuned default amplitude (48), this should still snap # flatly to a single nearest ink (see theme_tokens.py's module docstring # for why 48 was chosen for icon/text legibility); only a much higher # amplitude (as a rich theme's accent_amplitude would use) stipples it # into a multi-ink approximation. _RICH_HUE = (168, 75, 42) # a terracotta-ish RGB, not one of the 6 inks def test_ordered_dither_output_is_exact_palette_colors(): img = Image.new("RGB", (40, 30), (128, 128, 128)) dithered = html_render.ordered_dither(img, None) assert set(dithered.getdata()) <= _PALETTE def test_ordered_dither_regions_outside_the_region_matches_plain_dither(): """Pixels outside every accent_regions rect must come out identical to a plain ordered_dither call at base_amplitude -- the region-aware variant must not perturb anything it wasn't asked to.""" img = Image.new("RGB", (100, 80), (90, 140, 200)) base_only = html_render.ordered_dither(img, None, amplitude=48.0) regions = html_render.ordered_dither_regions( img, None, base_amplitude=48.0, accent_regions=[((10, 10, 40, 30), 130.0)] ) for x in range(100): for y in range(80): if 10 <= x < 40 and 10 <= y < 30: continue # inside the accent region -- expected to differ assert regions.getpixel((x, y)) == base_only.getpixel((x, y)) def test_ordered_dither_regions_stipples_a_rich_hue_the_base_amplitude_would_flatten(): """The whole reason ordered_dither_regions exists: a rich accent hue dithered at the base (icon/text-safe) amplitude just snaps to one nearest ink, but the same hue in an accent region at a theme's higher accent_amplitude resolves to a believable multi-ink stipple instead -- assert that difference directly, not just "some image came back".""" img = Image.new("RGB", (60, 60), _RICH_HUE) rect = (0, 0, 60, 60) flat = html_render.ordered_dither(img, None, amplitude=48.0) richer = html_render.ordered_dither_regions(img, None, base_amplitude=48.0, accent_regions=[(rect, 130.0)]) assert len(set(flat.getdata())) == 1 assert len(set(richer.getdata())) > 1 assert set(richer.getdata()) <= _PALETTE def test_ordered_dither_regions_with_no_accent_regions_matches_plain_dither(): img = Image.new("RGB", (30, 30), (50, 60, 70)) assert list(html_render.ordered_dither_regions(img, None, base_amplitude=48.0).getdata()) == \ list(html_render.ordered_dither(img, None, amplitude=48.0).getdata())