1
0
mirror of https://github.com/Intervention/image.git synced 2025-01-17 12:18:14 +01:00

Supported format detection (#1330)

* Implement data struture for format, media types & file extensions
* Refactor encoder resolving
* Extend type options in encoder methods
* Add DriverInterface::supports()
This commit is contained in:
Oliver Vogel 2024-04-13 18:42:48 +02:00 committed by GitHub
parent 5ee087e711
commit 8f6aabe8b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 991 additions and 58 deletions

View File

@ -6,7 +6,10 @@ namespace Intervention\Image\Drivers\Gd;
use Intervention\Image\Drivers\AbstractDriver;
use Intervention\Image\Exceptions\DriverException;
use Intervention\Image\Exceptions\NotSupportedException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Format;
use Intervention\Image\FileExtension;
use Intervention\Image\Image;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\ColorProcessorInterface;
@ -14,6 +17,7 @@ use Intervention\Image\Interfaces\ColorspaceInterface;
use Intervention\Image\Interfaces\DriverInterface;
use Intervention\Image\Interfaces\FontProcessorInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\MediaType;
class Driver extends AbstractDriver
{
@ -138,4 +142,28 @@ class Driver extends AbstractDriver
{
return new FontProcessor();
}
/**
* {@inheritdoc}
*
* @see DriverInterface::supports()
*/
public function supports(string|Format|FileExtension|MediaType $identifier): bool
{
try {
$format = Format::create($identifier);
} catch (NotSupportedException) {
return false;
}
return match ($format) {
Format::JPEG => boolval(imagetypes() & IMG_JPEG),
Format::WEBP => boolval(imagetypes() & IMG_WEBP),
Format::GIF => boolval(imagetypes() & IMG_GIF),
Format::PNG => boolval(imagetypes() & IMG_PNG),
Format::AVIF => boolval(imagetypes() & IMG_AVIF),
Format::BMP => boolval(imagetypes() & IMG_BMP),
default => false,
};
}
}

View File

@ -8,7 +8,10 @@ use Imagick;
use ImagickPixel;
use Intervention\Image\Drivers\AbstractDriver;
use Intervention\Image\Exceptions\DriverException;
use Intervention\Image\Exceptions\NotSupportedException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Format;
use Intervention\Image\FileExtension;
use Intervention\Image\Image;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\ColorProcessorInterface;
@ -16,6 +19,7 @@ use Intervention\Image\Interfaces\ColorspaceInterface;
use Intervention\Image\Interfaces\DriverInterface;
use Intervention\Image\Interfaces\FontProcessorInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\MediaType;
class Driver extends AbstractDriver
{
@ -141,4 +145,15 @@ class Driver extends AbstractDriver
{
return new FontProcessor();
}
public function supports(string|Format|FileExtension|MediaType $identifier): bool
{
try {
$format = Format::create($identifier);
} catch (NotSupportedException) {
return false;
}
return count(Imagick::queryFormats($format->name)) >= 1;
}
}

View File

@ -4,7 +4,9 @@ declare(strict_types=1);
namespace Intervention\Image\Encoders;
use Error;
use Intervention\Image\Exceptions\EncoderException;
use Intervention\Image\FileExtension;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\ImageInterface;
@ -16,10 +18,10 @@ class FileExtensionEncoder extends AutoEncoder
/**
* Create new encoder instance to encode to format of given file extension
*
* @param null|string $extension Target file extension for example "png"
* @param null|string|FileExtension $extension Target file extension for example "png"
* @return void
*/
public function __construct(public ?string $extension = null, mixed ...$options)
public function __construct(public null|string|FileExtension $extension = null, mixed ...$options)
{
$this->options = $options;
}
@ -31,9 +33,11 @@ class FileExtensionEncoder extends AutoEncoder
*/
public function encode(ImageInterface $image): EncodedImageInterface
{
$extension = is_null($this->extension) ? $image->origin()->fileExtension() : $this->extension;
return $image->encode(
$this->encoderByFileExtension(
is_null($this->extension) ? $image->origin()->fileExtension() : $this->extension
$extension
)
);
}
@ -41,27 +45,22 @@ class FileExtensionEncoder extends AutoEncoder
/**
* Create matching encoder for given file extension
*
* @param string $extension
* @param null|string|FileExtension $extension
* @throws EncoderException
* @return EncoderInterface
*/
protected function encoderByFileExtension(?string $extension): EncoderInterface
protected function encoderByFileExtension(null|string|FileExtension $extension): EncoderInterface
{
if (empty($extension)) {
throw new EncoderException('No encoder found for empty file extension.');
}
return match (strtolower($extension)) {
'webp' => new WebpEncoder(...$this->options),
'avif' => new AvifEncoder(...$this->options),
'jpeg', 'jpg' => new JpegEncoder(...$this->options),
'bmp' => new BmpEncoder(...$this->options),
'gif' => new GifEncoder(...$this->options),
'png' => new PngEncoder(...$this->options),
'tiff', 'tif' => new TiffEncoder(...$this->options),
'jp2', 'j2k', 'jpf', 'jpm', 'jpg2', 'j2c', 'jpc', 'jpx' => new Jpeg2000Encoder(...$this->options),
'heic', 'heif' => new HeicEncoder(...$this->options),
default => throw new EncoderException('No encoder found for file extension (' . $extension . ').'),
};
try {
$extension = is_string($extension) ? FileExtension::from($extension) : $extension;
} catch (Error) {
throw new EncoderException('No encoder found for file extension (' . $extension . ').');
}
return $extension->format()->encoder(...$this->options);
}
}

