From 38e1b6f2a6711c4fda64a3153a63f731c2432eb9 Mon Sep 17 00:00:00 2001 From: Benjamin Nussbaum Date: Wed, 29 Oct 2025 22:35:16 +0100 Subject: [PATCH] fix(#103): apply dithering if requested by markup --- app/Services/ImageGenerationService.php | 31 +++++++++++++++++++++++++ composer.json | 2 +- composer.lock | 14 +++++------ 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/app/Services/ImageGenerationService.php b/app/Services/ImageGenerationService.php index f513e05..76be3bb 100644 --- a/app/Services/ImageGenerationService.php +++ b/app/Services/ImageGenerationService.php @@ -72,6 +72,12 @@ class ImageGenerationService ->offsetY($imageSettings['offset_y']) ->outputPath($outputPath); + // Apply dithering if requested by markup + $shouldDither = self::markupContainsDitherImage($markup); + if ($shouldDither) { + $imageStage->dither(); + } + (new TrmnlPipeline())->pipe($browserStage) ->pipe($imageStage) ->process(); @@ -209,6 +215,31 @@ class ImageGenerationService }; } + /** + * Detect whether the provided HTML markup contains an tag with class "image-dither". + */ + private static function markupContainsDitherImage(string $markup): bool + { + if (mb_trim($markup) === '') { + return false; + } + + // Find (or with single quotes) and inspect class tokens + $imgWithClassPattern = '/]*\bclass\s*=\s*(["\'])(.*?)\1[^>]*>/i'; + if (! preg_match_all($imgWithClassPattern, $markup, $matches)) { + return false; + } + + foreach ($matches[2] as $classValue) { + // Look for class token 'image-dither' or 'image--dither' + if (preg_match('/(?:^|\s)image--?dither(?:\s|$)/', $classValue)) { + return true; + } + } + + return false; + } + public static function cleanupFolder(): void { $activeDeviceImageUuids = Device::pluck('current_screen_image')->filter()->toArray(); diff --git a/composer.json b/composer.json index 0d3fc42..79306ce 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "ext-simplexml": "*", "ext-zip": "*", "bnussbau/laravel-trmnl-blade": "2.0.*", - "bnussbau/trmnl-pipeline-php": "^0.3.0", + "bnussbau/trmnl-pipeline-php": "^0.4.0", "keepsuit/laravel-liquid": "^0.5.2", "laravel/framework": "^12.1", "laravel/sanctum": "^4.0", diff --git a/composer.lock b/composer.lock index e1f0d77..2f54904 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d6d201899ecc5b1243e9a481c22c5732", + "content-hash": "3d743ce4dc2742c59ed6f9cc8ed36e04", "packages": [ { "name": "aws/aws-crt-php", @@ -243,16 +243,16 @@ }, { "name": "bnussbau/trmnl-pipeline-php", - "version": "0.3.2", + "version": "0.4.0", "source": { "type": "git", "url": "https://github.com/bnussbau/trmnl-pipeline-php.git", - "reference": "ead26a45ac919e3f2a5f4a448508a919cd3258d3" + "reference": "b58b937f36e55aa7cbd4859cbe7a902bf1050bf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bnussbau/trmnl-pipeline-php/zipball/ead26a45ac919e3f2a5f4a448508a919cd3258d3", - "reference": "ead26a45ac919e3f2a5f4a448508a919cd3258d3", + "url": "https://api.github.com/repos/bnussbau/trmnl-pipeline-php/zipball/b58b937f36e55aa7cbd4859cbe7a902bf1050bf8", + "reference": "b58b937f36e55aa7cbd4859cbe7a902bf1050bf8", "shasum": "" }, "require": { @@ -294,7 +294,7 @@ ], "support": { "issues": "https://github.com/bnussbau/trmnl-pipeline-php/issues", - "source": "https://github.com/bnussbau/trmnl-pipeline-php/tree/0.3.2" + "source": "https://github.com/bnussbau/trmnl-pipeline-php/tree/0.4.0" }, "funding": [ { @@ -310,7 +310,7 @@ "type": "github" } ], - "time": "2025-10-17T12:12:40+00:00" + "time": "2025-10-30T11:52:17+00:00" }, { "name": "brick/math",