1
0
mirror of https://github.com/Intervention/image.git synced 2025-08-23 22:12:51 +02:00

Switch EncodedImage::class to temporary stream resource

This commit is contained in:
Oliver Vogel
2024-10-06 11:36:17 +02:00
committed by GitHub
parent e244bc9c93
commit e77a33394c
44 changed files with 269 additions and 246 deletions

View File

@@ -21,7 +21,7 @@
"require": {
"php": "^8.1",
"ext-mbstring": "*",
"intervention/gif": "^4.1"
"intervention/gif": "^4.2"
},
"require-dev": {
"phpunit/phpunit": "^10.0",

View File

@@ -4,12 +4,17 @@ declare(strict_types=1);
namespace Intervention\Image\Drivers;
use Intervention\Image\EncodedImage;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Traits\CanBuildFilePointer;
abstract class AbstractEncoder implements EncoderInterface
{
use CanBuildFilePointer;
public const DEFAULT_QUALITY = 75;
/**
@@ -23,18 +28,17 @@ abstract class AbstractEncoder implements EncoderInterface
}
/**
* Get return value of callback through output buffer
* Build new file pointer, run callback with it and return result as encoded image
*
* @param callable $callback
* @return string
* @throws RuntimeException
* @return EncodedImage
*/
protected function buffered(callable $callback): string
protected function createEncodedImage(callable $callback): EncodedImage
{
ob_start();
$callback();
$buffer = ob_get_contents();
ob_end_clean();
$pointer = $this->buildFilePointer();
$callback($pointer);
return $buffer;
return new EncodedImage($pointer);
}
}

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Intervention\Image\Drivers\Gd\Decoders;
use Exception;
use GdImage;
use Intervention\Gif\Decoder as GifDecoder;
use Intervention\Gif\Splitter as GifSplitter;
@@ -76,6 +77,7 @@ class NativeObjectDecoder extends AbstractDecoder
return $image;
}
try {
// create empty core
$core = new Core();
@@ -94,6 +96,9 @@ class NativeObjectDecoder extends AbstractDecoder
new Frame($native, $delays[$key] / 100)
);
}
} catch (Exception $e) {
throw new DecoderException($e->getMessage(), $e->getCode(), $e);
}
// create (possibly) animated image
$image = new Image($this->driver(), $core);

View File

@@ -18,11 +18,8 @@ class AvifEncoder extends GenericAvifEncoder implements SpecializedInterface
*/
public function encode(ImageInterface $image): EncodedImage
{
$gd = $image->core()->native();
$data = $this->buffered(function () use ($gd) {
imageavif($gd, null, $this->quality);
return $this->createEncodedImage(function ($pointer) use ($image) {
imageavif($image->core()->native(), $pointer, $this->quality);
});
return new EncodedImage($data, 'image/avif');
}
}

View File

@@ -18,10 +18,8 @@ class BmpEncoder extends GenericBmpEncoder implements SpecializedInterface
*/
public function encode(ImageInterface $image): EncodedImage
{
$data = $this->buffered(function () use ($image) {
imagebmp($image->core()->native(), null, false);
return $this->createEncodedImage(function ($pointer) use ($image) {
imagebmp($image->core()->native(), $pointer, false);
});
return new EncodedImage($data, 'image/bmp');
}
}

View File

@@ -28,12 +28,11 @@ class GifEncoder extends GenericGifEncoder implements SpecializedInterface
}
$gd = Cloner::clone($image->core()->native());
$data = $this->buffered(function () use ($gd) {
imageinterlace($gd, $this->interlaced);
imagegif($gd);
});
return new EncodedImage($data, 'image/gif');
return $this->createEncodedImage(function ($pointer) use ($gd) {
imageinterlace($gd, $this->interlaced);
imagegif($gd, $pointer);
});
}
/**
@@ -41,6 +40,7 @@ class GifEncoder extends GenericGifEncoder implements SpecializedInterface
*/
protected function encodeAnimated(ImageInterface $image): EncodedImage
{
try {
$builder = GifBuilder::canvas(
$image->width(),
$image->height()
@@ -48,18 +48,17 @@ class GifEncoder extends GenericGifEncoder implements SpecializedInterface
foreach ($image as $frame) {
$builder->addFrame(
source: (string) $this->encode($frame->toImage($image->driver())),
source: $this->encode($frame->toImage($image->driver()))->toFilePointer(),
delay: $frame->delay(),
interlaced: $this->interlaced
);
}
try {
$builder->setLoops($image->loops());
return new EncodedImage($builder->encode());
} catch (Exception $e) {
throw new EncoderException($e->getMessage(), $e->getCode(), $e);
}
return new EncodedImage($builder->encode(), 'image/gif');
}
}

View File

@@ -28,11 +28,9 @@ class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface
background: $blendingColor
);
$data = $this->buffered(function () use ($output) {
return $this->createEncodedImage(function ($pointer) use ($output) {
imageinterlace($output, $this->progressive);
imagejpeg($output, null, $this->quality);
imagejpeg($output, $pointer, $this->quality);
});
return new EncodedImage($data, 'image/jpeg');
}
}