View File

@ -4,11 +4,13 @@ declare(strict_types=1);
namespace Intervention\Image\Encoders;
use Error;
use Intervention\Image\Drivers\AbstractEncoder;
use Intervention\Image\Exceptions\EncoderException;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\MediaType;
class MediaTypeEncoder extends AbstractEncoder
{
@ -17,10 +19,10 @@ class MediaTypeEncoder extends AbstractEncoder
/**
* Create new encoder instance
*
* @param null|string $mediaType Target media type for example "image/jpeg"
* @param null|string|MediaType $mediaType Target media type for example "image/jpeg"
* @return void
*/
public function __construct(public ?string $mediaType = null, mixed ...$options)
public function __construct(public null|string|MediaType $mediaType = null, mixed ...$options)
{
$this->options = $options;
}
@ -42,38 +44,18 @@ class MediaTypeEncoder extends AbstractEncoder
/**
* Return new encoder by given media (MIME) type
*
* @param string $mediaType
* @param string|MediaType $mediaType
* @throws EncoderException
* @return EncoderInterface
*/
protected function encoderByMediaType(string $mediaType): EncoderInterface
protected function encoderByMediaType(string|MediaType $mediaType): EncoderInterface
{
return match (strtolower($mediaType)) {
'image/webp',
'image/x-webp' => new WebpEncoder(...$this->options),
'image/avif',
'image/x-avif' => new AvifEncoder(...$this->options),
'image/jpeg',
'image/jpg',
'image/pjpeg' => new JpegEncoder(...$this->options),
'image/bmp',
'image/ms-bmp',
'image/x-bitmap',
'image/x-bmp',
'image/x-ms-bmp',
'image/x-win-bitmap',
'image/x-windows-bmp',
'image/x-xbitmap' => new BmpEncoder(...$this->options),
'image/gif' => new GifEncoder(...$this->options),
'image/png',
'image/x-png' => new PngEncoder(...$this->options),
'image/tiff' => new TiffEncoder(...$this->options),
'image/jp2',
'image/jpx',
'image/jpm' => new Jpeg2000Encoder(...$this->options),
'image/heic',
'image/heif', => new HeicEncoder(...$this->options),
default => throw new EncoderException('No encoder found for media type (' . $mediaType . ').'),
};
try {
$mediaType = is_string($mediaType) ? MediaType::from($mediaType) : $mediaType;
} catch (Error) {
throw new EncoderException('No encoder found for media type (' . $mediaType . ').');
}
return $mediaType->format()->encoder(...$this->options);
}
}

58
src/FileExtension.php Normal file
View File

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace Intervention\Image;
enum FileExtension: string
{
case JPG = 'jpg';
case JPEG = 'jpeg';
case WEBP = 'webp';
case AVIF = 'avif';
case BMP = 'bmp';
case GIF = 'gif';
case PNG = 'png';
case TIF = 'tif';
case TIFF = 'tiff';
case JP2 = 'jp2';
case J2K = 'j2k';
case JPF = 'jpf';
case JPM = 'jpm';
case JPG2 = 'jpg2';
case J2C = 'j2c';
case JPC = 'jpc';
case JPX = 'jpx';
case HEIC = 'heic';
case HEIF = 'heif';
/**
* Return the matching format for the current file extension
*
* @return Format
*/
public function format(): Format
{
return match ($this) {
self::JPEG,
self::JPG => Format::JPEG,
self::WEBP => Format::WEBP,
self::GIF => Format::GIF,
self::PNG => Format::PNG,
self::AVIF => Format::AVIF,
self::BMP => Format::BMP,
self::TIF,
self::TIFF => Format::TIFF,
self::JP2,
self::J2K,
self::JPF,
self::JPM,
self::JPG2,
self::J2C,
self::JPC,
self::JPX => Format::JP2,
self::HEIC,
self::HEIF => Format::HEIC,
};
}
}

110
src/Format.php Normal file
View File

