From b65246efcdd5ba3bd14269d6c8079818c53a876e Mon Sep 17 00:00:00 2001 From: Kent Rasmussen Date: Tue, 7 Oct 2025 15:16:04 +0900 Subject: [PATCH 1/3] rename variable to match other modifiers --- src/Modifiers/CropModifier.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Modifiers/CropModifier.php b/src/Modifiers/CropModifier.php index 745b59c..ab752fa 100644 --- a/src/Modifiers/CropModifier.php +++ b/src/Modifiers/CropModifier.php @@ -76,22 +76,22 @@ private function background(SizeInterface $resizeTo, ImageInterface $image): Vip $bgColor->channel(Blue::class)->value(), ]; - $originalImage = $image->core()->native(); - if ($originalImage->bands === 1) { + $imageNative = $image->core()->native(); + if ($imageNative->bands === 1) { // Grayscale -> RGB - $originalImage = $originalImage->colourspace('srgb'); + $imageNative = $imageNative->colourspace('srgb'); } // original image and background must have the same number of bands - if ($originalImage->hasAlpha()) { + if ($imageNative->hasAlpha()) { $bands[] = $bgColor->channel(Alpha::class)->value(); } return VipsImage::black(1, 1) ->add($bgColor->channel(Red::class)->value()) - ->cast($originalImage->format) + ->cast($imageNative->format) ->embed(0, 0, $resizeTo->width(), $resizeTo->height(), ['extend' => Extend::COPY]) - ->copy(['interpretation' => $originalImage->interpretation]) + ->copy(['interpretation' => $imageNative->interpretation]) ->bandjoin($bands); } From c43939eed269be2ec673fffb034b1fb70312e0c2 Mon Sep 17 00:00:00 2001 From: Kent Rasmussen Date: Tue, 7 Oct 2025 15:25:34 +0900 Subject: [PATCH 2/3] add grayscale alpha png created myself --- tests/resources/grayscale-alpha.png | Bin 0 -> 692 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/resources/grayscale-alpha.png diff --git a/tests/resources/grayscale-alpha.png b/tests/resources/grayscale-alpha.png new file mode 100644 index 0000000000000000000000000000000000000000..e341d5ba4794cab82f3d741485574169792ef6b9 GIT binary patch literal 692 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K588}#g)VJz{w+swS)t)YnAr*7pUSecC;K0+e z;q{dLUpP4rGHowko%~xYiur*Q!*zxoYzIsk)-e|FHe@rzj0%m01QpUm+Hb~F0?hRt TziW(usgc3c)z4*}Q$iB}vO3vm literal 0 HcmV?d00001 From 89aee517bc52255e45c5399c82e3326919961071 Mon Sep 17 00:00:00 2001 From: Kent Rasmussen Date: Tue, 7 Oct 2025 15:45:06 +0900 Subject: [PATCH 3/3] add support for grayscale alpha pngs --- src/Modifiers/ContainModifier.php | 5 ++++ src/Modifiers/CropModifier.php | 7 +++++- src/Modifiers/PadModifier.php | 9 ++++---- tests/Unit/Modifiers/ContainModifierTest.php | 24 ++++++++++++++++++++ tests/Unit/Modifiers/CropModifierTest.php | 12 ++++++++++ tests/Unit/Modifiers/PadModifierTest.php | 14 ++++++++++++ 6 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/Modifiers/ContainModifier.php b/src/Modifiers/ContainModifier.php index b726f35..cbfb933 100644 --- a/src/Modifiers/ContainModifier.php +++ b/src/Modifiers/ContainModifier.php @@ -57,6 +57,11 @@ private function contain(FrameInterface $frame, SizeInterface $resize, ColorInte 'no_rotate' => true, ]); + if ($resized->bands < 3) { + // Grayscale -> RGB + $resized = $resized->colourspace('srgb'); + } + if (!$resized->hasAlpha()) { $resized = $resized->bandjoin_const(255); } diff --git a/src/Modifiers/CropModifier.php b/src/Modifiers/CropModifier.php index ab752fa..8ea8c83 100644 --- a/src/Modifiers/CropModifier.php +++ b/src/Modifiers/CropModifier.php @@ -77,7 +77,7 @@ private function background(SizeInterface $resizeTo, ImageInterface $image): Vip ]; $imageNative = $image->core()->native(); - if ($imageNative->bands === 1) { + if ($imageNative->bands < 3) { // Grayscale -> RGB $imageNative = $imageNative->colourspace('srgb'); } @@ -136,6 +136,11 @@ private function cropFrame( ); if ($crop->width() > $originalSize->width() || $cropped->height < $crop->height()) { + if ($cropped->bands < 3) { + // Grayscale -> RGB + $cropped = $cropped->colourspace('srgb'); + } + $cropped = $background->insert( $cropped, max($offset_x * -1, 0), diff --git a/src/Modifiers/PadModifier.php b/src/Modifiers/PadModifier.php index 27a1593..44e40ae 100644 --- a/src/Modifiers/PadModifier.php +++ b/src/Modifiers/PadModifier.php @@ -55,11 +55,12 @@ private function pad(FrameInterface $frame, SizeInterface $resize, ColorInterfac 'no_rotate' => true, ]); + if ($resized->bands < 3) { + // Grayscale -> RGB + $resized = $resized->colourspace('srgb'); + } + if (!$resized->hasAlpha()) { - if ($resized->bands === 1) { - // Grayscale -> RGB - $resized = $resized->colourspace('srgb'); - } $resized = $resized->bandjoin_const(255); } diff --git a/tests/Unit/Modifiers/ContainModifierTest.php b/tests/Unit/Modifiers/ContainModifierTest.php index d7736f4..433c505 100644 --- a/tests/Unit/Modifiers/ContainModifierTest.php +++ b/tests/Unit/Modifiers/ContainModifierTest.php @@ -65,4 +65,28 @@ public function testModifyContainAnimated(): void $this->assertColor(255, 255, 255, 0, $frame->toImage(new Driver())->pickColor(0, 0)); } } + + public function testModifyContainGrayscale(): void + { + $image = $this->readTestImage('grayscale.png'); + $this->assertEquals(150, $image->width()); + $this->assertEquals(200, $image->height()); + $image->modify(new ContainModifier(200, 200, 'transparent', 'top')); + $this->assertEquals(200, $image->width()); + $this->assertEquals(200, $image->height()); + $this->assertColor(255, 255, 255, 0, $image->pickColor(0, 0)); + $this->assertColor(0, 0, 0, 255, $image->pickColor(50, 0)); + } + + public function testModifyContainGrayscaleAlpha(): void + { + $image = $this->readTestImage('grayscale-alpha.png'); + $this->assertEquals(256, $image->width()); + $this->assertEquals(256, $image->height()); + $image->modify(new ContainModifier(258, 256, 'transparent', 'top')); + $this->assertEquals(258, $image->width()); + $this->assertEquals(256, $image->height()); + $this->assertColor(255, 255, 255, 0, $image->pickColor(0, 0)); + $this->assertColor(0, 0, 0, 128, $image->pickColor(1, 0)); + } } diff --git a/tests/Unit/Modifiers/CropModifierTest.php b/tests/Unit/Modifiers/CropModifierTest.php index e290997..bc7c917 100644 --- a/tests/Unit/Modifiers/CropModifierTest.php +++ b/tests/Unit/Modifiers/CropModifierTest.php @@ -100,4 +100,16 @@ public function testCropGrayscale(): void // Ensure the image is encodable $image->encode(); } + + public function testCropGrayscaleAlpha(): void + { + $image = $this->readTestImage('grayscale-alpha.png'); + $image->modify(new CropModifier(258, 258, 0, 0, 'ff0000', 'center')); + $this->assertColor(255, 0, 0, 255, $image->pickColor(0, 0)); + $this->assertColor(0, 0, 0, 128, $image->pickColor(1, 1)); + $this->assertColor(255, 255, 255, 128, $image->pickColor(256, 1)); + + // Ensure the image is encodable + $image->encode(); + } } diff --git a/tests/Unit/Modifiers/PadModifierTest.php b/tests/Unit/Modifiers/PadModifierTest.php index 1a4765f..14252f5 100644 --- a/tests/Unit/Modifiers/PadModifierTest.php +++ b/tests/Unit/Modifiers/PadModifierTest.php @@ -50,4 +50,18 @@ public function testModifyGrayscale(): void $this->assertColor(255, 0, 0, 255, $image->pickColor(199, 0)); $this->assertColor(255, 0, 0, 255, $image->pickColor(199, 199)); } + + public function testModifyGrayscaleAlpha(): void + { + $image = $this->readTestImage('grayscale-alpha.png'); + $this->assertEquals(256, $image->width()); + $this->assertEquals(256, $image->height()); + $image->modify(new PadModifier(258, 258, 'f00')); + $this->assertEquals(258, $image->width()); + $this->assertEquals(258, $image->height()); + $this->assertColor(255, 0, 0, 255, $image->pickColor(0, 0)); + $this->assertColor(255, 0, 0, 255, $image->pickColor(0, 257)); + $this->assertColor(255, 0, 0, 255, $image->pickColor(257, 0)); + $this->assertColor(255, 0, 0, 255, $image->pickColor(257, 257)); + } }