View File

@@ -25,13 +25,10 @@ class PngEncoder extends GenericPngEncoder implements SpecializedInterface
{
$output = $this->prepareOutput($image);
// encode
$data = $this->buffered(function () use ($output) {
return $this->createEncodedImage(function ($pointer) use ($output) {
imageinterlace($output, $this->interlaced);
imagepng($output, null, -1);
imagepng($output, $pointer, -1);
});
return new EncodedImage($data, 'image/png');
}
/**

View File

@@ -19,10 +19,9 @@ class WebpEncoder extends GenericWebpEncoder implements SpecializedInterface
public function encode(ImageInterface $image): EncodedImage
{
$quality = $this->quality === 100 ? IMG_WEBP_LOSSLESS : $this->quality;
$data = $this->buffered(function () use ($image, $quality) {
imagewebp($image->core()->native(), null, $quality);
});
return new EncodedImage($data, 'image/webp');
return $this->createEncodedImage(function ($pointer) use ($image, $quality) {
imagewebp($image->core()->native(), $pointer, $quality);
});
}
}

View File

@@ -7,12 +7,13 @@ namespace Intervention\Image\Drivers\Imagick\Encoders;
use Imagick;
use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\AvifEncoder as GenericAvifEncoder;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
class AvifEncoder extends GenericAvifEncoder implements SpecializedInterface
{
public function encode(ImageInterface $image): EncodedImage
public function encode(ImageInterface $image): EncodedImageInterface
{
$format = 'AVIF';
$compression = Imagick::COMPRESSION_ZIP;
@@ -25,6 +26,6 @@ class AvifEncoder extends GenericAvifEncoder implements SpecializedInterface
$imagick->setCompressionQuality($this->quality);
$imagick->setImageCompressionQuality($this->quality);
return new EncodedImage($imagick->getImagesBlob(), 'image/avif');
return new EncodedImage($imagick->getImagesBlob());
}
}

View File

@@ -7,12 +7,13 @@ namespace Intervention\Image\Drivers\Imagick\Encoders;
use Imagick;
use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\BmpEncoder as GenericBmpEncoder;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
class BmpEncoder extends GenericBmpEncoder implements SpecializedInterface
{
public function encode(ImageInterface $image): EncodedImage
public function encode(ImageInterface $image): EncodedImageInterface
{
$format = 'BMP';
$compression = Imagick::COMPRESSION_NO;
@@ -23,6 +24,6 @@ class BmpEncoder extends GenericBmpEncoder implements SpecializedInterface
$imagick->setCompression($compression);
$imagick->setImageCompression($compression);
return new EncodedImage($imagick->getImagesBlob(), 'image/bmp');
return new EncodedImage($imagick->getImagesBlob());
}
}

View File

@@ -7,12 +7,13 @@ namespace Intervention\Image\Drivers\Imagick\Encoders;
use Imagick;
use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\GifEncoder as GenericGifEncoder;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
class GifEncoder extends GenericGifEncoder implements SpecializedInterface
{
public function encode(ImageInterface $image): EncodedImage
public function encode(ImageInterface $image): EncodedImageInterface
{
$format = 'GIF';
$compression = Imagick::COMPRESSION_LZW;
@@ -28,6 +29,6 @@ class GifEncoder extends GenericGifEncoder implements SpecializedInterface
$imagick->setInterlaceScheme(Imagick::INTERLACE_LINE);
}
return new EncodedImage($imagick->getImagesBlob(), 'image/gif');
return new EncodedImage($imagick->getImagesBlob());
}
}

View File

@@ -6,8 +6,8 @@ namespace Intervention\Image\Drivers\Imagick\Encoders;
use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\HeicEncoder as GenericHeicEncoder;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
class HeicEncoder extends GenericHeicEncoder implements SpecializedInterface
@@ -17,12 +17,11 @@ class HeicEncoder extends GenericHeicEncoder implements SpecializedInterface
$format = 'HEIC';
$imagick = $image->core()->native();
$imagick->setFormat($format);
$imagick->setImageFormat($format);
$imagick->setCompressionQuality($this->quality);
$imagick->setImageCompressionQuality($this->quality);
return new EncodedImage($imagick->getImagesBlob(), 'image/heic');
return new EncodedImage($imagick->getImagesBlob());
}
}

View File

@@ -28,6 +28,6 @@ class Jpeg2000Encoder extends GenericJpeg2000Encoder implements SpecializedInter
$imagick->setCompressionQuality($this->quality);
$imagick->setImageCompressionQuality($this->quality);
return new EncodedImage($imagick->getImagesBlob(), 'image/jp2');
return new EncodedImage($imagick->getImagesBlob());
}
}

View File

@@ -7,12 +7,13 @@ namespace Intervention\Image\Drivers\Imagick\Encoders;
use Imagick;
use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\JpegEncoder as GenericJpegEncoder;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface
{
public function encode(ImageInterface $image): EncodedImage
public function encode(ImageInterface $image): EncodedImageInterface
{
$format = 'JPEG';
$compression = Imagick::COMPRESSION_JPEG;
@@ -44,6 +45,6 @@ class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface
$imagick->setInterlaceScheme(Imagick::INTERLACE_PLANE);
}
return new EncodedImage($imagick->getImagesBlob(), 'image/jpeg');
return new EncodedImage($imagick->getImagesBlob());
}
}

View File

@@ -5,12 +5,9 @@ declare(strict_types=1);
namespace Intervention\Image\Drivers\Imagick\Encoders;
use Imagick;
use ImagickException;
use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\PngEncoder as GenericPngEncoder;
use Intervention\Image\Exceptions\AnimationException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Exceptions\ColorException;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
@@ -21,9 +18,21 @@ class PngEncoder extends GenericPngEncoder implements SpecializedInterface
*
* @see EncoderInterface::encode()
*/
public function encode(ImageInterface $image): EncodedImage
public function encode(ImageInterface $image): EncodedImageInterface
{
$output = $this->prepareOutput($image);
if ($this->indexed) {
// reduce colors
$output = clone $image;
$output->reduceColors(256);
$output = $output->core()->native();
$output->setFormat('PNG');
$output->setImageFormat('PNG');
} else {
$output = clone $image->core()->native();
$output->setFormat('PNG32');
$output->setImageFormat('PNG32');
}
$output->setCompression(Imagick::COMPRESSION_ZIP);
$output->setImageCompression(Imagick::COMPRESSION_ZIP);
@@ -32,40 +41,6 @@ class PngEncoder extends GenericPngEncoder implements SpecializedInterface
$output->setInterlaceScheme(Imagick::INTERLACE_LINE);
}
return new EncodedImage($output->getImagesBlob(), 'image/png');
}
/**
* Prepare given image instance for PNG format output according to encoder settings
*
* @param ImageInterface $image
* @throws AnimationException
* @throws RuntimeException
* @throws ColorException
* @throws ImagickException
* @return Imagick
*/
private function prepareOutput(ImageInterface $image): Imagick
{
$output = clone $image;
if ($this->indexed) {
// reduce colors
$output->reduceColors(256);
$output = $output->core()->native();
$output->setFormat('PNG');
$output->setImageFormat('PNG');
return $output;
}
// ensure to encode PNG image type 6 (true color alpha)
$output = clone $image->core()->native();
$output->setFormat('PNG32');
$output->setImageFormat('PNG32');
return $output;
return new EncodedImage($output->getImagesBlob());
}
}