@ -0,0 +1,110 @@
<?php
declare(strict_types=1);
namespace Intervention\Image;
use Error;
use Intervention\Image\Encoders\AvifEncoder;
use Intervention\Image\Encoders\BmpEncoder;
use Intervention\Image\Encoders\GifEncoder;
use Intervention\Image\Encoders\HeicEncoder;
use Intervention\Image\Encoders\Jpeg2000Encoder;
use Intervention\Image\Encoders\JpegEncoder;
use Intervention\Image\Encoders\PngEncoder;
use Intervention\Image\Encoders\TiffEncoder;
use Intervention\Image\Encoders\WebpEncoder;
use Intervention\Image\Exceptions\NotSupportedException;
use Intervention\Image\Interfaces\EncoderInterface;
enum Format
{
case AVIF;
case BMP;
case GIF;
case HEIC;
case JP2;
case JPEG;
case PNG;
case TIFF;
case WEBP;
/**
* Create format from given identifier
*
* @param string|Format|MediaType|FileExtension $identifier
* @throws NotSupportedException
* @return Format
*/
public static function create(string|self|MediaType|FileExtension $identifier): self
{
if ($identifier instanceof self) {
return $identifier;
}
if ($identifier instanceof MediaType) {
return $identifier->format();
}
if ($identifier instanceof FileExtension) {
return $identifier->format();
}
try {
$format = MediaType::from(strtolower($identifier))->format();
} catch (Error) {
try {
$format = FileExtension::from(strtolower($identifier))->format();
} catch (Error) {
throw new NotSupportedException('Unable to create format from "' . $identifier . '".');
}
}
return $format;
}
/**
* Return the possible media (MIME) types for the current format
*
* @return array
*/
public function mediaTypes(): array
{
return array_filter(MediaType::cases(), function ($mediaType) {
return $mediaType->format() === $this;
});
}
/**
* Return the possible file extension for the current format
*
* @return array
*/
public function fileExtensions(): array
{
return array_filter(FileExtension::cases(), function ($fileExtension) {
return $fileExtension->format() === $this;
});
}
/**
* Create an encoder instance that matches the format
*
* @param array $options
* @return EncoderInterface
*/
public function encoder(mixed ...$options): EncoderInterface
{
return match ($this) {
self::AVIF => new AvifEncoder(...$options),
self::BMP => new BmpEncoder(...$options),
self::GIF => new GifEncoder(...$options),
self::HEIC => new HeicEncoder(...$options),
self::JP2 => new Jpeg2000Encoder(...$options),
self::JPEG => new JpegEncoder(...$options),
self::PNG => new PngEncoder(...$options),
self::TIFF => new TiffEncoder(...$options),
self::WEBP => new WebpEncoder(...$options),
};
}
}

View File

@ -875,7 +875,7 @@ final class Image implements ImageInterface
*
* @see ImageInterface::encodeByMediaType()
*/
public function encodeByMediaType(?string $type = null, mixed ...$options): EncodedImageInterface
public function encodeByMediaType(null|string|MediaType $type = null, mixed ...$options): EncodedImageInterface
{
return $this->encode(new MediaTypeEncoder($type, ...$options));
}
@ -885,8 +885,10 @@ final class Image implements ImageInterface
*
* @see ImageInterface::encodeByExtension()
*/
public function encodeByExtension(?string $extension = null, mixed ...$options): EncodedImageInterface
{
public function encodeByExtension(
null|string|FileExtension $extension = null,
mixed ...$options
): EncodedImageInterface {
return $this->encode(new FileExtensionEncoder($extension, ...$options));
}

View File

@ -7,6 +7,9 @@ namespace Intervention\Image\Interfaces;
use Intervention\Image\Exceptions\DriverException;
use Intervention\Image\Exceptions\NotSupportedException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\FileExtension;
use Intervention\Image\Format;
use Intervention\Image\MediaType;
interface DriverInterface
{
@ -87,4 +90,13 @@ interface DriverInterface
* @return void
*/
public function checkHealth(): void;
/**
* Check if the current driver supports the given format and if the
* underlying PHP extension was built with support for the format.
*
* @param string|Format|FileExtension|MediaType $identifier
* @return bool
*/
public function supports(string|Format|FileExtension|MediaType $identifier): bool;
}

View File

@ -8,6 +8,8 @@ use Countable;
use Intervention\Image\Encoders\AutoEncoder;
use Intervention\Image\Exceptions\AnimationException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\FileExtension;
use Intervention\Image\MediaType;
use Intervention\Image\Origin;
use IteratorAggregate;
@ -739,11 +741,11 @@ interface ImageInterface extends IteratorAggregate, Countable
* will be encoded to the format of the originally read image.
*
* @link https://image.intervention.io/v3/basics/image-output#encode-images-by-media-mime-type
* @param null|string $type
* @param null|string|MediaType $type
* @throws RuntimeException
* @return EncodedImageInterface
*/
public function encodeByMediaType(?string $type = null, mixed ...$options): EncodedImageInterface;
public function encodeByMediaType(null|string|MediaType $type = null, mixed ...$options): EncodedImageInterface;
/**
* Encode the image into the format represented by the given extension. If no
@ -751,11 +753,14 @@ interface ImageInterface extends IteratorAggregate, Countable
* originally read image.
*
* @link https://image.intervention.io/v3/basics/image-output#encode-images-by-file-extension
* @param null|string $extension
* @param null|string|FileExtension $extension
* @throws RuntimeException
* @return EncodedImageInterface
*/
public function encodeByExtension(?string $extension = null, mixed ...$options): EncodedImageInterface;
public function encodeByExtension(
null|string|FileExtension $extension = null,
mixed ...$options
): EncodedImageInterface;
/**
* Encode the image into the format represented by the given extension of

68
src/MediaType.php Normal file
View File

@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
namespace Intervention\Image;
enum MediaType: string
{
case IMAGE_JPEG = 'image/jpeg';
case IMAGE_JPG = 'image/jpg';
case IMAGE_PJPEG = 'image/pjpeg';
case IMAGE_WEBP = 'image/webp';
case IMAGE_X_WEBP = 'image/x-webp';
case IMAGE_GIF = 'image/gif';
case IMAGE_PNG = 'image/png';
case IMAGE_X_PNG = 'image/x-png';
case IMAGE_AVIF = 'image/avif';
case IMAGE_X_AVIF = 'image/x-avif';
case IMAGE_BMP = 'image/bmp';
case IMAGE_MS_BMP = 'image/ms-bmp';
case IMAGE_X_BITMAP = 'image/x-bitmap';
case IMAGE_X_BMP = 'image/x-bmp';
case IMAGE_X_MS_BMP = 'image/x-ms-bmp';
case IMAGE_X_WINDOWS_BMP = 'image/x-windows-bmp';
case IMAGE_X_WIN_BITMAP = 'image/x-win-bitmap';
case IMAGE_X_XBITMAP = 'image/x-xbitmap';
case IMAGE_TIFF = 'image/tiff';
case IMAGE_JP2 = 'image/jp2';
case IMAGE_JPX = 'image/jpx';
case IMAGE_JPM = 'image/jpm';
case IMAGE_HEIC = 'image/heic';
case IMAGE_HEIF = 'image/heif';
/**
* Return the matching format for the current media (MIME) type
*
* @return Format
*/
public function format(): Format
{
return match ($this) {
self::IMAGE_JPEG,
self::IMAGE_JPG,
self::IMAGE_PJPEG => Format::JPEG,
self::IMAGE_WEBP,
self::IMAGE_X_WEBP => Format::WEBP,
self::IMAGE_GIF => Format::GIF,
self::IMAGE_PNG,
self::IMAGE_X_PNG => Format::PNG,
self::IMAGE_AVIF,
self::IMAGE_X_AVIF => Format::AVIF,
self::IMAGE_BMP,
self::IMAGE_MS_BMP,
self::IMAGE_X_BITMAP,
self::IMAGE_X_BMP,
self::IMAGE_X_MS_BMP,
self::IMAGE_X_XBITMAP,
self::IMAGE_X_WINDOWS_BMP,
self::IMAGE_X_WIN_BITMAP => Format::BMP,
self::IMAGE_TIFF => Format::TIFF,
self::IMAGE_JP2,
self::IMAGE_JPX,
self::IMAGE_JPM => Format::JP2,
self::IMAGE_HEIF,
self::IMAGE_HEIC => Format::HEIC,
};
}
}

