Skip to content

Commit

Permalink
added AVIF support (#3320)
Browse files Browse the repository at this point in the history
* added avif support

* bump version

* bump

---------

Co-authored-by: Freek Van der Herten <[email protected]>
  • Loading branch information
0xb4lint and freekmurze authored Jul 24, 2023
1 parent f8e47a7 commit 83e902e
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 9 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"illuminate/support": "^9.18|^10.0",
"intervention/image": "^2.7",
"maennchen/zipstream-php": "^2.0|^3.0",
"spatie/image": "^2.2.2",
"spatie/image": "^2.2.7",
"spatie/temporary-directory": "^2.0",
"symfony/console": "^6.0"
},
Expand Down
11 changes: 11 additions & 0 deletions config/media-library.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@
'-mt', // multithreading for some speed improvements.
'-q 90', //quality factor that brings the least noticeable changes.
],
Spatie\ImageOptimizer\Optimizers\Avifenc::class => [
'-a cq-level=23', // constant quality level, lower values mean better quality and greater file size (0-63).
'-j all', // number of jobs (worker threads, "all" uses all available cores).
'--min 0', // min quantizer for color (0-63).
'--max 63', // max quantizer for color (0-63).
'--minalpha 0', // min quantizer for alpha (0-63).
'--maxalpha 63', // max quantizer for alpha (0-63).
'-a end-usage=q', // rate control mode set to Constant Quality mode.
'-a tune=ssim', // SSIM as tune the encoder for distortion metric.
],
],

