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": { "require": {
"php": "^8.1", "php": "^8.1",
"ext-mbstring": "*", "ext-mbstring": "*",
"intervention/gif": "^4.1" "intervention/gif": "^4.2"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^10.0", "phpunit/phpunit": "^10.0",

View File

@@ -4,12 +4,17 @@ declare(strict_types=1);
namespace Intervention\Image\Drivers; namespace Intervention\Image\Drivers;
use Intervention\Image\EncodedImage;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\EncoderInterface; use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Traits\CanBuildFilePointer;
abstract class AbstractEncoder implements EncoderInterface abstract class AbstractEncoder implements EncoderInterface
{ {
use CanBuildFilePointer;
public const DEFAULT_QUALITY = 75; 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 * @param callable $callback
* @return string * @throws RuntimeException
* @return EncodedImage
*/ */
protected function buffered(callable $callback): string protected function createEncodedImage(callable $callback): EncodedImage
{ {
ob_start(); $pointer = $this->buildFilePointer();
$callback(); $callback($pointer);
$buffer = ob_get_contents();
ob_end_clean();
return $buffer; return new EncodedImage($pointer);
} }
} }

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Intervention\Image\Drivers\Gd\Decoders; namespace Intervention\Image\Drivers\Gd\Decoders;
use Exception;
use GdImage; use GdImage;
use Intervention\Gif\Decoder as GifDecoder; use Intervention\Gif\Decoder as GifDecoder;
use Intervention\Gif\Splitter as GifSplitter; use Intervention\Gif\Splitter as GifSplitter;
@@ -76,23 +77,27 @@ class NativeObjectDecoder extends AbstractDecoder
return $image; return $image;
} }
// create empty core try {
$core = new Core(); // create empty core
$core = new Core();
$gif = GifDecoder::decode($input); $gif = GifDecoder::decode($input);
$splitter = GifSplitter::create($gif)->split(); $splitter = GifSplitter::create($gif)->split();
$delays = $splitter->getDelays(); $delays = $splitter->getDelays();
// set loops on core // set loops on core
if ($loops = $gif->getMainApplicationExtension()?->getLoops()) { if ($loops = $gif->getMainApplicationExtension()?->getLoops()) {
$core->setLoops($loops); $core->setLoops($loops);
} }
// add GDImage instances to core // add GDImage instances to core
foreach ($splitter->coalesceToResources() as $key => $native) { foreach ($splitter->coalesceToResources() as $key => $native) {
$core->push( $core->push(
new Frame($native, $delays[$key] / 100) new Frame($native, $delays[$key] / 100)
); );
}
} catch (Exception $e) {
throw new DecoderException($e->getMessage(), $e->getCode(), $e);
} }
// create (possibly) animated image // create (possibly) animated image

View File

