From f3bf49ba1d37c72ba8fd51f44faef72b630fac92 Mon Sep 17 00:00:00 2001 From: Matt Edholm Date: Thu, 14 May 2026 13:29:46 -0400 Subject: [PATCH] =?UTF-8?q?experiment(render):=20Riemersma=20dither=20to?= =?UTF-8?q?=20stop=20sky=E2=86=92face=20blue=20bleed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Floyd-Steinberg's row-order error diffusion was flushing residual blue debt from sky pixels downward into the face below — visible as a blue hue in skin tones that should have been YELLOW/RED/WHITE in the 6-color palette. Riemersma uses a Hilbert-curve scan, so error stays local and isn't biased along any axis. DITHER_METHOD FLOYDSTEINBERG → RIEMERSMA (gamma 1.2 + saturation 115 from experiment #1 unchanged). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/MessageHandler/RenderImageMessageHandler.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/MessageHandler/RenderImageMessageHandler.php b/src/MessageHandler/RenderImageMessageHandler.php index 5c41a69..7927c3f 100644 --- a/src/MessageHandler/RenderImageMessageHandler.php +++ b/src/MessageHandler/RenderImageMessageHandler.php @@ -46,8 +46,14 @@ final class RenderImageMessageHandler /** sharpenImage(radius=0, SHARPEN_SIGMA). Baseline: 0.8 (light). */ private const SHARPEN_SIGMA = 0.8; - /** Imagick dither method. Baseline: DITHERMETHOD_FLOYDSTEINBERG. */ - private const DITHER_METHOD = \Imagick::DITHERMETHOD_FLOYDSTEINBERG; + /** Imagick dither method. + * Baseline: DITHERMETHOD_FLOYDSTEINBERG — error diffuses down-right + * in row order, so a blue sky's residual error + * accumulates downward and "flushes" into faces/hair + * below, contaminating skin tones with blue. + * Experiment #2: DITHERMETHOD_RIEMERSMA — Hilbert-curve scan, error + * stays local and doesn't bias along any axis. */ + private const DITHER_METHOD = \Imagick::DITHERMETHOD_RIEMERSMA; public function __construct( private readonly ImageRepository $imageRepo,