View File

@@ -24,6 +24,6 @@ class TiffEncoder extends GenericTiffEncoder implements SpecializedInterface
$imagick->setCompressionQuality($this->quality);
$imagick->setImageCompressionQuality($this->quality);
return new EncodedImage($imagick->getImagesBlob(), 'image/tiff');
return new EncodedImage($imagick->getImagesBlob());
}
}

View File

@@ -8,12 +8,13 @@ use Imagick;
use ImagickPixel;
use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\WebpEncoder as GenericWebpEncoder;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
class WebpEncoder extends GenericWebpEncoder implements SpecializedInterface
{
public function encode(ImageInterface $image): EncodedImage
public function encode(ImageInterface $image): EncodedImageInterface
{
$format = 'WEBP';
$compression = Imagick::COMPRESSION_ZIP;
@@ -31,6 +32,6 @@ class WebpEncoder extends GenericWebpEncoder implements SpecializedInterface
$imagick->setImageCompression($compression);
$imagick->setImageCompressionQuality($this->quality);
return new EncodedImage($imagick->getImagesBlob(), 'image/webp');
return new EncodedImage($imagick->getImagesBlob());
}
}

View File

@@ -11,13 +11,18 @@ class EncodedImage extends File implements EncodedImageInterface
/**
* Create new instance
*
* @param string $data
* @param string $mediaType
* @param string|resource $data
* @param string $mediaType Deprecated parameter, will be removed
*/
public function __construct(
protected string $data,
protected string $mediaType = 'application/octet-stream'
mixed $data,
protected string $mediaType = 'application/octet-stream' // deprecated
) {
if ($mediaType !== 'application/octet-stream') {
trigger_error('Parameter $mediaType for class' . self::class . ' is deprecated.', E_USER_DEPRECATED);
}
parent::__construct($data);
}
/**
@@ -27,7 +32,7 @@ class EncodedImage extends File implements EncodedImageInterface
*/
public function mediaType(): string
{
return $this->mediaType;
return mime_content_type($this->pointer);
}
/**
@@ -47,6 +52,6 @@ class EncodedImage extends File implements EncodedImageInterface
*/
public function toDataUri(): string
{
return sprintf('data:%s;base64,%s', $this->mediaType, base64_encode($this->data));
return sprintf('data:%s;base64,%s', $this->mediaType(), base64_encode((string) $this));
}
}

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Intervention\Image;
use Intervention\Image\Exceptions\NotWritableException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\FileInterface;
use Intervention\Image\Traits\CanBuildFilePointer;
@@ -12,13 +13,20 @@ class File implements FileInterface
{
use CanBuildFilePointer;
/**
* @var resource
*/
protected $pointer;
/**
* Create new instance
*
* @param string $data
* @param string|resource|null $data
* @throws RuntimeException
*/
public function __construct(protected string $data)
public function __construct(mixed $data = null)
{
$this->pointer = $this->buildFilePointer($data);
}
/**
@@ -42,8 +50,14 @@ class File implements FileInterface
);
}
if (is_file($filepath) && !is_writable($filepath)) {
throw new NotWritableException(
"Can't write image. Path ({$filepath}) is not writable."
);
}
// write data
$saved = @file_put_contents($filepath, (string) $this);
$saved = @file_put_contents($filepath, $this->pointer);
if ($saved === false) {
throw new NotWritableException(
"Can't write image data to path ({$filepath})."
@@ -58,7 +72,7 @@ class File implements FileInterface
*/
public function toString(): string
{
return $this->data;
return stream_get_contents($this->pointer, offset: 0);
}
/**
@@ -68,7 +82,9 @@ class File implements FileInterface
*/
public function toFilePointer()
{
return $this->buildFilePointer($this->toString());
rewind($this->pointer);
return $this->pointer;
}
/**
@@ -78,7 +94,9 @@ class File implements FileInterface
*/
public function size(): int
{
return mb_strlen($this->data);
$info = fstat($this->pointer);
return intval($info['size']);
}
/**

View File

@@ -4,18 +4,37 @@ declare(strict_types=1);
namespace Intervention\Image\Traits;
use Intervention\Image\Exceptions\RuntimeException;
trait CanBuildFilePointer
{
/**
* Transform the provided data into a pointer with the data as its content
*
* @param string $data
* @param resource|string|null $data
* @throws RuntimeException
* @return resource|false
*/
public function buildFilePointer(string $data)
public function buildFilePointer(mixed $data = null)
{
$pointer = fopen('php://temp', 'rw');
fputs($pointer, $data);
switch (true) {
case is_string($data):
$pointer = fopen('php://temp', 'r+');
fwrite($pointer, $data);
break;
case is_resource($data) && get_resource_type($data) === 'stream':
$pointer = $data;
break;
case is_null($data):
$pointer = fopen('php://temp', 'r+');
break;
default:
throw new RuntimeException('Unable to build file pointer.');
}
rewind($pointer);
return $pointer;

View File

@@ -9,6 +9,7 @@ use Intervention\Image\Colors\Rgb\Channels\Blue;
use Intervention\Image\Colors\Rgb\Channels\Green;
use Intervention\Image\Colors\Rgb\Channels\Red;
use Intervention\Image\Colors\Rgb\Color as RgbColor;
use Intervention\Image\EncodedImage;
use Intervention\Image\Interfaces\ColorInterface;
use Mockery\Adapter\Phpunit\MockeryTestCase;
use PHPUnit\Framework\ExpectationFailedException;
@@ -102,19 +103,18 @@ abstract class BaseTestCase extends MockeryTestCase
$this->assertEquals(0, $channel->value());
}
protected function assertMediaType(string|array $allowed, string $input): void
protected function assertMediaType(string|array $allowed, string|EncodedImage $input): void
{
$pointer = fopen('php://temp', 'rw');
fputs($pointer, $input);
rewind($pointer);
$detected = mime_content_type($pointer);
fclose($pointer);
$detected = match (true) {
is_string($input) => (new EncodedImage($input))->mimetype(),
default => $input->mimetype(),
};
$allowed = is_string($allowed) ? [$allowed] : $allowed;
$this->assertTrue(in_array($detected, $allowed));
}
protected function assertMediaTypeBitmap(string $input): void
protected function assertMediaTypeBitmap(string|EncodedImage $input): void
{
$this->assertMediaType([
'image/x-ms-bmp',

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Intervention\Image\Tests\Traits;
use Intervention\Image\EncodedImage;
use Intervention\Image\Traits\CanBuildFilePointer;
trait CanDetectProgressiveJpeg
@@ -13,12 +14,12 @@ trait CanDetectProgressiveJpeg
/**
* Checks if the given image data is progressive encoded Jpeg format
*
* @param string $imagedata
* @param EncodedImage $imagedata
* @return bool
*/
private function isProgressiveJpeg(string $imagedata): bool
private function isProgressiveJpeg(EncodedImage $image): bool
{
$f = $this->buildFilePointer($imagedata);
$f = $image->toFilePointer();
while (!feof($f)) {
if (unpack('C', fread($f, 1))[1] !== 0xff) {

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Intervention\Image\Tests\Traits;
use Intervention\Image\EncodedImage;
use Intervention\Image\Traits\CanBuildFilePointer;
trait CanInspectPngFormat
@@ -13,12 +14,12 @@ trait CanInspectPngFormat
/**
* Checks if the given image data is interlaced encoded PNG format
*
* @param string $imagedata
* @param EncodedImage $image
* @return bool
*/
private function isInterlacedPng(string $imagedata): bool
private function isInterlacedPng(EncodedImage $image): bool
{
$f = $this->buildFilePointer($imagedata);
$f = $image->toFilePointer();
$contents = fread($f, 32);
fclose($f);
@@ -28,11 +29,13 @@ trait CanInspectPngFormat
/**
* Try to detect PNG color type from given binary data
*
* @param string $data
* @param EncodedImage $image
* @return string
*/
private function pngColorType(string $data): string
private function pngColorType(EncodedImage $image): string
{
$data = $image->toString();
if (substr($data, 1, 3) !== 'PNG') {
return 'unkown';
}

View File

@@ -23,21 +23,4 @@ final class AbstractEncoderTest extends BaseTestCase
$result = $encoder->encode($image);
$this->assertInstanceOf(EncodedImage::class, $result);
}
public function testGetBuffered(): void
{
$encoder = new class () extends AbstractEncoder
{
public function test(callable $callback)
{
return $this->buffered($callback);
}
};
$result = $encoder->test(function () {
echo 'result';
});
$this->assertEquals('result', $result);
}
}

View File

@@ -19,6 +19,6 @@ final class AvifEncoderTest extends GdTestCase
$image = $this->createTestImage(3, 2);
$encoder = new AvifEncoder(10);
$result = $encoder->encode($image);
$this->assertMediaType('image/avif', (string) $result);
$this->assertMediaType('image/avif', $result);
}
}

View File

@@ -19,6 +19,6 @@ final class BmpEncoderTest extends GdTestCase
$image = $this->createTestImage(3, 2);
$encoder = new BmpEncoder();
$result = $encoder->encode($image);
$this->assertMediaType(['image/bmp', 'image/x-ms-bmp'], (string) $result);
$this->assertMediaType(['image/bmp', 'image/x-ms-bmp'], $result);
}
}

View File

@@ -20,7 +20,7 @@ final class GifEncoderTest extends GdTestCase
$image = $this->createTestAnimation();
$encoder = new GifEncoder();
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$this->assertFalse(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);
@@ -31,7 +31,7 @@ final class GifEncoderTest extends GdTestCase
$image = $this->createTestImage(3, 2);
$encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);
@@ -42,7 +42,7 @@ final class GifEncoderTest extends GdTestCase
$image = $this->createTestAnimation(3, 2);
$encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);

View File

@@ -22,7 +22,7 @@ final class JpegEncoderTest extends GdTestCase
$image = $this->createTestImage(3, 2);
$encoder = new JpegEncoder(75);
$result = $encoder->encode($image);
$this->assertMediaType('image/jpeg', (string) $result);
$this->assertMediaType('image/jpeg', $result);
}
public function testEncodeProgressive(): void
@@ -30,7 +30,7 @@ final class JpegEncoderTest extends GdTestCase
$image = $this->createTestImage(3, 2);
$encoder = new JpegEncoder(progressive: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/jpeg', (string) $result);
$this->assertTrue($this->isProgressiveJpeg((string) $result));
$this->assertMediaType('image/jpeg', $result);
$this->assertTrue($this->isProgressiveJpeg($result));
}
}