View File

@ -7,10 +7,14 @@ namespace Intervention\Image\Tests\Unit\Drivers\Gd;
use Intervention\Image\Colors\Rgb\Colorspace;
use Intervention\Image\Colors\Rgb\Decoders\HexColorDecoder;
use Intervention\Image\Drivers\Gd\Driver;
use Intervention\Image\FileExtension;
use Intervention\Image\Format;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\ColorProcessorInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\MediaType;
use Intervention\Image\Tests\BaseTestCase;
use PHPUnit\Framework\Attributes\DataProvider;
final class DriverTest extends BaseTestCase
{
@ -81,4 +85,122 @@ final class DriverTest extends BaseTestCase
$result = $this->driver->colorProcessor(new Colorspace());
$this->assertInstanceOf(ColorProcessorInterface::class, $result);
}
#[DataProvider('supportsDataProvider')]
public function testSupports(bool $result, mixed $identifier): void
{
$this->assertEquals($result, $this->driver->supports($identifier));
}
public static function supportsDataProvider(): array
{
return [
[true, Format::JPEG],
[true, MediaType::IMAGE_JPEG],
[true, MediaType::IMAGE_JPG],
[true, FileExtension::JPG],
[true, FileExtension::JPEG],
[true, 'jpg'],
[true, 'jpeg'],
[true, 'image/jpg'],
[true, 'image/jpeg'],
[true, Format::WEBP],
[true, MediaType::IMAGE_WEBP],
[true, MediaType::IMAGE_X_WEBP],
[true, FileExtension::WEBP],
[true, 'webp'],
[true, 'image/webp'],
[true, 'image/x-webp'],
[true, Format::GIF],
[true, MediaType::IMAGE_GIF],
[true, FileExtension::GIF],
[true, 'gif'],
[true, 'image/gif'],
[true, Format::PNG],
[true, MediaType::IMAGE_PNG],
[true, MediaType::IMAGE_X_PNG],
[true, FileExtension::PNG],
[true, 'png'],
[true, 'image/png'],
[true, 'image/x-png'],
[true, Format::AVIF],
[true, MediaType::IMAGE_AVIF],
[true, MediaType::IMAGE_X_AVIF],
[true, FileExtension::AVIF],
[true, 'avif'],
[true, 'image/avif'],
[true, 'image/x-avif'],
[true, Format::BMP],
[true, FileExtension::BMP],
[true, MediaType::IMAGE_BMP],
[true, MediaType::IMAGE_MS_BMP],
[true, MediaType::IMAGE_X_BITMAP],
[true, MediaType::IMAGE_X_BMP],
[true, MediaType::IMAGE_X_MS_BMP],
[true, MediaType::IMAGE_X_WINDOWS_BMP],
[true, MediaType::IMAGE_X_WIN_BITMAP],
[true, MediaType::IMAGE_X_XBITMAP],
[true, 'bmp'],
[true, 'image/bmp'],
[true, 'image/ms-bmp'],
[true, 'image/x-bitmap'],
[true, 'image/x-bmp'],
[true, 'image/x-ms-bmp'],
[true, 'image/x-windows-bmp'],
[true, 'image/x-win-bitmap'],
[true, 'image/x-xbitmap'],
[false, Format::TIFF],
[false, MediaType::IMAGE_TIFF],
[false, FileExtension::TIFF],
[false, FileExtension::TIF],
[false, 'tif'],
[false, 'tiff'],
[false, 'image/tiff'],
[false, Format::JP2],
[false, MediaType::IMAGE_JP2],
[false, MediaType::IMAGE_JPX],
[false, MediaType::IMAGE_JPM],
[false, FileExtension::TIFF],
[false, FileExtension::TIF],
[false, FileExtension::JP2],
[false, FileExtension::J2K],
[false, FileExtension::JPF],
[false, FileExtension::JPM],
[false, FileExtension::JPG2],
[false, FileExtension::J2C],
[false, FileExtension::JPC],
[false, FileExtension::JPX],
[false, 'jp2'],
[false, 'j2k'],
[false, 'jpf'],
[false, 'jpm'],
[false, 'jpg2'],
[false, 'j2c'],
[false, 'jpc'],
[false, 'jpx'],
[false, Format::HEIC],
[false, MediaType::IMAGE_HEIC],
[false, MediaType::IMAGE_HEIF],
[false, FileExtension::HEIC],
[false, FileExtension::HEIF],
[false, 'heic'],
[false, 'heif'],
[false, 'image/heic'],
[false, 'image/heif'],
[false, 'tga'],
[false, 'image/tga'],
[false, 'image/x-targa'],
[false, 'foo'],
[false, ''],
];
}
}

