Skip to content

Commit

Permalink
Implement Image::encodeByExtension()
Browse files Browse the repository at this point in the history
  • Loading branch information
olivervogel committed Dec 21, 2023
1 parent c6d52c3 commit 38cdd24
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 33 deletions.
4 changes: 3 additions & 1 deletion src/Drivers/Gd/Decoders/FilePathImageDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ public function decode(mixed $input): ImageInterface|ColorInterface
throw new DecoderException('Unable to decode input');
}

// decode image
$image = parent::decode(file_get_contents($input));

// set origin
// set file path on origin
$image->origin()->setFilePath($input);

return $image;
}
Expand Down
12 changes: 9 additions & 3 deletions src/Drivers/Imagick/Decoders/FilePathImageDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,24 @@ class FilePathImageDecoder extends BinaryImageDecoder implements DecoderInterfac
{
public function decode(mixed $input): ImageInterface|ColorInterface
{
if (! is_string($input)) {
if (!is_string($input)) {
throw new DecoderException('Unable to decode input');
}

try {
if (! @is_file($input)) {
if (!@is_file($input)) {
throw new DecoderException('Unable to decode input');
}
} catch (Exception $e) {
throw new DecoderException('Unable to decode input');
}

return parent::decode(file_get_contents($input));
// decode image
$image = parent::decode(file_get_contents($input));

// set file path on origin
$image->origin()->setFilePath($input);

return $image;
}
}
25 changes: 1 addition & 24 deletions src/Encoders/AutoEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

namespace Intervention\Image\Encoders;

use Intervention\Gif\Exception\EncoderException;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\ImageInterface;

class AutoEncoder implements EncoderInterface
class AutoEncoder extends MediaTypeEncoder
{
/**
* {@inheritdoc}
Expand All @@ -22,25 +20,4 @@ public function encode(ImageInterface $image): EncodedImageInterface
)
);
}

/**
* Return encoder matching to encode given media (mime) type
*
* @param string $type
* @return EncoderInterface
* @throws EncoderException
*/
protected function encoderByMediaType(string $type): EncoderInterface
{
return match ($type) {
'image/webp' => new WebpEncoder(),
'image/avif' => new AvifEncoder(),
'image/jpeg' => new JpegEncoder(),
'image/bmp' => new BmpEncoder(),
'image/gif' => new GifEncoder(),
'image/png' => new PngEncoder(),
'image/tiff' => new TiffEncoder(),
default => throw new EncoderException('No encoder found for media type (' . $type . ').'),
};
}
}
49 changes: 49 additions & 0 deletions src/Encoders/FileExtensionEncoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Intervention\Image\Encoders;

use Intervention\Gif\Exception\EncoderException;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\ImageInterface;

class FileExtensionEncoder extends AutoEncoder
{
/**
* Create new encoder instance to encode to format of given file extension
*
* @param null|string $extension
* @return void
*/
public function __construct(protected ?string $extension = null)
{
}

/**
* {@inheritdoc}
*
* @see EncoderInterface::encode()
*/
public function encode(ImageInterface $image): EncodedImageInterface
{
return $image->encode(
$this->encoderByFileExtension(
is_null($this->extension) ? $image->origin()->fileExtension() : $this->extension
)
);
}

protected function encoderByFileExtension(string $extension): EncoderInterface
{
return match ($extension) {
'webp' => new WebpEncoder(),
'avif' => new AvifEncoder(),
'jpeg', 'jpg' => new JpegEncoder(),
'bmp' => new BmpEncoder(),
'gif' => new GifEncoder(),
'png' => new PngEncoder(),
'tiff', 'tif' => new TiffEncoder(),
default => throw new EncoderException('No encoder found for file extension (' . $extension . ').'),
};
}
}
31 changes: 27 additions & 4 deletions src/Encoders/MediaTypeEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

namespace Intervention\Image\Encoders;

use Intervention\Gif\Exception\EncoderException;
use Intervention\Image\Interfaces\EncodedImageInterface;
use Intervention\Image\Interfaces\EncoderInterface;
use Intervention\Image\Interfaces\ImageInterface;

class MediaTypeEncoder extends AutoEncoder
class MediaTypeEncoder implements EncoderInterface
{
/**
* Create new encoder instance to encode given media (mime) type
Expand All @@ -24,10 +26,31 @@ public function __construct(protected ?string $type = null)
*/
public function encode(ImageInterface $image): EncodedImageInterface
{
$type = is_null($this->type) ? $image->origin()->mediaType() : $this->type;

return $image->encode(
$this->encoderByMediaType(
is_null($this->type) ? $image->origin()->mediaType() : $this->type
)
$this->encoderByMediaType($type)
);
}

/**
* Return new encoder by given media (MIME) type
*
* @param string $type
* @return EncoderInterface
* @throws EncoderException
*/
protected function encoderByMediaType(string $type): EncoderInterface
{
return match ($type) {
'image/webp' => new WebpEncoder(),
'image/avif' => new AvifEncoder(),
'image/jpeg' => new JpegEncoder(),
'image/bmp' => new BmpEncoder(),
'image/gif' => new GifEncoder(),
'image/png' => new PngEncoder(),
'image/tiff' => new TiffEncoder(),
default => throw new EncoderException('No encoder found for media type (' . $type . ').'),
};
}
}
11 changes: 11 additions & 0 deletions src/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Intervention\Image\Encoders\AutoEncoder;
use Intervention\Image\Encoders\AvifEncoder;
use Intervention\Image\Encoders\BmpEncoder;
use Intervention\Image\Encoders\FileExtensionEncoder;
use Intervention\Image\Encoders\GifEncoder;
use Intervention\Image\Encoders\JpegEncoder;
use Intervention\Image\Encoders\MediaTypeEncoder;
Expand Down Expand Up @@ -755,6 +756,16 @@ public function encodeByMediaType(?string $type = null): EncodedImageInterface
return $this->encode(new MediaTypeEncoder($type));
}

/**
* {@inheritdoc}
*
* @see ImageInterface::encodeByExtension()
*/
public function encodeByExtension(?string $extension = null): EncodedImageInterface
{
return $this->encode(new FileExtensionEncoder($extension));
}

/**
* {@inheritdoc}
*
Expand Down
10 changes: 10 additions & 0 deletions src/Interfaces/ImageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,16 @@ public function drawLine(callable $init): ImageInterface;
*/
public function encodeByMediaType(?string $type = null): EncodedImageInterface;

/**
* Encode the image into the format represented by the given extension. If no
* extension is given the image will be encoded to the format of the
* originally read image.
*
* @param null|string $extension
* @return EncodedImageInterface
*/
public function encodeByExtension(?string $extension = null): EncodedImageInterface;

/**
* Encode image to JPEG format
*
Expand Down
35 changes: 34 additions & 1 deletion src/Origin.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,53 @@ class Origin
* Create new origin instance
*
* @param string $mediaType
* @param null|string $filePath
* @return void
*/
public function __construct(
protected string $mediaType = 'application/octet-stream'
protected string $mediaType = 'application/octet-stream',
protected ?string $filePath = null
) {
}

/**
* Return media type of origin
*
* @return string
*/
public function mediaType(): string
{
return $this->mediaType;
}

/**
* Alias of self::mediaType()
*/
public function mimetype(): string
{
return $this->mediaType();
}

/**
* Set file path for origin
*
* @param string $path
* @return Origin
*/
public function setFilePath(string $path): self
{
$this->filePath = $path;

return $this;
}

/**
* Return file extension if origin was created from file path
*
* @return null|string
*/
public function fileExtension(): ?string
{
return empty($this->filePath) ? null : pathinfo($this->filePath, PATHINFO_EXTENSION);
}
}
11 changes: 11 additions & 0 deletions tests/Drivers/Gd/ImageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,17 @@ public function testEncodeByMediaType(): void
$this->assertMediaType('image/png', (string) $result);
}