View File

@@ -24,8 +24,8 @@ final class PngEncoderTest extends GdTestCase
$image = $this->createTestImage(3, 2);
$encoder = new PngEncoder();
$result = $encoder->encode($image);
$this->assertMediaType('image/png', (string) $result);
$this->assertFalse($this->isInterlacedPng((string) $result));
$this->assertMediaType('image/png', $result);
$this->assertFalse($this->isInterlacedPng($result));
}
public function testEncodeInterlaced(): void
@@ -33,8 +33,8 @@ final class PngEncoderTest extends GdTestCase
$image = $this->createTestImage(3, 2);
$encoder = new PngEncoder(interlaced: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/png', (string) $result);
$this->assertTrue($this->isInterlacedPng((string) $result));
$this->assertMediaType('image/png', $result);
$this->assertTrue($this->isInterlacedPng($result));
}
#[DataProvider('indexedDataProvider')]
@@ -42,7 +42,7 @@ final class PngEncoderTest extends GdTestCase
{
$this->assertEquals(
$result,
$this->pngColorType((string) $encoder->encode($image)),
$this->pngColorType($encoder->encode($image)),
);
}

View File

@@ -19,6 +19,6 @@ final class WebpEncoderTest extends GdTestCase
$image = $this->createTestImage(3, 2);
$encoder = new WebpEncoder(75);
$result = $encoder->encode($image);
$this->assertMediaType('image/webp', (string) $result);
$this->assertMediaType('image/webp', $result);
}
}

