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)); + } +}