@@ -18,11 +18,8 @@ class AvifEncoder extends GenericAvifEncoder implements SpecializedInterface
*/ */
public function encode(ImageInterface $image): EncodedImage public function encode(ImageInterface $image): EncodedImage
{ {
$gd = $image->core()->native(); return $this->createEncodedImage(function ($pointer) use ($image) {
$data = $this->buffered(function () use ($gd) { imageavif($image->core()->native(), $pointer, $this->quality);
imageavif($gd, null, $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 public function encode(ImageInterface $image): EncodedImage
{ {
$data = $this->buffered(function () use ($image) { return $this->createEncodedImage(function ($pointer) use ($image) {
imagebmp($image->core()->native(), null, false); 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()); $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,25 +40,25 @@ class GifEncoder extends GenericGifEncoder implements SpecializedInterface
*/ */
protected function encodeAnimated(ImageInterface $image): EncodedImage protected function encodeAnimated(ImageInterface $image): EncodedImage
{ {
$builder = GifBuilder::canvas(
$image->width(),
$image->height()
);
foreach ($image as $frame) {
$builder->addFrame(
source: (string) $this->encode($frame->toImage($image->driver())),
delay: $frame->delay(),
interlaced: $this->interlaced
);
}
try { try {
$builder = GifBuilder::canvas(
$image->width(),
$image->height()
);
foreach ($image as $frame) {
$builder->addFrame(
source: $this->encode($frame->toImage($image->driver()))->toFilePointer(),
delay: $frame->delay(),
interlaced: $this->interlaced
);
}
$builder->setLoops($image->loops()); $builder->setLoops($image->loops());
return new EncodedImage($builder->encode());
} catch (Exception $e) { } catch (Exception $e) {
throw new EncoderException($e->getMessage(), $e->getCode(), $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 background: $blendingColor
); );
$data = $this->buffered(function () use ($output) { return $this->createEncodedImage(function ($pointer) use ($output) {
imageinterlace($output, $this->progressive); 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); $output = $this->prepareOutput($image);
// encode return $this->createEncodedImage(function ($pointer) use ($output) {
$data = $this->buffered(function () use ($output) {
imageinterlace($output, $this->interlaced); 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 public function encode(ImageInterface $image): EncodedImage
{ {
$quality = $this->quality === 100 ? IMG_WEBP_LOSSLESS : $this->quality; $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 Imagick;
use Intervention\Image\EncodedImage; use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\AvifEncoder as GenericAvifEncoder; use Intervention\Image\Encoders\AvifEncoder as GenericAvifEncoder;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface; use Intervention\Image\Interfaces\SpecializedInterface;
class AvifEncoder extends GenericAvifEncoder implements SpecializedInterface class AvifEncoder extends GenericAvifEncoder implements SpecializedInterface
{ {
public function encode(ImageInterface $image): EncodedImage public function encode(ImageInterface $image): EncodedImageInterface
{ {
$format = 'AVIF'; $format = 'AVIF';
$compression = Imagick::COMPRESSION_ZIP; $compression = Imagick::COMPRESSION_ZIP;
@@ -25,6 +26,6 @@ class AvifEncoder extends GenericAvifEncoder implements SpecializedInterface
$imagick->setCompressionQuality($this->quality); $imagick->setCompressionQuality($this->quality);
$imagick->setImageCompressionQuality($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 Imagick;
use Intervention\Image\EncodedImage; use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\BmpEncoder as GenericBmpEncoder; use Intervention\Image\Encoders\BmpEncoder as GenericBmpEncoder;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface; use Intervention\Image\Interfaces\SpecializedInterface;
class BmpEncoder extends GenericBmpEncoder implements SpecializedInterface class BmpEncoder extends GenericBmpEncoder implements SpecializedInterface
{ {
public function encode(ImageInterface $image): EncodedImage public function encode(ImageInterface $image): EncodedImageInterface
{ {
$format = 'BMP'; $format = 'BMP';
$compression = Imagick::COMPRESSION_NO; $compression = Imagick::COMPRESSION_NO;
@@ -23,6 +24,6 @@ class BmpEncoder extends GenericBmpEncoder implements SpecializedInterface
$imagick->setCompression($compression); $imagick->setCompression($compression);
$imagick->setImageCompression($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 Imagick;
use Intervention\Image\EncodedImage; use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\GifEncoder as GenericGifEncoder; use Intervention\Image\Encoders\GifEncoder as GenericGifEncoder;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface; use Intervention\Image\Interfaces\SpecializedInterface;
class GifEncoder extends GenericGifEncoder implements SpecializedInterface class GifEncoder extends GenericGifEncoder implements SpecializedInterface
{ {
public function encode(ImageInterface $image): EncodedImage public function encode(ImageInterface $image): EncodedImageInterface
{ {
$format = 'GIF'; $format = 'GIF';
$compression = Imagick::COMPRESSION_LZW; $compression = Imagick::COMPRESSION_LZW;
@@ -28,6 +29,6 @@ class GifEncoder extends GenericGifEncoder implements SpecializedInterface
$imagick->setInterlaceScheme(Imagick::INTERLACE_LINE); $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\EncodedImage;
use Intervention\Image\Encoders\HeicEncoder as GenericHeicEncoder; use Intervention\Image\Encoders\HeicEncoder as GenericHeicEncoder;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\EncodedImageInterface; use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface; use Intervention\Image\Interfaces\SpecializedInterface;
class HeicEncoder extends GenericHeicEncoder implements SpecializedInterface class HeicEncoder extends GenericHeicEncoder implements SpecializedInterface
@@ -17,12 +17,11 @@ class HeicEncoder extends GenericHeicEncoder implements SpecializedInterface
$format = 'HEIC'; $format = 'HEIC';
$imagick = $image->core()->native(); $imagick = $image->core()->native();
$imagick->setFormat($format); $imagick->setFormat($format);
$imagick->setImageFormat($format); $imagick->setImageFormat($format);
$imagick->setCompressionQuality($this->quality); $imagick->setCompressionQuality($this->quality);
$imagick->setImageCompressionQuality($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->setCompressionQuality($this->quality);
$imagick->setImageCompressionQuality($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 Imagick;
use Intervention\Image\EncodedImage; use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\JpegEncoder as GenericJpegEncoder; use Intervention\Image\Encoders\JpegEncoder as GenericJpegEncoder;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface; use Intervention\Image\Interfaces\SpecializedInterface;
class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface
{ {
public function encode(ImageInterface $image): EncodedImage public function encode(ImageInterface $image): EncodedImageInterface
{ {
$format = 'JPEG'; $format = 'JPEG';
$compression = Imagick::COMPRESSION_JPEG; $compression = Imagick::COMPRESSION_JPEG;
@@ -44,6 +45,6 @@ class JpegEncoder extends GenericJpegEncoder implements SpecializedInterface
$imagick->setInterlaceScheme(Imagick::INTERLACE_PLANE); $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; namespace Intervention\Image\Drivers\Imagick\Encoders;
use Imagick; use Imagick;
use ImagickException;
use Intervention\Image\EncodedImage; use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\PngEncoder as GenericPngEncoder; use Intervention\Image\Encoders\PngEncoder as GenericPngEncoder;
use Intervention\Image\Exceptions\AnimationException; use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Exceptions\ColorException;
use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface; use Intervention\Image\Interfaces\SpecializedInterface;
@@ -21,9 +18,21 @@ class PngEncoder extends GenericPngEncoder implements SpecializedInterface
* *
* @see EncoderInterface::encode() * @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->setCompression(Imagick::COMPRESSION_ZIP);
$output->setImageCompression(Imagick::COMPRESSION_ZIP); $output->setImageCompression(Imagick::COMPRESSION_ZIP);
@@ -32,40 +41,6 @@ class PngEncoder extends GenericPngEncoder implements SpecializedInterface
$output->setInterlaceScheme(Imagick::INTERLACE_LINE); $output->setInterlaceScheme(Imagick::INTERLACE_LINE);
} }
return new EncodedImage($output->getImagesBlob(), 'image/png'); return new EncodedImage($output->getImagesBlob());
}
/**
* 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;
} }
} }

View File

@@ -24,6 +24,6 @@ class TiffEncoder extends GenericTiffEncoder implements SpecializedInterface
$imagick->setCompressionQuality($this->quality); $imagick->setCompressionQuality($this->quality);
$imagick->setImageCompressionQuality($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 ImagickPixel;
use Intervention\Image\EncodedImage; use Intervention\Image\EncodedImage;
use Intervention\Image\Encoders\WebpEncoder as GenericWebpEncoder; use Intervention\Image\Encoders\WebpEncoder as GenericWebpEncoder;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\ImageInterface; use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface; use Intervention\Image\Interfaces\SpecializedInterface;
class WebpEncoder extends GenericWebpEncoder implements SpecializedInterface class WebpEncoder extends GenericWebpEncoder implements SpecializedInterface
{ {
public function encode(ImageInterface $image): EncodedImage public function encode(ImageInterface $image): EncodedImageInterface
{ {
$format = 'WEBP'; $format = 'WEBP';
$compression = Imagick::COMPRESSION_ZIP; $compression = Imagick::COMPRESSION_ZIP;
@@ -31,6 +32,6 @@ class WebpEncoder extends GenericWebpEncoder implements SpecializedInterface
$imagick->setImageCompression($compression); $imagick->setImageCompression($compression);
$imagick->setImageCompressionQuality($this->quality); $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 * Create new instance
* *
* @param string $data * @param string|resource $data
* @param string $mediaType * @param string $mediaType Deprecated parameter, will be removed
*/ */
public function __construct( public function __construct(
protected string $data, mixed $data,
protected string $mediaType = 'application/octet-stream' 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 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 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; namespace Intervention\Image;
use Intervention\Image\Exceptions\NotWritableException; use Intervention\Image\Exceptions\NotWritableException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Interfaces\FileInterface; use Intervention\Image\Interfaces\FileInterface;
use Intervention\Image\Traits\CanBuildFilePointer; use Intervention\Image\Traits\CanBuildFilePointer;
@@ -12,13 +13,20 @@ class File implements FileInterface
{ {
use CanBuildFilePointer; use CanBuildFilePointer;
/**
* @var resource
*/
protected $pointer;
/** /**
* Create new instance * 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 // write data
$saved = @file_put_contents($filepath, (string) $this); $saved = @file_put_contents($filepath, $this->pointer);
if ($saved === false) { if ($saved === false) {
throw new NotWritableException( throw new NotWritableException(
"Can't write image data to path ({$filepath})." "Can't write image data to path ({$filepath})."
@@ -58,7 +72,7 @@ class File implements FileInterface
*/ */
public function toString(): string 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() 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 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; namespace Intervention\Image\Traits;
use Intervention\Image\Exceptions\RuntimeException;
trait CanBuildFilePointer trait CanBuildFilePointer
{ {
/** /**
* Transform the provided data into a pointer with the data as its content * 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 * @return resource|false
*/ */
public function buildFilePointer(string $data) public function buildFilePointer(mixed $data = null)
{ {
$pointer = fopen('php://temp', 'rw'); switch (true) {
fputs($pointer, $data); 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); rewind($pointer);
return $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\Green;
use Intervention\Image\Colors\Rgb\Channels\Red; use Intervention\Image\Colors\Rgb\Channels\Red;
use Intervention\Image\Colors\Rgb\Color as RgbColor; use Intervention\Image\Colors\Rgb\Color as RgbColor;
use Intervention\Image\EncodedImage;
use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\ColorInterface;
use Mockery\Adapter\Phpunit\MockeryTestCase; use Mockery\Adapter\Phpunit\MockeryTestCase;
use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\ExpectationFailedException;
@@ -102,19 +103,18 @@ abstract class BaseTestCase extends MockeryTestCase
$this->assertEquals(0, $channel->value()); $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'); $detected = match (true) {
fputs($pointer, $input); is_string($input) => (new EncodedImage($input))->mimetype(),
rewind($pointer); default => $input->mimetype(),
$detected = mime_content_type($pointer); };
fclose($pointer);
$allowed = is_string($allowed) ? [$allowed] : $allowed; $allowed = is_string($allowed) ? [$allowed] : $allowed;
$this->assertTrue(in_array($detected, $allowed)); $this->assertTrue(in_array($detected, $allowed));
} }
protected function assertMediaTypeBitmap(string $input): void protected function assertMediaTypeBitmap(string|EncodedImage $input): void
{ {
$this->assertMediaType([ $this->assertMediaType([
'image/x-ms-bmp', 'image/x-ms-bmp',

View File

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

View File

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

View File

@@ -23,21 +23,4 @@ final class AbstractEncoderTest extends BaseTestCase
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertInstanceOf(EncodedImage::class, $result); $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); $image = $this->createTestImage(3, 2);
$encoder = new AvifEncoder(10); $encoder = new AvifEncoder(10);
$result = $encoder->encode($image); $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); $image = $this->createTestImage(3, 2);
$encoder = new BmpEncoder(); $encoder = new BmpEncoder();
$result = $encoder->encode($image); $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(); $image = $this->createTestAnimation();
$encoder = new GifEncoder(); $encoder = new GifEncoder();
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
$this->assertFalse( $this->assertFalse(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced() Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
); );
@@ -31,7 +31,7 @@ final class GifEncoderTest extends GdTestCase
$image = $this->createTestImage(3, 2); $image = $this->createTestImage(3, 2);
$encoder = new GifEncoder(interlaced: true); $encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
$this->assertTrue( $this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced() Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
); );
@@ -42,7 +42,7 @@ final class GifEncoderTest extends GdTestCase
$image = $this->createTestAnimation(3, 2); $image = $this->createTestAnimation(3, 2);
$encoder = new GifEncoder(interlaced: true); $encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
$this->assertTrue( $this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced() Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
); );

View File

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

View File

@@ -24,8 +24,8 @@ final class PngEncoderTest extends GdTestCase
$image = $this->createTestImage(3, 2); $image = $this->createTestImage(3, 2);
$encoder = new PngEncoder(); $encoder = new PngEncoder();
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/png', (string) $result); $this->assertMediaType('image/png', $result);
$this->assertFalse($this->isInterlacedPng((string) $result)); $this->assertFalse($this->isInterlacedPng($result));
} }
public function testEncodeInterlaced(): void public function testEncodeInterlaced(): void
@@ -33,8 +33,8 @@ final class PngEncoderTest extends GdTestCase
$image = $this->createTestImage(3, 2); $image = $this->createTestImage(3, 2);
$encoder = new PngEncoder(interlaced: true); $encoder = new PngEncoder(interlaced: true);
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/png', (string) $result); $this->assertMediaType('image/png', $result);
$this->assertTrue($this->isInterlacedPng((string) $result)); $this->assertTrue($this->isInterlacedPng($result));
} }
#[DataProvider('indexedDataProvider')] #[DataProvider('indexedDataProvider')]
@@ -42,7 +42,7 @@ final class PngEncoderTest extends GdTestCase
{ {
$this->assertEquals( $this->assertEquals(
$result, $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); $image = $this->createTestImage(3, 2);
$encoder = new WebpEncoder(75); $encoder = new WebpEncoder(75);
$result = $encoder->encode($image); $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(); $result = $this->readTestImage('blue.gif')->encode();
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
} }
public function testEncodeByMediaType(): void public function testEncodeByMediaType(): void
{ {
$result = $this->readTestImage('blue.gif')->encodeByMediaType(); $result = $this->readTestImage('blue.gif')->encodeByMediaType();
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
$result = $this->readTestImage('blue.gif')->encodeByMediaType('image/png'); $result = $this->readTestImage('blue.gif')->encodeByMediaType('image/png');
$this->assertInstanceOf(EncodedImage::class, $result); $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); $result = $this->readTestImage('blue.gif')->encodeByMediaType(MediaType::IMAGE_PNG);
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result); $this->assertMediaType('image/png', $result);
} }
public function testEncodeByExtension(): void public function testEncodeByExtension(): void
{ {
$result = $this->readTestImage('blue.gif')->encodeByExtension(); $result = $this->readTestImage('blue.gif')->encodeByExtension();
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
$result = $this->readTestImage('blue.gif')->encodeByExtension('png'); $result = $this->readTestImage('blue.gif')->encodeByExtension('png');
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result); $this->assertMediaType('image/png', $result);
$result = $this->readTestImage('blue.gif')->encodeByExtension(FileExtension::PNG); $result = $this->readTestImage('blue.gif')->encodeByExtension(FileExtension::PNG);
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result); $this->assertMediaType('image/png', $result);
} }
public function testEncodeByPath(): void public function testEncodeByPath(): void
{ {
$result = $this->readTestImage('blue.gif')->encodeByPath(); $result = $this->readTestImage('blue.gif')->encodeByPath();
$this->assertInstanceOf(EncodedImage::class, $result); $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'); $result = $this->readTestImage('blue.gif')->encodeByPath('foo/bar.png');
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result); $this->assertMediaType('image/png', $result);
} }
public function testSaveAsFormat(): void public function testSaveAsFormat(): void
@@ -299,8 +299,8 @@ final class ImageTest extends GdTestCase
public function testToJpeg(): void public function testToJpeg(): void
{ {
$this->assertMediaType('image/jpeg', (string) $this->image->toJpeg()); $this->assertMediaType('image/jpeg', $this->image->toJpeg());
$this->assertMediaType('image/jpeg', (string) $this->image->toJpg()); $this->assertMediaType('image/jpeg', $this->image->toJpg());
} }
public function testToJpeg2000(): void public function testToJpeg2000(): void
@@ -311,28 +311,28 @@ final class ImageTest extends GdTestCase
public function testToPng(): void public function testToPng(): void
{ {
$this->assertMediaType('image/png', (string) $this->image->toPng()); $this->assertMediaType('image/png', $this->image->toPng());
} }
public function testToGif(): void public function testToGif(): void
{ {
$this->assertMediaType('image/gif', (string) $this->image->toGif()); $this->assertMediaType('image/gif', $this->image->toGif());
} }
public function testToWebp(): void public function testToWebp(): void
{ {
$this->assertMediaType('image/webp', (string) $this->image->toWebp()); $this->assertMediaType('image/webp', $this->image->toWebp());
} }
public function testToBitmap(): void public function testToBitmap(): void
{ {
$this->assertMediaTypeBitmap((string) $this->image->toBitmap()); $this->assertMediaTypeBitmap($this->image->toBitmap());
$this->assertMediaTypeBitmap((string) $this->image->toBmp()); $this->assertMediaTypeBitmap($this->image->toBmp());
} }
public function testToAvif(): void public function testToAvif(): void
{ {
$this->assertMediaType('image/avif', (string) $this->image->toAvif()); $this->assertMediaType('image/avif', $this->image->toAvif());
} }
public function testToTiff(): void public function testToTiff(): void

View File

@@ -19,6 +19,6 @@ final class AvifEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2); $image = $this->createTestImage(3, 2);
$encoder = new AvifEncoder(10); $encoder = new AvifEncoder(10);
$result = $encoder->encode($image); $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); $image = $this->createTestImage(3, 2);
$encoder = new BmpEncoder(); $encoder = new BmpEncoder();
$result = $encoder->encode($image); $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); $image = $this->createTestImage(3, 2);
$encoder = new GifEncoder(); $encoder = new GifEncoder();
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
$this->assertFalse( $this->assertFalse(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced() Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
); );
@@ -31,7 +31,7 @@ final class GifEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2); $image = $this->createTestImage(3, 2);
$encoder = new GifEncoder(interlaced: true); $encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
$this->assertTrue( $this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced() Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
); );
@@ -42,7 +42,7 @@ final class GifEncoderTest extends ImagickTestCase
$image = $this->createTestAnimation(); $image = $this->createTestAnimation();
$encoder = new GifEncoder(interlaced: true); $encoder = new GifEncoder(interlaced: true);
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
$this->assertTrue( $this->assertTrue(
Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced() Decoder::decode((string) $result)->getFirstFrame()->getImageDescriptor()->isInterlaced()
); );

View File

@@ -19,6 +19,6 @@ final class HeicEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2); $image = $this->createTestImage(3, 2);
$encoder = new HeicEncoder(75); $encoder = new HeicEncoder(75);
$result = $encoder->encode($image); $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); $image = $this->createTestImage(3, 2);
$encoder = new Jpeg2000Encoder(75); $encoder = new Jpeg2000Encoder(75);
$result = $encoder->encode($image); $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); $image = $this->createTestImage(3, 2);
$encoder = new JpegEncoder(75); $encoder = new JpegEncoder(75);
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/jpeg', (string) $result); $this->assertMediaType('image/jpeg', $result);
} }
public function testEncodeProgressive(): void public function testEncodeProgressive(): void
@@ -30,7 +30,7 @@ final class JpegEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2); $image = $this->createTestImage(3, 2);
$encoder = new JpegEncoder(progressive: true); $encoder = new JpegEncoder(progressive: true);
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/jpeg', (string) $result); $this->assertMediaType('image/jpeg', $result);
$this->assertTrue($this->isProgressiveJpeg((string) $result)); $this->assertTrue($this->isProgressiveJpeg($result));
} }
} }

View File

@@ -24,8 +24,8 @@ final class PngEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2); $image = $this->createTestImage(3, 2);
$encoder = new PngEncoder(); $encoder = new PngEncoder();
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/png', (string) $result); $this->assertMediaType('image/png', $result);
$this->assertFalse($this->isInterlacedPng((string) $result)); $this->assertFalse($this->isInterlacedPng($result));
} }
public function testEncodeInterlaced(): void public function testEncodeInterlaced(): void
@@ -33,8 +33,8 @@ final class PngEncoderTest extends ImagickTestCase
$image = $this->createTestImage(3, 2); $image = $this->createTestImage(3, 2);
$encoder = new PngEncoder(interlaced: true); $encoder = new PngEncoder(interlaced: true);
$result = $encoder->encode($image); $result = $encoder->encode($image);
$this->assertMediaType('image/png', (string) $result); $this->assertMediaType('image/png', $result);
$this->assertTrue($this->isInterlacedPng((string) $result)); $this->assertTrue($this->isInterlacedPng($result));
} }
#[DataProvider('indexedDataProvider')] #[DataProvider('indexedDataProvider')]
@@ -42,7 +42,7 @@ final class PngEncoderTest extends ImagickTestCase
{ {
$this->assertEquals( $this->assertEquals(
$result, $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); $image = $this->createTestImage(3, 2);
$encoder = new TiffEncoder(); $encoder = new TiffEncoder();
$result = $encoder->encode($image); $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); $image = $this->createTestImage(3, 2);
$encoder = new WebpEncoder(75); $encoder = new WebpEncoder(75);
$result = $encoder->encode($image); $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(); $result = $this->readTestImage('blue.gif')->encode();
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
} }
public function testEncodeByMediaType(): void public function testEncodeByMediaType(): void
{ {
$result = $this->readTestImage('blue.gif')->encodeByMediaType(); $result = $this->readTestImage('blue.gif')->encodeByMediaType();
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
$result = $this->readTestImage('blue.gif')->encodeByMediaType('image/png'); $result = $this->readTestImage('blue.gif')->encodeByMediaType('image/png');
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result); $this->assertMediaType('image/png', $result);
} }
public function testEncodeByExtension(): void public function testEncodeByExtension(): void
{ {
$result = $this->readTestImage('blue.gif')->encodeByExtension(); $result = $this->readTestImage('blue.gif')->encodeByExtension();
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result); $this->assertMediaType('image/gif', $result);
$result = $this->readTestImage('blue.gif')->encodeByExtension('png'); $result = $this->readTestImage('blue.gif')->encodeByExtension('png');
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result); $this->assertMediaType('image/png', $result);
} }
public function testEncodeByPath(): void public function testEncodeByPath(): void
{ {
$result = $this->readTestImage('blue.gif')->encodeByPath(); $result = $this->readTestImage('blue.gif')->encodeByPath();
$this->assertInstanceOf(EncodedImage::class, $result); $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'); $result = $this->readTestImage('blue.gif')->encodeByPath('foo/bar.png');
$this->assertInstanceOf(EncodedImage::class, $result); $this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result); $this->assertMediaType('image/png', $result);
} }
public function testSaveAsFormat(): void public function testSaveAsFormat(): void
@@ -293,51 +293,51 @@ final class ImageTest extends ImagickTestCase
public function testToJpeg(): void public function testToJpeg(): void
{ {
$this->assertMediaType('image/jpeg', (string) $this->image->toJpeg()); $this->assertMediaType('image/jpeg', $this->image->toJpeg());
$this->assertMediaType('image/jpeg', (string) $this->image->toJpg()); $this->assertMediaType('image/jpeg', $this->image->toJpg());
} }
public function testToJpeg2000(): void public function testToJpeg2000(): void
{ {
$this->assertMediaType('image/jp2', (string) $this->image->toJpeg2000()); $this->assertMediaType('image/jp2', $this->image->toJpeg2000());
$this->assertMediaType('image/jp2', (string) $this->image->toJp2()); $this->assertMediaType('image/jp2', $this->image->toJp2());
} }
public function testToPng(): void public function testToPng(): void
{ {
$this->assertMediaType('image/png', (string) $this->image->toPng()); $this->assertMediaType('image/png', $this->image->toPng());
} }
public function testToGif(): void public function testToGif(): void
{ {
$this->assertMediaType('image/gif', (string) $this->image->toGif()); $this->assertMediaType('image/gif', $this->image->toGif());
} }
public function testToWebp(): void public function testToWebp(): void
{ {
$this->assertMediaType('image/webp', (string) $this->image->toWebp()); $this->assertMediaType('image/webp', $this->image->toWebp());
} }
public function testToBitmap(): void public function testToBitmap(): void
{ {
$this->assertMediaTypeBitmap((string) $this->image->toBitmap()); $this->assertMediaTypeBitmap($this->image->toBitmap());
$this->assertMediaTypeBitmap((string) $this->image->toBmp()); $this->assertMediaTypeBitmap($this->image->toBmp());
} }
public function testToAvif(): void public function testToAvif(): void
{ {
$this->assertMediaType('image/avif', (string) $this->image->toAvif()); $this->assertMediaType('image/avif', $this->image->toAvif());
} }
public function testToTiff(): void public function testToTiff(): void
{ {
$this->assertMediaType('image/tiff', (string) $this->image->toTiff()); $this->assertMediaType('image/tiff', $this->image->toTiff());
$this->assertMediaType('image/tiff', (string) $this->image->toTif()); $this->assertMediaType('image/tiff', $this->image->toTif());
} }
public function testToHeic(): void public function testToHeic(): void
{ {
$this->assertMediaType('image/heic', (string) $this->image->toHeic()); $this->assertMediaType('image/heic', $this->image->toHeic());
} }
public function testInvert(): void public function testInvert(): void

View File

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

View File

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