From f3122ae4367b7cdab972e02804195b0ebd91aa7b Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Thu, 5 Oct 2023 17:27:51 +0200 Subject: [PATCH] Fix image orientation with GD driver --- .../Abstract/Decoders/AbstractDecoder.php | 22 +++++++++---------- .../Gd/Decoders/BinaryImageDecoder.php | 13 ++++++++++- src/Interfaces/ImageInterface.php | 15 +++++++++++++ 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/Drivers/Abstract/Decoders/AbstractDecoder.php b/src/Drivers/Abstract/Decoders/AbstractDecoder.php index 61fee9f3..52bcd1b0 100644 --- a/src/Drivers/Abstract/Decoders/AbstractDecoder.php +++ b/src/Drivers/Abstract/Decoders/AbstractDecoder.php @@ -32,6 +32,16 @@ abstract class AbstractDecoder implements DecoderInterface return $decoded; } + protected function hasSuccessor(): bool + { + return $this->successor !== null; + } + + protected function inputType($input): AbstractType + { + return MimeSniffer::createFromString($input)->getType(); + } + protected function decodeExifData(string $image_data): array { if (! function_exists('exif_read_data')) { @@ -42,22 +52,12 @@ abstract class AbstractDecoder implements DecoderInterface $pointer = fopen('php://temp', 'rw'); fputs($pointer, $image_data); rewind($pointer); - $data = @exif_read_data($pointer, null, true); + fclose($pointer); } catch (Exception $e) { $data = []; } return is_array($data) ? $data : []; } - - protected function hasSuccessor(): bool - { - return $this->successor !== null; - } - - protected function inputType($input): AbstractType - { - return MimeSniffer::createFromString($input)->getType(); - } } diff --git a/src/Drivers/Gd/Decoders/BinaryImageDecoder.php b/src/Drivers/Gd/Decoders/BinaryImageDecoder.php index 60157efc..ae90dd86 100644 --- a/src/Drivers/Gd/Decoders/BinaryImageDecoder.php +++ b/src/Drivers/Gd/Decoders/BinaryImageDecoder.php @@ -42,10 +42,21 @@ class BinaryImageDecoder extends AbstractDecoder implements DecoderInterface imagesavealpha($gd, true); + // build image instance $image = new Image(new Collection([new Frame($gd)])); $image->setExif($this->decodeExifData($input)); - return $image; + // fix image orientation + return match ($image->getExif('IFD0.Orientation')) { + 2 => $image->flip(), + 3 => $image->rotate(180), + 4 => $image->rotate(180)->flip(), + 5 => $image->rotate(270)->flip(), + 6 => $image->rotate(270), + 7 => $image->rotate(90)->flip(), + 8 => $image->rotate(90), + default => $image + }; } protected function decodeGif($input): ImageInterface diff --git a/src/Interfaces/ImageInterface.php b/src/Interfaces/ImageInterface.php index 34b42f12..45b257db 100644 --- a/src/Interfaces/ImageInterface.php +++ b/src/Interfaces/ImageInterface.php @@ -3,6 +3,7 @@ namespace Intervention\Image\Interfaces; use Countable; +use Intervention\Image\Collection; use Intervention\Image\EncodedImage; use Traversable; @@ -55,6 +56,20 @@ interface ImageInterface extends Traversable, Countable */ public function getSize(): SizeInterface; + /** + * Return exif data of current image + * + * @return mixed + */ + public function getExif(?string $query = null): mixed; + + /** + * Set exif data on current image (will not be written in final image) + * + * @return ImageInterface + */ + public function setExif(array $data): ImageInterface; + /** * Determine if current image is animated *