View File

@@ -142,48 +142,48 @@ final class ImageTest extends GdTestCase
{
$result = $this->readTestImage('blue.gif')->encode();
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
}
public function testEncodeByMediaType(): void
{
$result = $this->readTestImage('blue.gif')->encodeByMediaType();
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$result = $this->readTestImage('blue.gif')->encodeByMediaType('image/png');
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
$this->assertMediaType('image/png', $result);
$result = $this->readTestImage('blue.gif')->encodeByMediaType(MediaType::IMAGE_PNG);
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
$this->assertMediaType('image/png', $result);
}
public function testEncodeByExtension(): void
{
$result = $this->readTestImage('blue.gif')->encodeByExtension();
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$result = $this->readTestImage('blue.gif')->encodeByExtension('png');
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
$this->assertMediaType('image/png', $result);
$result = $this->readTestImage('blue.gif')->encodeByExtension(FileExtension::PNG);
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
$this->assertMediaType('image/png', $result);
}
public function testEncodeByPath(): void
{
$result = $this->readTestImage('blue.gif')->encodeByPath();
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$result = $this->readTestImage('blue.gif')->encodeByPath('foo/bar.png');
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
$this->assertMediaType('image/png', $result);
}
public function testSaveAsFormat(): void
@@ -299,8 +299,8 @@ final class ImageTest extends GdTestCase
public function testToJpeg(): void
{
$this->assertMediaType('image/jpeg', (string) $this->image->toJpeg());
$this->assertMediaType('image/jpeg', (string) $this->image->toJpg());
$this->assertMediaType('image/jpeg', $this->image->toJpeg());
$this->assertMediaType('image/jpeg', $this->image->toJpg());
}
public function testToJpeg2000(): void
@@ -311,28 +311,28 @@ final class ImageTest extends GdTestCase
public function testToPng(): void
{
$this->assertMediaType('image/png', (string) $this->image->toPng());
$this->assertMediaType('image/png', $this->image->toPng());
}
public function testToGif(): void
{
$this->assertMediaType('image/gif', (string) $this->image->toGif());
$this->assertMediaType('image/gif', $this->image->toGif());
}
public function testToWebp(): void
{
$this->assertMediaType('image/webp', (string) $this->image->toWebp());
$this->assertMediaType('image/webp', $this->image->toWebp());
}
public function testToBitmap(): void
{
$this->assertMediaTypeBitmap((string) $this->image->toBitmap());
$this->assertMediaTypeBitmap((string) $this->image->toBmp());
$this->assertMediaTypeBitmap($this->image->toBitmap());
$this->assertMediaTypeBitmap($this->image->toBmp());
}
public function testToAvif(): void
{
$this->assertMediaType('image/avif', (string) $this->image->toAvif());
$this->assertMediaType('image/avif', $this->image->toAvif());
}
public function testToTiff(): void

