diff --git a/Dockerfile b/Dockerfile index f3471b6cc..b17cf7c36 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,7 @@ RUN apt update \ && apt install -y \ libpng-dev \ libicu-dev \ + libavif-dev \ libpq-dev \ libzip-dev \ zip \ @@ -13,7 +14,7 @@ RUN apt update \ libmagickwand-dev \ libwebp-dev \ && pecl install imagick \ - && docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \ + && docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-avif \ && docker-php-ext-enable imagick \ && docker-php-ext-install \ intl \ diff --git a/composer.json b/composer.json index 909da5f29..b2591f2e1 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "require": { "php": "^8.1", "intervention/gif": "^3.0", - "intervention/mimesniffer": "^0.4.2" + "intervention/mimesniffer": "^0.5" }, "require-dev": { "phpunit/phpunit": "^9", diff --git a/src/Drivers/Abstract/AbstractImage.php b/src/Drivers/Abstract/AbstractImage.php index 7fbe5b4a6..3b70d93a2 100644 --- a/src/Drivers/Abstract/AbstractImage.php +++ b/src/Drivers/Abstract/AbstractImage.php @@ -94,6 +94,13 @@ public function toBmp(): EncodedImage return $this->toBitmap(); } + public function toAvif(): EncodedImage + { + return $this->encode( + $this->resolveDriverClass('Encoders\AvifEncoder') + ); + } + public function greyscale(): ImageInterface { return $this->modify( diff --git a/src/Drivers/Gd/Encoders/AvifEncoder.php b/src/Drivers/Gd/Encoders/AvifEncoder.php new file mode 100644 index 000000000..aaa39ea5b --- /dev/null +++ b/src/Drivers/Gd/Encoders/AvifEncoder.php @@ -0,0 +1,25 @@ +quality = $quality; + } + + public function encode(ImageInterface $image): EncodedImage + { + $data = $this->getBuffered(function () use ($image) { + imageavif($image->getFrame()->getCore(), null, $this->quality); + }); + + return new EncodedImage($data, 'image/avif'); + } +} diff --git a/src/Drivers/Imagick/Encoders/AvifEncoder.php b/src/Drivers/Imagick/Encoders/AvifEncoder.php new file mode 100644 index 000000000..f1aef7170 --- /dev/null +++ b/src/Drivers/Imagick/Encoders/AvifEncoder.php @@ -0,0 +1,26 @@ +getFrame()->getCore(); + $imagick->setFormat($format); + $imagick->setImageFormat($format); + $imagick->setCompression($compression); + $imagick->setImageCompression($compression); + + return new EncodedImage($imagick->getImagesBlob(), 'image/avif'); + } +} diff --git a/src/Interfaces/ImageInterface.php b/src/Interfaces/ImageInterface.php index aac0d79b1..34b42f12f 100644 --- a/src/Interfaces/ImageInterface.php +++ b/src/Interfaces/ImageInterface.php @@ -109,6 +109,12 @@ public function toWebp(int $quality = 75): EncodedImage; */ public function toGif(): EncodedImage; + /** + * Encode image to avif format + * + * @return EncodedImage + */ + public function toAvif(): EncodedImage; /** * Encode image to png format diff --git a/tests/Drivers/Gd/Encoders/AvifEncoderTest.php b/tests/Drivers/Gd/Encoders/AvifEncoderTest.php new file mode 100644 index 000000000..b2d1fa0da --- /dev/null +++ b/tests/Drivers/Gd/Encoders/AvifEncoderTest.php @@ -0,0 +1,33 @@ +getTestImage(); + $encoder = new AvifEncoder(10); + $result = $encoder->encode($image); + $this->assertTrue(MimeSniffer::createFromString($result)->matches(new ImageAvif())); + } +} diff --git a/tests/Drivers/Imagick/Encoders/AvifEncoderTest.php b/tests/Drivers/Imagick/Encoders/AvifEncoderTest.php new file mode 100644 index 000000000..e3fa42cac --- /dev/null +++ b/tests/Drivers/Imagick/Encoders/AvifEncoderTest.php @@ -0,0 +1,34 @@ +newImage(3, 2, new ImagickPixel('red'), 'png'); + + return new Image($imagick); + } + + public function testEncode(): void + { + $image = $this->getTestImage(); + $encoder = new AvifEncoder(10); + $result = $encoder->encode($image); + $this->assertTrue(MimeSniffer::createFromString($result)->matches(new ImageAvif())); + } +}