From 8eb1394b9908aebee0d750abf4e6fcd6a3aaad75 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Tue, 3 Oct 2023 10:18:17 +0200 Subject: [PATCH] Add methods to create new animated images --- src/Drivers/Gd/ImageFactory.php | 33 +++++++++++++++++++ src/Drivers/Imagick/ImageFactory.php | 37 ++++++++++++++++++++++ src/ImageManager.php | 11 +++++++ tests/Drivers/Gd/ImageFactoryTest.php | 11 +++++++ tests/Drivers/Imagick/ImageFactoryTest.php | 11 +++++++ 5 files changed, 103 insertions(+) diff --git a/src/Drivers/Gd/ImageFactory.php b/src/Drivers/Gd/ImageFactory.php index 7dbc2f4ea..1d92a3689 100644 --- a/src/Drivers/Gd/ImageFactory.php +++ b/src/Drivers/Gd/ImageFactory.php @@ -3,11 +3,16 @@ namespace Intervention\Image\Drivers\Gd; use Intervention\Image\Collection; +use Intervention\Image\Drivers\Gd\Frame; +use Intervention\Image\Drivers\Gd\Image; use Intervention\Image\Interfaces\FactoryInterface; use Intervention\Image\Interfaces\ImageInterface; +use Intervention\Image\Traits\CanHandleInput; class ImageFactory implements FactoryInterface { + use CanHandleInput; + public function newImage(int $width, int $height): ImageInterface { return new Image( @@ -17,6 +22,34 @@ public function newImage(int $width, int $height): ImageInterface ); } + public function newAnimation(callable $callback): ImageInterface + { + $frames = new Collection(); + + $animation = new class ($frames) extends ImageFactory + { + public function __construct(public Collection $frames) + { + // + } + + public function add($source, float $delay = 1): self + { + $this->frames->push( + $this->handleInput($source) + ->getFrame() + ->setDelay($delay) + ); + + return $this; + } + }; + + $callback($animation); + + return new Image($frames); + } + public function newCore(int $width, int $height) { $core = imagecreatetruecolor($width, $height); diff --git a/src/Drivers/Imagick/ImageFactory.php b/src/Drivers/Imagick/ImageFactory.php index cc54048b7..773f1a532 100644 --- a/src/Drivers/Imagick/ImageFactory.php +++ b/src/Drivers/Imagick/ImageFactory.php @@ -4,16 +4,53 @@ use Imagick; use ImagickPixel; +use Intervention\Image\Drivers\Imagick\Image; use Intervention\Image\Interfaces\FactoryInterface; use Intervention\Image\Interfaces\ImageInterface; +use Intervention\Image\Traits\CanCheckType; +use Intervention\Image\Traits\CanHandleInput; class ImageFactory implements FactoryInterface { + use CanHandleInput; + use CanCheckType; + public function newImage(int $width, int $height): ImageInterface { return new Image($this->newCore($width, $height)); } + public function newAnimation(callable $callback): ImageInterface + { + $imagick = new Imagick(); + $imagick->setFormat('gif'); + + $animation = new class ($imagick) extends ImageFactory + { + public function __construct(public Imagick $imagick) + { + // + } + + public function add($source, float $delay = 1): self + { + $imagick = $this->failIfNotClass( + $this->handleInput($source), + Image::class, + )->getImagick(); + $imagick->setImageDelay($delay * 100); + + $this->imagick->addImage($imagick); + + return $this; + } + }; + + $callback($animation); + + return new Image($animation->imagick); + } + public function newCore(int $width, int $height) { $imagick = new Imagick(); diff --git a/src/ImageManager.php b/src/ImageManager.php index fef130797..1703cf84e 100644 --- a/src/ImageManager.php +++ b/src/ImageManager.php @@ -26,6 +26,17 @@ public function create(int $width, int $height): ImageInterface return $this->resolveDriverClass('ImageFactory')->newImage($width, $height); } + /** + * Create new animated image from sources + * + * @param callable $callback + * @return ImageInterface + */ + public function animate(callable $callback): ImageInterface + { + return $this->resolveDriverClass('ImageFactory')->newAnimation($callback); + } + /** * Create new image instance from source * diff --git a/tests/Drivers/Gd/ImageFactoryTest.php b/tests/Drivers/Gd/ImageFactoryTest.php index 32cf83d46..38060e45e 100644 --- a/tests/Drivers/Gd/ImageFactoryTest.php +++ b/tests/Drivers/Gd/ImageFactoryTest.php @@ -20,6 +20,17 @@ public function testNewImage(): void $this->assertInstanceOf(Image::class, $image); } + public function testNewAnimation(): void + { + $factory = new ImageFactory(); + $image = $factory->newAnimation(function ($animation) { + $animation->add($this->getTestImagePath('blue.gif'), 1.2); + $animation->add($this->getTestImagePath('red.gif'), 1.2); + }); + $this->assertInstanceOf(Image::class, $image); + $this->assertEquals(2, $image->count()); + } + public function testNewCore(): void { $factory = new ImageFactory(); diff --git a/tests/Drivers/Imagick/ImageFactoryTest.php b/tests/Drivers/Imagick/ImageFactoryTest.php index 75e40e244..635139e54 100644 --- a/tests/Drivers/Imagick/ImageFactoryTest.php +++ b/tests/Drivers/Imagick/ImageFactoryTest.php @@ -20,6 +20,17 @@ public function testNewImage(): void $this->assertInstanceOf(Image::class, $image); } + public function testNewAnimation(): void + { + $factory = new ImageFactory(); + $image = $factory->newAnimation(function ($animation) { + $animation->add($this->getTestImagePath('blue.gif'), 1.2); + $animation->add($this->getTestImagePath('red.gif'), 1.2); + }); + $this->assertInstanceOf(Image::class, $image); + $this->assertEquals(2, $image->count()); + } + public function testNewCore(): void { $factory = new ImageFactory();