View File

@@ -19,6 +19,6 @@ final class AvifEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new AvifEncoder(10);
$result = $encoder->encode($image);
$this->assertMediaType('image/avif', (string) $result);
$this->assertMediaType('image/avif', $result);
}
}

View File

@@ -19,6 +19,6 @@ final class BmpEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new BmpEncoder();
$result = $encoder->encode($image);
$this->assertMediaType(['image/bmp', 'image/x-ms-bmp'], (string) $result);
$this->assertMediaType(['image/bmp', 'image/x-ms-bmp'], $result);
}
}

View File

@@ -20,7 +20,7 @@ final class GifEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new GifEncoder();
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$this->assertFalse(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);
@@ -31,7 +31,7 @@ final class GifEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);
@@ -42,7 +42,7 @@ final class GifEncoderTest extends ImagickTestCase
$image = $this->createTestAnimation();
$encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
);

View File

@@ -19,6 +19,6 @@ final class HeicEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new HeicEncoder(75);
$result = $encoder->encode($image);
$this->assertMediaType('image/heic', (string) $result);
$this->assertMediaType('image/heic', $result);
}
}

View File

@@ -19,6 +19,6 @@ final class Jpeg2000EncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new Jpeg2000Encoder(75);
$result = $encoder->encode($image);
$this->assertMediaType('image/jp2', (string) $result);
$this->assertMediaType('image/jp2', $result);
}
}

