From a62859fbf46ca74ed92fa2a90193ba3a6a8df9d8 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Thu, 5 Oct 2023 17:20:15 +0200 Subject: [PATCH] Add EXIF data decoding --- src/Drivers/Abstract/AbstractImage.php | 43 ++++++------------- .../Abstract/Decoders/AbstractDecoder.php | 20 +++++++++ .../Gd/Decoders/BinaryImageDecoder.php | 5 ++- .../Imagick/Decoders/BinaryImageDecoder.php | 1 + 4 files changed, 37 insertions(+), 32 deletions(-) diff --git a/src/Drivers/Abstract/AbstractImage.php b/src/Drivers/Abstract/AbstractImage.php index 7565dcf6..ba849194 100644 --- a/src/Drivers/Abstract/AbstractImage.php +++ b/src/Drivers/Abstract/AbstractImage.php @@ -2,7 +2,6 @@ namespace Intervention\Image\Drivers\Abstract; -use Exception; use Intervention\Gif\Exception\NotReadableException; use Intervention\Image\Collection; use Intervention\Image\EncodedImage; @@ -21,6 +20,7 @@ use Intervention\Image\Interfaces\SizeInterface; use Intervention\Image\Traits\CanHandleInput; use Intervention\Image\Traits\CanResolveDriverClass; use Intervention\Image\Traits\CanRunCallback; +use ReflectionProperty; abstract class AbstractImage implements ImageInterface { @@ -28,6 +28,10 @@ abstract class AbstractImage implements ImageInterface use CanHandleInput; use CanRunCallback; + protected Collection $exif; + + + public function eachFrame(callable $callback): ImageInterface { foreach ($this as $frame) { @@ -351,39 +355,16 @@ abstract class AbstractImage implements ImageInterface ); } - /** - * Read exif data from current image instance - * - * Returns value of given key or null if key was not found. If no - * parameter is given an array of all available data is returned. - * - * @param null|string $tag - * @return mixed - * @throws NotSupportedException - * @throws NotReadableException - */ - public function readExif(?string $tag = null): mixed + public function setExif(array $data): ImageInterface { - if (!function_exists('exif_read_data')) { - throw new NotSupportedException( - 'Reading Exif data is not supported by this PHP installation.' - ); - } + $this->exif = new Collection($data); - try { - $pointer = $this->toJpeg()->toFilePointer(); - $data = @exif_read_data($pointer); - } catch (Exception $e) { - throw new NotReadableException('Unable to read Exif data from this image.'); - } + return $this; + } - fclose($pointer); - - if (!is_null($tag) && is_array($data)) { - $data = array_key_exists($tag, $data) ? $data[$tag] : null; - } - - return is_array($data) ? new Collection($data) : $data; + public function getExif(?string $query = null): mixed + { + return is_null($query) ? $this->exif : $this->exif->get($query); } public function destroy(): void diff --git a/src/Drivers/Abstract/Decoders/AbstractDecoder.php b/src/Drivers/Abstract/Decoders/AbstractDecoder.php index 61e350d2..61fee9f3 100644 --- a/src/Drivers/Abstract/Decoders/AbstractDecoder.php +++ b/src/Drivers/Abstract/Decoders/AbstractDecoder.php @@ -2,6 +2,7 @@ namespace Intervention\Image\Drivers\Abstract\Decoders; +use Exception; use Intervention\Image\Exceptions\DecoderException; use Intervention\Image\Interfaces\ColorInterface; use Intervention\Image\Interfaces\DecoderInterface; @@ -31,6 +32,25 @@ abstract class AbstractDecoder implements DecoderInterface return $decoded; } + protected function decodeExifData(string $image_data): array + { + if (! function_exists('exif_read_data')) { + return []; + } + + try { + $pointer = fopen('php://temp', 'rw'); + fputs($pointer, $image_data); + rewind($pointer); + + $data = @exif_read_data($pointer, null, true); + } catch (Exception $e) { + $data = []; + } + + return is_array($data) ? $data : []; + } + protected function hasSuccessor(): bool { return $this->successor !== null; diff --git a/src/Drivers/Gd/Decoders/BinaryImageDecoder.php b/src/Drivers/Gd/Decoders/BinaryImageDecoder.php index 467493b0..60157efc 100644 --- a/src/Drivers/Gd/Decoders/BinaryImageDecoder.php +++ b/src/Drivers/Gd/Decoders/BinaryImageDecoder.php @@ -42,7 +42,10 @@ class BinaryImageDecoder extends AbstractDecoder implements DecoderInterface imagesavealpha($gd, true); - return new Image(new Collection([new Frame($gd)])); + $image = new Image(new Collection([new Frame($gd)])); + $image->setExif($this->decodeExifData($input)); + + return $image; } protected function decodeGif($input): ImageInterface diff --git a/src/Drivers/Imagick/Decoders/BinaryImageDecoder.php b/src/Drivers/Imagick/Decoders/BinaryImageDecoder.php index 5cb31596..ac4f1488 100644 --- a/src/Drivers/Imagick/Decoders/BinaryImageDecoder.php +++ b/src/Drivers/Imagick/Decoders/BinaryImageDecoder.php @@ -28,6 +28,7 @@ class BinaryImageDecoder extends AbstractDecoder implements DecoderInterface $image = new Image($imagick); $image->setLoops($imagick->getImageIterations()); + $image->setExif($this->decodeExifData($input)); return $image; }