From 0a5c7acaeab96b0a1a20e49382f3dce2a233142f Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 8 Jan 2025 07:45:51 -0600 Subject: [PATCH] fixed crop for animations --- src/Modifiers/CropModifier.php | 60 ++++++++++++++++------- tests/Unit/Modifiers/CropModifierTest.php | 23 +++++++++ 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/src/Modifiers/CropModifier.php b/src/Modifiers/CropModifier.php index 250b82d..856e171 100644 --- a/src/Modifiers/CropModifier.php +++ b/src/Modifiers/CropModifier.php @@ -8,7 +8,9 @@ use Intervention\Image\Colors\Rgb\Channels\Blue; use Intervention\Image\Colors\Rgb\Channels\Green; use Intervention\Image\Colors\Rgb\Channels\Red; +use Intervention\Image\Drivers\Vips\Core; use Intervention\Image\Exceptions\RuntimeException; +use Intervention\Image\Interfaces\FrameInterface; use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\SizeInterface; use Intervention\Image\Interfaces\SpecializedInterface; @@ -48,27 +50,14 @@ public function apply(ImageInterface $image): ImageInterface ) ); } else { - $offset_x = $crop->pivot()->x() + $this->offset_x; - $offset_y = $crop->pivot()->y() + $this->offset_y; - - $targetWidth = min($crop->width(), $originalSize->width()); - $targetHeight = min($crop->height(), $originalSize->height()); - - $targetWidth = $targetWidth > $originalSize->width() ? $targetWidth + $offset_x : $targetWidth; - $targetHeight = $targetHeight > $originalSize->height() ? $targetHeight + $offset_y : $targetHeight; - - $cropped = $image->core()->native()->crop( - max($offset_x, 0), - max($offset_y, 0), - $targetWidth, - $targetHeight - ); - - if ($crop->width() > $originalSize->width() || $cropped->height < $crop->height()) { - $cropped = $background->insert($cropped, max($offset_x * -1, 0), max($offset_y * -1, 0)); + $frames = []; + foreach ($image as $frame) { + $frames[] = $frame->setNative($this->cropFrame($frame, $crop, $originalSize, $background)); } - $image->core()->setNative($cropped); + $image->core()->setNative( + Core::replaceFrames($image->core()->native(), $frames) + ); } return $image; @@ -116,4 +105,37 @@ private function getInterestingPositions(): array Interesting::ALL, ]); } + + private function cropFrame( + FrameInterface $frame, + SizeInterface $crop, + SizeInterface $originalSize, + VipsImage $background + ): VipsImage { + $offset_x = $crop->pivot()->x() + $this->offset_x; + $offset_y = $crop->pivot()->y() + $this->offset_y; + + $targetWidth = min($crop->width(), $originalSize->width()); + $targetHeight = min($crop->height(), $originalSize->height()); + + $targetWidth = $targetWidth > $originalSize->width() ? $targetWidth + $offset_x : $targetWidth; + $targetHeight = $targetHeight > $originalSize->height() ? $targetHeight + $offset_y : $targetHeight; + + $cropped = $frame->native()->crop( + max($offset_x, 0), + max($offset_y, 0), + $targetWidth, + $targetHeight + ); + + if ($crop->width() > $originalSize->width() || $cropped->height < $crop->height()) { + $cropped = $background->insert( + $cropped, + max($offset_x * -1, 0), + max($offset_y * -1, 0) + ); + } + + return $cropped; + } } diff --git a/tests/Unit/Modifiers/CropModifierTest.php b/tests/Unit/Modifiers/CropModifierTest.php index a263ebd..444069b 100644 --- a/tests/Unit/Modifiers/CropModifierTest.php +++ b/tests/Unit/Modifiers/CropModifierTest.php @@ -4,6 +4,7 @@ namespace Intervention\Image\Drivers\Vips\Tests\Unit\Modifiers; +use Intervention\Image\Colors\Rgb\Color; use Intervention\Image\Drivers\Vips\Driver; use Intervention\Image\Drivers\Vips\Tests\BaseTestCase; use Intervention\Image\Modifiers\CropModifier; @@ -65,4 +66,26 @@ public function testModifyCropSmart(): void $this->assertEquals(50, $image->height()); $this->assertColor(255, 219, 154, 255, $image->pickColor(25, 25)); } + + public function testModifyCropAnimated(): void + { + $image = $this->readTestImage('animation.gif'); + $image = $image->modify(new CropModifier(15, 15, 0, 0, position: 'center')); + $this->assertEquals(15, $image->width()); + $this->assertEquals(15, $image->height()); + + $this->assertEquals( + array_map(fn(Color $color): string => $color->toHex(), $image->pickColors(8, 8)->toArray()), + ['ffa601', 'ffa601', 'ffa601', 'ffa601', '394b63', '394b63', '394b63', '394b63'] + ); + } + + public function testModifyCropAnimatedSmart(): void + { + $image = $this->readTestImage('animation.gif'); + $image = $image->modify(new CropModifier(15, 15, 0, 0, 'ff0000', 'interesting-attention')); + $this->assertEquals(15, $image->width()); + $this->assertEquals(15, $image->height()); + $this->assertColor(255, 166, 1, 255, $image->pickColor(8, 8)); + } }