View File

@@ -22,7 +22,7 @@ final class JpegEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new JpegEncoder(75);
$result = $encoder->encode($image);
$this->assertMediaType('image/jpeg', (string) $result);
$this->assertMediaType('image/jpeg', $result);
}
public function testEncodeProgressive(): void
@@ -30,7 +30,7 @@ final class JpegEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new JpegEncoder(progressive: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/jpeg', (string) $result);
$this->assertTrue($this->isProgressiveJpeg((string) $result));
$this->assertMediaType('image/jpeg', $result);
$this->assertTrue($this->isProgressiveJpeg($result));
}
}

View File

@@ -24,8 +24,8 @@ final class PngEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new PngEncoder();
$result = $encoder->encode($image);
$this->assertMediaType('image/png', (string) $result);
$this->assertFalse($this->isInterlacedPng((string) $result));
$this->assertMediaType('image/png', $result);
$this->assertFalse($this->isInterlacedPng($result));
}
public function testEncodeInterlaced(): void
@@ -33,8 +33,8 @@ final class PngEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new PngEncoder(interlaced: true);
$result = $encoder->encode($image);
$this->assertMediaType('image/png', (string) $result);
$this->assertTrue($this->isInterlacedPng((string) $result));
$this->assertMediaType('image/png', $result);
$this->assertTrue($this->isInterlacedPng($result));
}
#[DataProvider('indexedDataProvider')]
@@ -42,7 +42,7 @@ final class PngEncoderTest extends ImagickTestCase
{
$this->assertEquals(
$result,
$this->pngColorType((string) $encoder->encode($image)),
$this->pngColorType($encoder->encode($image)),
);
}

View File

@@ -19,6 +19,6 @@ final class TiffEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new TiffEncoder();
$result = $encoder->encode($image);
$this->assertMediaType('image/tiff', (string) $result);
$this->assertMediaType('image/tiff', $result);
}
}

View File

@@ -19,6 +19,6 @@ final class WebpEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2);
$encoder = new WebpEncoder(75);
$result = $encoder->encode($image);
$this->assertMediaType('image/webp', (string) $result);
$this->assertMediaType('image/webp', $result);
}
}

View File