public function testEncodeByExtension(): void
{
$result = $this->readTestImage('blue.gif')->encodeByExtension();
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result);

$result = $this->readTestImage('blue.gif')->encodeByExtension('png');
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
}

public function testWidthHeightSize(): void
{
$this->assertEquals(3, $this->image->width());
Expand Down
11 changes: 11 additions & 0 deletions tests/Drivers/Imagick/ImageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,17 @@ public function testEncodeByMediaType(): void
$this->assertMediaType('image/png', (string) $result);
}

public function testEncodeByExtension(): void
{
$result = $this->readTestImage('blue.gif')->encodeByExtension();
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/gif', (string) $result);

$result = $this->readTestImage('blue.gif')->encodeByExtension('png');
$this->assertInstanceOf(EncodedImage::class, $result);
$this->assertMediaType('image/png', (string) $result);
}

public function testWidthHeightSize(): void
{
$this->assertEquals(20, $this->image->width());
Expand Down
9 changes: 9 additions & 0 deletions tests/OriginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,13 @@ public function testMediaType(): void
$origin = new Origin('image/gif');
$this->assertEquals('image/gif', $origin->mediaType());
}

public function testFileExtension(): void
{
$origin = new Origin('image/jpeg', __DIR__ . '/tests/images/example.jpg');
$this->assertEquals('jpg', $origin->fileExtension());

$origin = new Origin('image/jpeg');
$this->assertEquals('', $origin->fileExtension());
}
}

0 comments on commit 38cdd24

Please sign in to comment.