From ab403d98c630b0fd20a8892ae1aaa469e7440ba0 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sun, 5 May 2024 11:28:01 +0200 Subject: [PATCH] Fix ignored opacity in Imagick's PlaceModifer for certain files. (#1346) * Add tests to reproduce bug in PlaceModifier * Fix bug in PlaceModifier * Add tolerance parameter to BaseTestCase::assertColor() --- .../Imagick/Modifiers/PlaceModifier.php | 1 + tests/BaseTestCase.php | 55 ++++++++++++++++++- .../Gd/Modifiers/PlaceModifierTest.php | 10 +++- .../Imagick/Modifiers/PlaceModifierTest.php | 12 +++- 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/Drivers/Imagick/Modifiers/PlaceModifier.php b/src/Drivers/Imagick/Modifiers/PlaceModifier.php index 7ee6cb5d..aa2c6e86 100644 --- a/src/Drivers/Imagick/Modifiers/PlaceModifier.php +++ b/src/Drivers/Imagick/Modifiers/PlaceModifier.php @@ -18,6 +18,7 @@ class PlaceModifier extends GenericPlaceModifier implements SpecializedInterface // set opacity of watermark if ($this->opacity < 100) { + $watermark->core()->native()->setImageAlphaChannel(Imagick::ALPHACHANNEL_OPAQUE); $watermark->core()->native()->evaluateImage( Imagick::EVALUATE_DIVIDE, $this->opacity > 0 ? 100 / $this->opacity : 1000, diff --git a/tests/BaseTestCase.php b/tests/BaseTestCase.php index 1ebfedb8..cd499d25 100644 --- a/tests/BaseTestCase.php +++ b/tests/BaseTestCase.php @@ -5,9 +5,14 @@ declare(strict_types=1); namespace Intervention\Image\Tests; use Intervention\Image\Colors\Rgb\Channels\Alpha; +use Intervention\Image\Colors\Rgb\Channels\Blue; +use Intervention\Image\Colors\Rgb\Channels\Green; +use Intervention\Image\Colors\Rgb\Channels\Red; use Intervention\Image\Colors\Rgb\Color as RgbColor; +use Intervention\Image\Colors\Rgb\Colorspace; use Intervention\Image\Interfaces\ColorInterface; use Mockery\Adapter\Phpunit\MockeryTestCase; +use PHPUnit\Framework\ExpectationFailedException; abstract class BaseTestCase extends MockeryTestCase { @@ -30,9 +35,55 @@ abstract class BaseTestCase extends MockeryTestCase return $pointer; } - protected function assertColor($r, $g, $b, $a, ColorInterface $color) + /** + * Assert that given color equals the given color channel values in the given optional tolerance + * + * @param int $r + * @param int $g + * @param int $b + * @param int $a + * @param ColorInterface $color + * @param int $tolerance + * @throws ExpectationFailedException + * @return void + */ + protected function assertColor(int $r, int $g, int $b, int $a, ColorInterface $color, int $tolerance = 0) { - $this->assertEquals([$r, $g, $b, $a], $color->toArray()); + $this->assertContains( + $color->channel(Red::class)->value(), + range(max($r - $tolerance, 0), min($r + $tolerance, 255)), + 'Failed asserting that color ' . + $color->convertTo(Colorspace::class)->toString() . + ' equals ' + . $color->convertTo(Colorspace::class)->toString() + ); + + $this->assertContains( + $color->channel(Green::class)->value(), + range(max($g - $tolerance, 0), min($g + $tolerance, 255)), + 'Failed asserting that color ' . + $color->convertTo(Colorspace::class)->toString() . + ' equals ' + . $color->convertTo(Colorspace::class)->toString() + ); + + $this->assertContains( + $color->channel(Blue::class)->value(), + range(max($b - $tolerance, 0), min($b + $tolerance, 255)), + 'Failed asserting that color ' . + $color->convertTo(Colorspace::class)->toString() . + ' equals ' + . $color->convertTo(Colorspace::class)->toString() + ); + + $this->assertContains( + $color->channel(Alpha::class)->value(), + range(max($a - $tolerance, 0), min($a + $tolerance, 255)), + 'Failed asserting that color ' . + $color->convertTo(Colorspace::class)->toString() . + ' equals ' + . $color->convertTo(Colorspace::class)->toString() + ); } protected function assertTransparency(ColorInterface $color) diff --git a/tests/Unit/Drivers/Gd/Modifiers/PlaceModifierTest.php b/tests/Unit/Drivers/Gd/Modifiers/PlaceModifierTest.php index 02c1e554..7fcc1b88 100644 --- a/tests/Unit/Drivers/Gd/Modifiers/PlaceModifierTest.php +++ b/tests/Unit/Drivers/Gd/Modifiers/PlaceModifierTest.php @@ -22,11 +22,19 @@ final class PlaceModifierTest extends GdTestCase $this->assertEquals('32250d', $image->pickColor(300, 25)->toHex()); } - public function testColorChangeOpacity(): void + public function testColorChangeOpacityPng(): void { $image = $this->readTestImage('test.jpg'); $this->assertEquals('febc44', $image->pickColor(300, 25)->toHex()); $image->modify(new PlaceModifier($this->getTestResourcePath('circle.png'), 'top-right', 0, 0, 50)); $this->assertEquals('987028', $image->pickColor(300, 25)->toHex()); } + + public function testColorChangeOpacityJpeg(): void + { + $image = $this->createTestImage(16, 16)->fill('0000ff'); + $this->assertEquals('0000ff', $image->pickColor(10, 10)->toHex()); + $image->modify(new PlaceModifier($this->getTestResourcePath('exif.jpg'), opacity: 50)); + $this->assertColor(127, 83, 127, 255, $image->pickColor(10, 10), tolerance: 1); + } } diff --git a/tests/Unit/Drivers/Imagick/Modifiers/PlaceModifierTest.php b/tests/Unit/Drivers/Imagick/Modifiers/PlaceModifierTest.php index 7cb9de0d..d68f015a 100644 --- a/tests/Unit/Drivers/Imagick/Modifiers/PlaceModifierTest.php +++ b/tests/Unit/Drivers/Imagick/Modifiers/PlaceModifierTest.php @@ -22,11 +22,19 @@ final class PlaceModifierTest extends ImagickTestCase $this->assertEquals('33260e', $image->pickColor(300, 25)->toHex()); } - public function testColorChangeOpacity(): void + public function testColorChangeOpacityPng(): void { $image = $this->readTestImage('test.jpg'); $this->assertEquals('febc44', $image->pickColor(300, 25)->toHex()); $image->modify(new PlaceModifier($this->getTestResourcePath('circle.png'), 'top-right', 0, 0, 50)); - $this->assertEquals('987129', $image->pickColor(300, 25)->toHex()); + $this->assertEquals('7f5e22', $image->pickColor(300, 25)->toHex()); + } + + public function testColorChangeOpacityJpeg(): void + { + $image = $this->createTestImage(16, 16)->fill('0000ff'); + $this->assertEquals('0000ff', $image->pickColor(10, 10)->toHex()); + $image->modify(new PlaceModifier($this->getTestResourcePath('exif.jpg'), opacity: 50)); + $this->assertColor(127, 83, 127, 255, $image->pickColor(10, 10), tolerance: 1); } }