From 635567e9c20a73ccb7fc07d1efe7db63c53d5ef9 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Sat, 30 Sep 2023 17:00:22 +0200 Subject: [PATCH] Add remove animation modifiers --- src/Drivers/Abstract/AbstractImage.php | 7 ++++ .../Gd/Modifiers/RemoveAnimationModifier.php | 35 +++++++++++++++++++ src/Drivers/Imagick/Image.php | 10 +++--- .../Modifiers/RemoveAnimationModifier.php | 35 +++++++++++++++++++ src/Interfaces/ImageInterface.php | 7 ++++ .../Modifiers/RemoveAnimationModifierTest.php | 24 +++++++++++++ .../Modifiers/RemoveAnimationModifierTest.php | 24 +++++++++++++ 7 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 src/Drivers/Gd/Modifiers/RemoveAnimationModifier.php create mode 100644 src/Drivers/Imagick/Modifiers/RemoveAnimationModifier.php create mode 100644 tests/Drivers/Gd/Modifiers/RemoveAnimationModifierTest.php create mode 100644 tests/Drivers/Imagick/Modifiers/RemoveAnimationModifierTest.php diff --git a/src/Drivers/Abstract/AbstractImage.php b/src/Drivers/Abstract/AbstractImage.php index 25a6cf35a..7fbe5b4a6 100644 --- a/src/Drivers/Abstract/AbstractImage.php +++ b/src/Drivers/Abstract/AbstractImage.php @@ -334,6 +334,13 @@ public function padDown( ); } + public function removeAnimation(int $position = 0): ImageInterface + { + return $this->modify( + $this->resolveDriverClass('Modifiers\RemoveAnimationModifier', $position) + ); + } + public function destroy(): void { $this->modify( diff --git a/src/Drivers/Gd/Modifiers/RemoveAnimationModifier.php b/src/Drivers/Gd/Modifiers/RemoveAnimationModifier.php new file mode 100644 index 000000000..7802f08b8 --- /dev/null +++ b/src/Drivers/Gd/Modifiers/RemoveAnimationModifier.php @@ -0,0 +1,35 @@ +isAnimated()) { + throw new RuntimeException('Image is not animated.'); + } + + $frames = new Collection(); + foreach ($image as $key => $frame) { + if ($this->position == $key) { + $frames->push($frame); + } else { + imagedestroy($frame->getCore()); + } + } + + return new Image($frames); + } +} diff --git a/src/Drivers/Imagick/Image.php b/src/Drivers/Imagick/Image.php index e5cf937f4..03f2743ab 100644 --- a/src/Drivers/Imagick/Image.php +++ b/src/Drivers/Imagick/Image.php @@ -26,13 +26,13 @@ public function getImagick(): Imagick public function getFrame(int $position = 0): ?FrameInterface { - try { - $this->imagick->setIteratorIndex($position); - } catch (ImagickException $e) { - return null; + foreach ($this->imagick as $core) { + if ($core->getIteratorIndex() == $position) { + return new Frame($core); + } } - return new Frame($this->imagick->current()); + return null; } public function addFrame(FrameInterface $frame): ImageInterface diff --git a/src/Drivers/Imagick/Modifiers/RemoveAnimationModifier.php b/src/Drivers/Imagick/Modifiers/RemoveAnimationModifier.php new file mode 100644 index 000000000..60a21f1a2 --- /dev/null +++ b/src/Drivers/Imagick/Modifiers/RemoveAnimationModifier.php @@ -0,0 +1,35 @@ +isAnimated()) { + throw new RuntimeException('Image is not animated.'); + } + + $imagick = new Imagick(); + foreach ($image as $frame) { + if ($frame->getCore()->getIteratorIndex() == $this->position) { + $imagick->addImage($frame->getCore()->getImage()); + } + } + + $image->destroy(); + + return new Image($imagick); + } +} diff --git a/src/Interfaces/ImageInterface.php b/src/Interfaces/ImageInterface.php index 4b04f7619..aac0d79b1 100644 --- a/src/Interfaces/ImageInterface.php +++ b/src/Interfaces/ImageInterface.php @@ -62,6 +62,13 @@ public function getSize(): SizeInterface; */ public function isAnimated(): bool; + /** + * Remove all frames but keep the one at the specified position + * + * @param int $position + * @return ImageInterface + */ + public function removeAnimation(int $position = 0): ImageInterface; /** * Apply given modifier to current image diff --git a/tests/Drivers/Gd/Modifiers/RemoveAnimationModifierTest.php b/tests/Drivers/Gd/Modifiers/RemoveAnimationModifierTest.php new file mode 100644 index 000000000..a48473ab7 --- /dev/null +++ b/tests/Drivers/Gd/Modifiers/RemoveAnimationModifierTest.php @@ -0,0 +1,24 @@ +createTestImage('animation.gif'); + $this->assertEquals(8, count($image)); + $image = $image->modify(new RemoveAnimationModifier(2)); + $this->assertEquals(1, count($image)); + } +} diff --git a/tests/Drivers/Imagick/Modifiers/RemoveAnimationModifierTest.php b/tests/Drivers/Imagick/Modifiers/RemoveAnimationModifierTest.php new file mode 100644 index 000000000..8f0591a4b --- /dev/null +++ b/tests/Drivers/Imagick/Modifiers/RemoveAnimationModifierTest.php @@ -0,0 +1,24 @@ +createTestImage('animation.gif'); + $this->assertEquals(8, count($image)); + $image = $image->modify(new RemoveAnimationModifier(2)); + $this->assertEquals(1, count($image)); + } +}