View File

@ -15,12 +15,14 @@ use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\PngEncoder;
use Intervention\Image\Exceptions\EncoderException;
use Intervention\Image\Exceptions\NotSupportedException;
use Intervention\Image\FileExtension;
use Intervention\Image\Image;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\ColorspaceInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\ResolutionInterface;
use Intervention\Image\Interfaces\SizeInterface;
use Intervention\Image\MediaType;
use Intervention\Image\Modifiers\GreyscaleModifier;
use Intervention\Image\Tests\GdTestCase;
use Intervention\Image\Typography\Font;
@ -153,6 +155,10 @@ final class ImageTest extends GdTestCase
$result = $this->readTestImage('blue.gif')->encodeByMediaType('image/png');
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
$result = $this->readTestImage('blue.gif')->encodeByMediaType(MediaType::IMAGE_PNG);
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
}
public function testEncodeByExtension(): void
@ -164,6 +170,10 @@ final class ImageTest extends GdTestCase
$result = $this->readTestImage('blue.gif')->encodeByExtension('png');
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
$result = $this->readTestImage('blue.gif')->encodeByExtension(FileExtension::PNG);
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
}
public function testEncodeByPath(): void

View File

@ -7,10 +7,14 @@ namespace Intervention\Image\Tests\Unit\Drivers\Imagick;
use Intervention\Image\Colors\Rgb\Colorspace;
use Intervention\Image\Colors\Rgb\Decoders\HexColorDecoder;
use Intervention\Image\Drivers\Imagick\Driver;
use Intervention\Image\FileExtension;
use Intervention\Image\Format;
use Intervention\Image\Interfaces\ColorInterface;
use Intervention\Image\Interfaces\ColorProcessorInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\MediaType;
use Intervention\Image\Tests\BaseTestCase;
use PHPUnit\Framework\Attributes\DataProvider;
final class DriverTest extends BaseTestCase
{
@ -81,4 +85,122 @@ final class DriverTest extends BaseTestCase
$result = $this->driver->colorProcessor(new Colorspace());
$this->assertInstanceOf(ColorProcessorInterface::class, $result);
}
#[DataProvider('supportsDataProvider')]
public function testSupports(bool $result, mixed $identifier): void
{
$this->assertEquals($result, $this->driver->supports($identifier));
}
public static function supportsDataProvider(): array
{
return [
[true, Format::JPEG],
[true, MediaType::IMAGE_JPEG],
[true, MediaType::IMAGE_JPG],
[true, FileExtension::JPG],
[true, FileExtension::JPEG],
[true, 'jpg'],
[true, 'jpeg'],
[true, 'image/jpg'],
[true, 'image/jpeg'],
[true, Format::WEBP],
[true, MediaType::IMAGE_WEBP],
[true, MediaType::IMAGE_X_WEBP],
[true, FileExtension::WEBP],
[true, 'webp'],
[true, 'image/webp'],
[true, 'image/x-webp'],
[true, Format::GIF],
[true, MediaType::IMAGE_GIF],
[true, FileExtension::GIF],
[true, 'gif'],
[true, 'image/gif'],
[true, Format::PNG],
[true, MediaType::IMAGE_PNG],
[true, MediaType::IMAGE_X_PNG],
[true, FileExtension::PNG],
[true, 'png'],
[true, 'image/png'],
[true, 'image/x-png'],
[true, Format::AVIF],
[true, MediaType::IMAGE_AVIF],
[true, MediaType::IMAGE_X_AVIF],
[true, FileExtension::AVIF],
[true, 'avif'],
[true, 'image/avif'],
[true, 'image/x-avif'],
[true, Format::BMP],
[true, FileExtension::BMP],
[true, MediaType::IMAGE_BMP],
[true, MediaType::IMAGE_MS_BMP],
[true, MediaType::IMAGE_X_BITMAP],
[true, MediaType::IMAGE_X_BMP],
[true, MediaType::IMAGE_X_MS_BMP],
[true, MediaType::IMAGE_X_WINDOWS_BMP],
[true, MediaType::IMAGE_X_WIN_BITMAP],
[true, MediaType::IMAGE_X_XBITMAP],
[true, 'bmp'],
[true, 'image/bmp'],
[true, 'image/ms-bmp'],
[true, 'image/x-bitmap'],
[true, 'image/x-bmp'],
[true, 'image/x-ms-bmp'],
[true, 'image/x-windows-bmp'],
[true, 'image/x-win-bitmap'],
[true, 'image/x-xbitmap'],
[true, Format::TIFF],
[true, MediaType::IMAGE_TIFF],
[true, FileExtension::TIFF],
[true, FileExtension::TIF],
[true, 'tif'],
[true, 'tiff'],
[true, 'image/tiff'],
[true, Format::JP2],
[true, MediaType::IMAGE_JP2],
[true, MediaType::IMAGE_JPX],
[true, MediaType::IMAGE_JPM],
[true, FileExtension::TIFF],
[true, FileExtension::TIF],
[true, FileExtension::JP2],
[true, FileExtension::J2K],
[true, FileExtension::JPF],
[true, FileExtension::JPM],
[true, FileExtension::JPG2],
[true, FileExtension::J2C],
[true, FileExtension::JPC],
[true, FileExtension::JPX],
[true, 'jp2'],
[true, 'j2k'],
[true, 'jpf'],
[true, 'jpm'],
[true, 'jpg2'],
[true, 'j2c'],
[true, 'jpc'],
[true, 'jpx'],
[true, Format::HEIC],
[true, MediaType::IMAGE_HEIC],
[true, MediaType::IMAGE_HEIF],
[true, FileExtension::HEIC],
[true, FileExtension::HEIF],
[true, 'heic'],
[true, 'heif'],
[true, 'image/heic'],
[true, 'image/heif'],
[false, 'tga'],
[false, 'image/tga'],
[false, 'image/x-targa'],
[false, 'foo'],
[false, ''],
];
}
}

