1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-31 09:31:53 +02:00

Merge pull request #1130 from GwendolenLynch/driver-webp-support

[Next] Webp encoders for GD & ImageMagick
This commit is contained in:
Oliver Vogel
2022-02-09 19:34:46 +01:00
committed by GitHub
8 changed files with 197 additions and 8 deletions

View File

@@ -4,9 +4,7 @@ namespace Intervention\Image\Drivers\Abstract;
use Intervention\Image\Collection;
use Intervention\Image\EncodedImage;
use Intervention\Image\Exceptions\NotWritableException;
use Intervention\Image\Geometry\Point;
use Intervention\Image\Geometry\Resizer;
use Intervention\Image\Geometry\Size;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\FrameInterface;
@@ -92,6 +90,13 @@ abstract class AbstractImage
);
}
public function toWebp(int $quality = 75): EncodedImage
{
return $this->encode(
$this->resolveDriverClass('Encoders\WebpEncoder', $quality)
);
}
public function toGif(): EncodedImage
{
return $this->encode(

View File

@@ -0,0 +1,25 @@
<?php
namespace Intervention\Image\Drivers\Gd\Encoders;
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
use Intervention\Image\EncodedImage;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\ImageInterface;
class WebpEncoder extends AbstractEncoder implements EncoderInterface
{
public function __construct(int $quality)
{
$this->quality = $quality;
}
public function encode(ImageInterface $image): EncodedImage
{
$data = $this->getBuffered(function () use ($image) {
imagewebp($image->getFrames()->first()->getCore(), null, $this->quality);
});
return new EncodedImage($data, 'image/webp');
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Intervention\Image\Drivers\Imagick\Encoders;
use Imagick;
use ImagickPixel;
use Intervention\Image\Drivers\Abstract\Encoders\AbstractEncoder;
use Intervention\Image\EncodedImage;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\ImageInterface;
class WebpEncoder extends AbstractEncoder implements EncoderInterface
{
public function __construct(int $quality)
{
$this->quality = $quality;
}
public function encode(ImageInterface $image): EncodedImage
{
$format = 'webp';
$compression = Imagick::COMPRESSION_ZIP;
$imagick = $image->getFrames()->first()->getCore();
$imagick->setImageBackgroundColor(new ImagickPixel('transparent'));
$imagick = $imagick->mergeImageLayers(Imagick::LAYERMETHOD_MERGE);
$imagick->setFormat($format);
$imagick->setImageFormat($format);
$imagick->setCompression($compression);
$imagick->setImageCompression($compression);
$imagick->setImageCompressionQuality($this->quality);
return new EncodedImage($imagick->getImagesBlob(), 'image/webp');
}
}

View File

@@ -4,9 +4,6 @@ namespace Intervention\Image\Interfaces;
use Intervention\Image\Collection;
use Intervention\Image\EncodedImage;
use Intervention\Image\Interfaces\FrameInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SizeInterface;
interface ImageInterface
{
@@ -21,6 +18,7 @@ interface ImageInterface
public function modify(ModifierInterface $modifier): ImageInterface;
public function encode(EncoderInterface $encoder): EncodedImage;
public function toJpeg(int $quality = 75): EncodedImage;
public function toWebp(int $quality = 75): EncodedImage;
public function toGif(): EncodedImage;
public function toPng(): EncodedImage;
public function pickColors(int $x, int $y): Collection;

View File

@@ -3,7 +3,6 @@
namespace Intervention\Image\Tests;
use Intervention\Image\Collection;
use Intervention\Image\Drivers\Abstract\AbstractFrame;
use Intervention\Image\Drivers\Abstract\AbstractImage;
use Intervention\Image\EncodedImage;
use Intervention\Image\Geometry\Size;
@@ -130,13 +129,29 @@ class AbstractImageTest extends TestCase
$encoder->shouldReceive('encode')->with($img)->andReturn($encoded);
$img->shouldReceive('resolveDriverClass')
->with('Encoders\JpegEncoder', 45)
->andReturn($encoder);
->with('Encoders\JpegEncoder', 45)
->andReturn($encoder);
$result = $img->toJpeg(45);
$this->assertInstanceOf(EncodedImage::class, $result);
}
public function testToWebp(): void
{
$img = $this->abstractImageMock();
$encoded = Mockery::mock(EncodedImage::class);
$encoder = Mockery::mock(EncoderInterface::class);
$encoder->shouldReceive('encode')->with($img)->andReturn($encoded);
$img->shouldReceive('resolveDriverClass')
->with('Encoders\WebpEncoder', 45)
->andReturn($encoder);
$result = $img->toWebp(45);
$this->assertInstanceOf(EncodedImage::class, $result);
}
public function testToGif(): void
{
$img = $this->abstractImageMock();

View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace Intervention\Image\Tests\Drivers\Gd\Encoders;
use Intervention\Image\Collection;
use Intervention\Image\Drivers\Gd\Encoders\WebpEncoder;
use Intervention\Image\Drivers\Gd\Frame;
use Intervention\Image\Drivers\Gd\Image;
use Intervention\MimeSniffer\MimeSniffer;
use Intervention\MimeSniffer\Types\ImageWebp;
use PHPUnit\Framework\TestCase;
/**
* @requires extension gd
*/
final class WebpEncoderTest extends TestCase
{
protected function getTestImage(): Image
{
$frame = new Frame(imagecreatetruecolor(3, 2));
return new Image(new Collection([$frame]));
}
public function testEncode(): void
{
$image = $this->getTestImage();
$encoder = new WebpEncoder(75);
$result = $encoder->encode($image);
$this->assertTrue(MimeSniffer::createFromString((string) $result)->matches(new ImageWebp()));
}
}

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace Intervention\Image\Tests\Drivers\Imagick\Encoders;
use Imagick;
use ImagickPixel;
use Intervention\Image\Collection;
use Intervention\Image\Drivers\Imagick\Encoders\PngEncoder;
use Intervention\Image\Drivers\Imagick\Frame;
use Intervention\Image\Drivers\Imagick\Image;
use Intervention\MimeSniffer\MimeSniffer;
use Intervention\MimeSniffer\Types\ImagePng;
use PHPUnit\Framework\TestCase;
/**
* @requires extension imagick
*/
final class PngEncoderTest extends TestCase
{
protected function getTestImage(): Image
{
$imagick = new Imagick();
$imagick->newImage(3, 2, new ImagickPixel('red'), 'jpg');
$frame = new Frame($imagick);
return new Image(new Collection([$frame]));
}
public function testEncode(): void
{
$image = $this->getTestImage();
$encoder = new PngEncoder(75);
$result = $encoder->encode($image);
$this->assertTrue(MimeSniffer::createFromString((string) $result)->matches(new ImagePng()));
}
}

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace Intervention\Image\Tests\Drivers\Imagick\Encoders;
use Imagick;
use ImagickPixel;
use Intervention\Image\Collection;
use Intervention\Image\Drivers\Imagick\Encoders\WebpEncoder;
use Intervention\Image\Drivers\Imagick\Frame;
use Intervention\Image\Drivers\Imagick\Image;
use Intervention\MimeSniffer\MimeSniffer;
use Intervention\MimeSniffer\Types\ImageWebp;
use PHPUnit\Framework\TestCase;
/**
* @requires extension imagick
*/
final class WebpEncoderTest extends TestCase
{
protected function getTestImage(): Image
{
$imagick = new Imagick();
$imagick->newImage(3, 2, new ImagickPixel('red'), 'png');
$frame = new Frame($imagick);
return new Image(new Collection([$frame]));
}
public function testEncode(): void
{
$image = $this->getTestImage();
$encoder = new WebpEncoder(75);
$result = $encoder->encode($image);
$this->assertTrue(MimeSniffer::createFromString((string) $result)->matches(new ImageWebp()));
}
}