/*
Expand All @@ -141,6 +151,7 @@
'image_generators' => [
Spatie\MediaLibrary\Conversions\ImageGenerators\Image::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Webp::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Avif::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Pdf::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Svg::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Video::class,
Expand Down
2 changes: 1 addition & 1 deletion docs/converting-images/defining-conversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ weight: 1

When adding files to the media library it can automatically create derived versions such as thumbnails and banners.

Media conversions will be executed whenever a `jpg`, `png`, `svg`, `webp`, `pdf`, `mp4 `, `mov` or `webm` file is added to the media library. By default, the conversions will be saved as a `jpg` files. This can be overwritten using the `format()` or `keepOriginalImageFormat()` methods.
Media conversions will be executed whenever a `jpg`, `png`, `svg`, `webp`, `avif`, `pdf`, `mp4 `, `mov` or `webm` file is added to the media library. By default, the conversions will be saved as a `jpg` files. This can be overwritten using the `format()` or `keepOriginalImageFormat()` methods.

Internally, [spatie/image](https://docs.spatie.be/image/v1/) is used to manipulate the images. You can use [any manipulation function](https://docs.spatie.be/image) from that package.

Expand Down
19 changes: 15 additions & 4 deletions docs/installation-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,20 @@ return [
'-O3', // this produces the slowest but best results
],
Spatie\ImageOptimizer\Optimizers\Cwebp::class => [
'-m 6', // for the slowest compression method in order to get the best compression.
'-pass 10', // for maximizing the amount of analysis pass.
'-mt', // multithreading for some speed improvements.
'-q 90', //quality factor that brings the least noticeable changes.
'-m 6', // for the slowest compression method in order to get the best compression.
'-pass 10', // for maximizing the amount of analysis pass.
'-mt', // multithreading for some speed improvements.
'-q 90', //quality factor that brings the least noticeable changes.
],
Spatie\ImageOptimizer\Optimizers\Avifenc::class => [
'-a cq-level=23', // constant quality level, lower values mean better quality and greater file size (0-63).
'-j all', // number of jobs (worker threads, "all" uses all available cores).
'--min 0', // min quantizer for color (0-63).
'--max 63', // max quantizer for color (0-63).
'--minalpha 0', // min quantizer for alpha (0-63).
'--maxalpha 63', // max quantizer for alpha (0-63).
'-a end-usage=q', // rate control mode set to Constant Quality mode.
'-a tune=ssim', // SSIM as tune the encoder for distortion metric.
],
],

Expand All @@ -155,6 +165,7 @@ return [
'image_generators' => [
Spatie\MediaLibrary\Conversions\ImageGenerators\Image::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Webp::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Avif::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Pdf::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Svg::class,
Spatie\MediaLibrary\Conversions\ImageGenerators\Video::class,
Expand Down
20 changes: 20 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,26 @@ parameters:
count: 1
path: src/Conversions/ImageGenerators/Webp.php

-
message: "#^Method Spatie\\\\MediaLibrary\\\\Conversions\\\\ImageGenerators\\\\Avif\\:\\:supportedExtensions\\(\\) return type with generic class Illuminate\\\\Support\\\\Collection does not specify its types\\: TKey, TValue$#"
count: 1
path: src/Conversions/ImageGenerators/Avif.php

-
message: "#^Method Spatie\\\\MediaLibrary\\\\Conversions\\\\ImageGenerators\\\\Avif\\:\\:supportedMimeTypes\\(\\) return type with generic class Illuminate\\\\Support\\\\Collection does not specify its types\\: TKey, TValue$#"
count: 1
path: src/Conversions/ImageGenerators/Avif.php

-
message: "#^Parameter \\#1 \\$image of function imagedestroy expects GdImage, GdImage\\|false given\\.$#"
count: 1
path: src/Conversions/ImageGenerators/Avif.php

-
message: "#^Parameter \\#1 \\$image of function imagepng expects GdImage, GdImage\\|false given\\.$#"
count: 1
path: src/Conversions/ImageGenerators/Avif.php

-
message: "#^Method Spatie\\\\MediaLibrary\\\\Conversions\\\\Jobs\\\\PerformConversionsJob\\:\\:__construct\\(\\) has parameter \\$conversions with generic class Spatie\\\\MediaLibrary\\\\Conversions\\\\ConversionCollection but does not specify its types\\: TKey, TValue$#"
count: 1
Expand Down
2 changes: 1 addition & 1 deletion src/Conversions/Conversion.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public function shouldBeQueued(): bool
public function getResultExtension(string $originalFileExtension = ''): string
{
if ($this->shouldKeepOriginalImageFormat()) {
if (in_array(strtolower($originalFileExtension), ['jpg', 'jpeg', 'pjpg', 'png', 'gif', 'webp'])) {
if (in_array(strtolower($originalFileExtension), ['jpg', 'jpeg', 'pjpg', 'png', 'gif', 'webp', 'avif'])) {
return $originalFileExtension;
}
}
Expand Down
49 changes: 49 additions & 0 deletions src/Conversions/ImageGenerators/Avif.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Spatie\MediaLibrary\Conversions\ImageGenerators;

use Illuminate\Support\Collection;
use Spatie\MediaLibrary\Conversions\Conversion;

class Avif extends ImageGenerator
{
public function convert(string $file, Conversion $conversion = null): string
{
$pathToImageFile = pathinfo($file, PATHINFO_DIRNAME).'/'.pathinfo($file, PATHINFO_FILENAME).'.png';

$image = imagecreatefromavif($file);

imagepng($image, $pathToImageFile, 9);

imagedestroy($image);

return $pathToImageFile;
}

public function requirementsAreInstalled(): bool
{
if (! function_exists('imagecreatefromavif')) {
return false;
}

if (! function_exists('imagepng')) {
return false;
}

if (! function_exists('imagedestroy')) {
return false;
}

return true;
}

public function supportedExtensions(): Collection
{
return collect(['avif']);
}

public function supportedMimeTypes(): Collection
{
return collect(['image/avif']);
}
}
4 changes: 2 additions & 2 deletions src/Conversions/ImageGenerators/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function requirementsAreInstalled(): bool

public function supportedExtensions(): Collection
{
$extensions = ['png', 'jpg', 'jpeg', 'gif', 'webp'];
$extensions = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'avif'];
if (config('media-library.image_driver') === 'imagick') {
$extensions[] = 'tiff';
}
Expand All @@ -29,7 +29,7 @@ public function supportedExtensions(): Collection

public function supportedMimeTypes(): Collection
{
$mimeTypes = ['image/jpeg', 'image/gif', 'image/png', 'image/webp'];
$mimeTypes = ['image/jpeg', 'image/gif', 'image/png', 'image/webp', 'image/avif'];
if (config('media-library.image_driver') === 'imagick') {
$mimeTypes[] = 'image/tiff';
}
Expand Down
19 changes: 19 additions & 0 deletions tests/Conversions/ImageGenerators/AvifTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

use Spatie\MediaLibrary\Conversions\ImageGenerators\Avif;

it('can convert a avif', function () {
$imageGenerator = new Avif();

if (! $imageGenerator->requirementsAreInstalled()) {
$this->markTestSkipped('Skipping avif test because requirements to run it are not met');
}

$media = $this->testModelWithoutMediaConversions->addMedia($this->getTestAvif())->toMediaCollection();

expect($imageGenerator->canConvert($media))->toBeTrue();

$imageFile = $imageGenerator->convert($media->getPath());

expect(mime_content_type($imageFile))->toEqual('image/png');
});
5 changes: 5 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ public function getTestWebp(): string
return $this->getTestFilesDirectory('test.webp');
}

public function getTestAvif(): string
{
return $this->getTestFilesDirectory('test.avif');
}

public function getTestMp4(): string
{
return $this->getTestFilesDirectory('test.mp4');
Expand Down
Binary file added tests/TestSupport/testfiles/test.avif
Binary file not shown.

0 comments on commit 83e902e

Please sign in to comment.