View File

@ -15,12 +15,13 @@ use Intervention\Image\Encoders\PngEncoder;
use Intervention\Image\Encoders\TiffEncoder;
use Intervention\Image\Encoders\WebpEncoder;
use Intervention\Image\Exceptions\EncoderException;
use Intervention\Image\FileExtension;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Tests\BaseTestCase;
final class FileExtensionEncoderTest extends BaseTestCase
{
private function testEncoder(string $extension): EncoderInterface
private function testEncoder(string|FileExtension $extension): EncoderInterface
{
$encoder = new class () extends FileExtensionEncoder
{
@ -33,9 +34,8 @@ final class FileExtensionEncoderTest extends BaseTestCase
return $encoder->test($extension);
}
public function testEncoderByFileExtension(): void
public function testEncoderByFileExtensionString(): void
{
$this->assertInstanceOf(
WebpEncoder::class,
$this->testEncoder('webp')
@ -82,6 +82,54 @@ final class FileExtensionEncoderTest extends BaseTestCase
);
}
public function testEncoderByFileExtensionEnumMember(): void
{
$this->assertInstanceOf(
WebpEncoder::class,
$this->testEncoder(FileExtension::WEBP)
);
$this->assertInstanceOf(
AvifEncoder::class,
$this->testEncoder(FileExtension::AVIF)
);
$this->assertInstanceOf(
JpegEncoder::class,
$this->testEncoder(FileExtension::JPG)
);
$this->assertInstanceOf(
BmpEncoder::class,
$this->testEncoder(FileExtension::BMP)
);
$this->assertInstanceOf(
GifEncoder::class,
$this->testEncoder(FileExtension::GIF)
);
$this->assertInstanceOf(
PngEncoder::class,
$this->testEncoder(FileExtension::PNG)
);
$this->assertInstanceOf(
TiffEncoder::class,
$this->testEncoder(FileExtension::TIF)
);
$this->assertInstanceOf(
Jpeg2000Encoder::class,
$this->testEncoder(FileExtension::JPG2)
);
$this->assertInstanceOf(
HeicEncoder::class,
$this->testEncoder(FileExtension::HEIC)
);
}
public function testEncoderByFileExtensionUnknown(): void
{
$this->expectException(EncoderException::class);

View File

@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
namespace Intervention\Image\Tests\Unit;
use Intervention\Image\FileExtension;
use Intervention\Image\Format;
use Intervention\Image\Tests\BaseTestCase;
final class FileExtensionTest extends BaseTestCase
{
public function testFormatJpeg(): void
{
$ext = FileExtension::JPEG;
$this->assertEquals(Format::JPEG, $ext->format());
$ext = FileExtension::JPG;
$this->assertEquals(Format::JPEG, $ext->format());
}
public function testFormatWebp(): void
{
$ext = FileExtension::WEBP;
$this->assertEquals(Format::WEBP, $ext->format());
}
public function testFormatGif(): void
{
$ext = FileExtension::GIF;
$this->assertEquals(Format::GIF, $ext->format());
}
public function testFormatPng(): void
{
$ext = FileExtension::PNG;
$this->assertEquals(Format::PNG, $ext->format());
}
public function testFormatAvif(): void
{
$ext = FileExtension::AVIF;
$this->assertEquals(Format::AVIF, $ext->format());
}
public function testFormatBmp(): void
{
$ext = FileExtension::BMP;
$this->assertEquals(Format::BMP, $ext->format());
}
public function testFormatTiff(): void
{
$ext = FileExtension::TIFF;
$this->assertEquals(Format::TIFF, $ext->format());
$ext = FileExtension::TIF;
$this->assertEquals(Format::TIFF, $ext->format());
}
public function testFormatJpeg2000(): void
{
$ext = FileExtension::JP2;
$this->assertEquals(Format::JP2, $ext->format());
$ext = FileExtension::J2K;
$this->assertEquals(Format::JP2, $ext->format());
$ext = FileExtension::J2C;
$this->assertEquals(Format::JP2, $ext->format());
$ext = FileExtension::JPG2;
$this->assertEquals(Format::JP2, $ext->format());
}
public function testFormatHeic(): void
{
$ext = FileExtension::HEIC;
$this->assertEquals(Format::HEIC, $ext->format());
$ext = FileExtension::HEIF;
$this->assertEquals(Format::HEIC, $ext->format());
}
}

166
tests/Unit/FormatTest.php Normal file
View File

@ -0,0 +1,166 @@
<?php
declare(strict_types=1);
namespace Intervention\Image\Tests\Unit;
use Intervention\Image\Encoders\AvifEncoder;
use Intervention\Image\Encoders\BmpEncoder;
use Intervention\Image\Encoders\GifEncoder;
use Intervention\Image\Encoders\HeicEncoder;
use Intervention\Image\Encoders\Jpeg2000Encoder;
use Intervention\Image\Encoders\JpegEncoder;
use Intervention\Image\Encoders\PngEncoder;
use Intervention\Image\Encoders\TiffEncoder;
use Intervention\Image\Encoders\WebpEncoder;
use Intervention\Image\Exceptions\NotSupportedException;
use Intervention\Image\FileExtension;
use Intervention\Image\Format;
use Intervention\Image\MediaType;
use Intervention\Image\Tests\BaseTestCase;
final class FormatTest extends BaseTestCase
{
public function testCreate(): void
{
$this->assertEquals(Format::JPEG, Format::create(Format::JPEG));
$this->assertEquals(Format::JPEG, Format::create('jpg'));
$this->assertEquals(Format::JPEG, Format::create('jpeg'));
$this->assertEquals(Format::JPEG, Format::create('image/jpeg'));
$this->assertEquals(Format::GIF, Format::create('image/gif'));
$this->assertEquals(Format::PNG, Format::create(FileExtension::PNG));
$this->assertEquals(Format::WEBP, Format::create(MediaType::IMAGE_WEBP));
}
public function testCreateUnknown(): void
{
$this->expectException(NotSupportedException::class);
Format::create('foo');
}
public function testMediaTypesJpeg(): void
{
$format = Format::JPEG;
$mediaTypes = $format->mediaTypes();
$this->assertIsArray($mediaTypes);
$this->assertCount(3, $mediaTypes);
}
public function testMediaTypesWebp(): void
{
$format = Format::WEBP;
$mediaTypes = $format->mediaTypes();
$this->assertIsArray($mediaTypes);
$this->assertCount(2, $mediaTypes);
}
public function testMediaTypesFGif(): void
{
$format = Format::GIF;
$mediaTypes = $format->mediaTypes();
$this->assertIsArray($mediaTypes);
$this->assertCount(1, $mediaTypes);
}
public function testMediaTypesPng(): void
{
$format = Format::PNG;
$mediaTypes = $format->mediaTypes();
$this->assertIsArray($mediaTypes);
$this->assertCount(2, $mediaTypes);
}
public function testMediaTypesAvif(): void
{
$format = Format::AVIF;
$mediaTypes = $format->mediaTypes();
$this->assertIsArray($mediaTypes);
$this->assertCount(2, $mediaTypes);
}
public function testMediaTypesBmp(): void
{
$format = Format::BMP;
$mediaTypes = $format->mediaTypes();
$this->assertIsArray($mediaTypes);
$this->assertCount(8, $mediaTypes);
}
public function testMediaTypesTiff(): void
{
$format = Format::TIFF;
$mediaTypes = $format->mediaTypes();
$this->assertIsArray($mediaTypes);
$this->assertCount(1, $mediaTypes);
}
public function testMediaTypesJpeg2000(): void
{
$format = Format::JP2;
$mediaTypes = $format->mediaTypes();
$this->assertIsArray($mediaTypes);
$this->assertCount(3, $mediaTypes);
}
public function testMediaTypesHeic(): void
{
$format = Format::HEIC;
$mediaTypes = $format->mediaTypes();
$this->assertIsArray($mediaTypes);
$this->assertCount(2, $mediaTypes);
}
public function testEncoderJpeg(): void
{
$format = Format::JPEG;
$this->assertInstanceOf(JpegEncoder::class, $format->encoder());
}
public function testEncoderAvif(): void
{
$format = Format::AVIF;
$this->assertInstanceOf(AvifEncoder::class, $format->encoder());
}
public function testEncoderWebp(): void
{
$format = Format::WEBP;
$this->assertInstanceOf(WebpEncoder::class, $format->encoder());
}
public function testEncoderGif(): void
{
$format = Format::GIF;
$this->assertInstanceOf(GifEncoder::class, $format->encoder());
}
public function testEncoderPng(): void
{
$format = Format::PNG;
$this->assertInstanceOf(PngEncoder::class, $format->encoder());
}
public function testEncoderBitmap(): void
{
$format = Format::BMP;
$this->assertInstanceOf(BmpEncoder::class, $format->encoder());
}
public function testEncoderTiff(): void
{
$format = Format::TIFF;
$this->assertInstanceOf(TiffEncoder::class, $format->encoder());
}
public function testEncoderJpep2000(): void
{
$format = Format::JP2;
$this->assertInstanceOf(Jpeg2000Encoder::class, $format->encoder());
}
public function testEncoderHeic(): void
{
$format = Format::HEIC;
$this->assertInstanceOf(HeicEncoder::class, $format->encoder());
}
}

View File

@ -0,0 +1,102 @@
<?php
declare(strict_types=1);
namespace Intervention\Image\Tests\Unit;
use Intervention\Image\Format;
use Intervention\Image\MediaType;
use Intervention\Image\Tests\BaseTestCase;
final class MediaTypeTest extends BaseTestCase
{
public function testFormatJpeg(): void
{
$mime = MediaType::IMAGE_JPEG;
$this->assertEquals(Format::JPEG, $mime->format());
$mime = MediaType::IMAGE_PJPEG;
$this->assertEquals(Format::JPEG, $mime->format());
$mime = MediaType::IMAGE_JPG;
$this->assertEquals(Format::JPEG, $mime->format());
}
public function testFormatWebp(): void
{
$mime = MediaType::IMAGE_WEBP;
$this->assertEquals(Format::WEBP, $mime->format());
$mime = MediaType::IMAGE_X_WEBP;
$this->assertEquals(Format::WEBP, $mime->format());
}
public function testFormatGif(): void
{
$mime = MediaType::IMAGE_GIF;
$this->assertEquals(Format::GIF, $mime->format());
}
public function testFormatPng(): void
{
$mime = MediaType::IMAGE_PNG;
$this->assertEquals(Format::PNG, $mime->format());
$mime = MediaType::IMAGE_X_PNG;
$this->assertEquals(Format::PNG, $mime->format());
}
public function testFormatAvif(): void
{
$mime = MediaType::IMAGE_AVIF;
$this->assertEquals(Format::AVIF, $mime->format());
$mime = MediaType::IMAGE_X_AVIF;
$this->assertEquals(Format::AVIF, $mime->format());
}
public function testFormatBmp(): void
{
$mime = MediaType::IMAGE_BMP;
$this->assertEquals(Format::BMP, $mime->format());
$mime = MediaType::IMAGE_X_BMP;
$this->assertEquals(Format::BMP, $mime->format());
$mime = MediaType::IMAGE_X_BITMAP;
$this->assertEquals(Format::BMP, $mime->format());
$mime = MediaType::IMAGE_X_WIN_BITMAP;
$this->assertEquals(Format::BMP, $mime->format());
$mime = MediaType::IMAGE_X_WINDOWS_BMP;
$this->assertEquals(Format::BMP, $mime->format());
}
public function testFormatTiff(): void
{
$mime = MediaType::IMAGE_TIFF;
$this->assertEquals(Format::TIFF, $mime->format());
}
public function testFormatJpeg2000(): void
{
$mime = MediaType::IMAGE_JPM;
$this->assertEquals(Format::JP2, $mime->format());
$mime = MediaType::IMAGE_JPX;
$this->assertEquals(Format::JP2, $mime->format());
$mime = MediaType::IMAGE_JP2;
$this->assertEquals(Format::JP2, $mime->format());
}
public function testFormatHeic(): void
{
$mime = MediaType::IMAGE_HEIC;
$this->assertEquals(Format::HEIC, $mime->format());
$mime = MediaType::IMAGE_HEIF;
$this->assertEquals(Format::HEIC, $mime->format());
}
}