@@ -151,40 +151,40 @@ final class ImageTest extends ImagickTestCase
{
$result = $this->readTestImage('blue.gif')->encode();
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
}
public function testEncodeByMediaType(): void
{
$result = $this->readTestImage('blue.gif')->encodeByMediaType();
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$result = $this->readTestImage('blue.gif')->encodeByMediaType('image/png');
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
$this->assertMediaType('image/png', $result);
}
public function testEncodeByExtension(): void
{
$result = $this->readTestImage('blue.gif')->encodeByExtension();
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$result = $this->readTestImage('blue.gif')->encodeByExtension('png');
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
$this->assertMediaType('image/png', $result);
}
public function testEncodeByPath(): void
{
$result = $this->readTestImage('blue.gif')->encodeByPath();
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result);
$this->assertMediaType('image/gif', $result);
$result = $this->readTestImage('blue.gif')->encodeByPath('foo/bar.png');
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
$this->assertMediaType('image/png', $result);
}
public function testSaveAsFormat(): void
@@ -293,51 +293,51 @@ final class ImageTest extends ImagickTestCase
public function testToJpeg(): void
{
$this->assertMediaType('image/jpeg', (string) $this->image->toJpeg());
$this->assertMediaType('image/jpeg', (string) $this->image->toJpg());
$this->assertMediaType('image/jpeg', $this->image->toJpeg());
$this->assertMediaType('image/jpeg', $this->image->toJpg());
}
public function testToJpeg2000(): void
{
$this->assertMediaType('image/jp2', (string) $this->image->toJpeg2000());
$this->assertMediaType('image/jp2', (string) $this->image->toJp2());
$this->assertMediaType('image/jp2', $this->image->toJpeg2000());
$this->assertMediaType('image/jp2', $this->image->toJp2());
}
public function testToPng(): void
{
$this->assertMediaType('image/png', (string) $this->image->toPng());
$this->assertMediaType('image/png', $this->image->toPng());
}
public function testToGif(): void
{
$this->assertMediaType('image/gif', (string) $this->image->toGif());
$this->assertMediaType('image/gif', $this->image->toGif());
}
public function testToWebp(): void
{
$this->assertMediaType('image/webp', (string) $this->image->toWebp());
$this->assertMediaType('image/webp', $this->image->toWebp());
}
public function testToBitmap(): void
{
$this->assertMediaTypeBitmap((string) $this->image->toBitmap());
$this->assertMediaTypeBitmap((string) $this->image->toBmp());
$this->assertMediaTypeBitmap($this->image->toBitmap());
$this->assertMediaTypeBitmap($this->image->toBmp());
}
public function testToAvif(): void
{
$this->assertMediaType('image/avif', (string) $this->image->toAvif());
$this->assertMediaType('image/avif', $this->image->toAvif());
}
public function testToTiff(): void
{
$this->assertMediaType('image/tiff', (string) $this->image->toTiff());
$this->assertMediaType('image/tiff', (string) $this->image->toTif());
$this->assertMediaType('image/tiff', $this->image->toTiff());
$this->assertMediaType('image/tiff', $this->image->toTif());
}
public function testToHeic(): void
{
$this->assertMediaType('image/heic', (string) $this->image->toHeic());
$this->assertMediaType('image/heic', $this->image->toHeic());
}
public function testInvert(): void

View File

@@ -13,13 +13,13 @@ final class EncodedImageTest extends BaseTestCase
{
public function testConstructor(): void
{
$image = new EncodedImage('foo', 'bar');
$image = new EncodedImage('foo');
$this->assertInstanceOf(EncodedImage::class, $image);
}
public function testSave(): void
{
$image = new EncodedImage('foo', 'bar');
$image = new EncodedImage('foo');
$path = __DIR__ . '/foo.tmp';
$this->assertFalse(file_exists($path));
$image->save($path);
@@ -30,31 +30,31 @@ final class EncodedImageTest extends BaseTestCase
public function testToDataUri(): void
{
$image = new EncodedImage('foo', 'bar');
$this->assertEquals('data:bar;base64,Zm9v', $image->toDataUri());
$image = new EncodedImage('foo');
$this->assertEquals('data:text/plain;base64,Zm9v', $image->toDataUri());
}
public function testToString(): void
{
$image = new EncodedImage('foo', 'bar');
$image = new EncodedImage('foo');
$this->assertEquals('foo', (string) $image);
}
public function testMediaType(): void
{
$image = new EncodedImage('foo');
$this->assertEquals('application/octet-stream', $image->mediaType());
$this->assertEquals('text/plain', $image->mediaType());
$image = new EncodedImage('foo', 'image/jpeg');
$image = new EncodedImage($this->getTestResourceData());
$this->assertEquals('image/jpeg', $image->mediaType());
}
public function testMimetype(): void
{
$image = new EncodedImage('foo');
$this->assertEquals('application/octet-stream', $image->mimetype());
$this->assertEquals('text/plain', $image->mimetype());
$image = new EncodedImage('foo', 'image/jpeg');
$image = new EncodedImage($this->getTestResourceData());
$this->assertEquals('image/jpeg', $image->mimetype());
}
}

View File

@@ -13,10 +13,25 @@ final class FileTest extends BaseTestCase
{
public function testConstructor(): void
{
$file = new File();
$this->assertInstanceOf(File::class, $file);
$file = new File('foo');
$this->assertInstanceOf(File::class, $file);
}
public function testConstructorFromString(): void
{
$file = new File('foo');
$this->assertInstanceOf(File::class, $file);
}
public function testConstructorFromResource(): void
{
$file = new File(fopen('php://temp', 'r'));
$this->assertInstanceOf(File::class, $file);
}
public function testSave(): void
{
$filename = __DIR__ . '/file_' . strval(hrtime(true)) . '.test';
@@ -43,6 +58,9 @@ final class FileTest extends BaseTestCase
public function testSize(): void
{
$file = new File();
$this->assertEquals(0, $file->size());
$file = new File('foo');
$this->assertEquals(3, $file->size());
}