Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions src/Decoders/NativeObjectDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Intervention\Image\Drivers\SpecializableDecoder;
use Intervention\Image\Drivers\Vips\Core;
use Intervention\Image\Drivers\Vips\Modifiers\AlignRotationModifier;
use Intervention\Image\Exceptions\DecoderException;
use Intervention\Image\Exceptions\RuntimeException;
use Intervention\Image\Image;
Expand Down Expand Up @@ -35,17 +36,17 @@ public function decode(mixed $input): ImageInterface|ColorInterface
throw new DecoderException('Unable to decode input');
}

// auto-rotate
if ($this->driver()->config()->autoOrientation === true) {
$input = $input->autorot();
}

// build image instance
$image = new Image(
$this->driver(),
new Core($input)
);

// auto-rotate
if ($this->driver()->config()->autoOrientation === true && $this->exifRotation($input) > 1) {
$image->modify(new AlignRotationModifier());
}

// set media type on origin
if ($mediaType = $this->vipsMediaType($input)) {
$image->origin()->setMediaType($mediaType);
Expand Down Expand Up @@ -96,4 +97,22 @@ protected function vipsMediaType(VipsImage $vips): ?MediaType
default => null
};
}

/**
* Return the exif rotation of the given image or null if there isn't any
*/
protected function exifRotation(VipsImage $vips): ?int
{
if (!in_array('orientation', $vips->getFields())) {
return null;
}

try {
$orientation = $vips->get('orientation');
} catch (VipsException) {
return null;
}

return is_int($orientation) ? $orientation : null;
}
}
4 changes: 3 additions & 1 deletion src/Modifiers/AlignRotationModifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Intervention\Image\Drivers\Vips\Modifiers;

use Intervention\Image\Drivers\Vips\Core;
use Intervention\Image\Interfaces\ImageInterface;
use Intervention\Image\Interfaces\SpecializedInterface;
use Intervention\Image\Modifiers\AlignRotationModifier as GenericAlignRotationModifier;
Expand All @@ -18,7 +19,8 @@ class AlignRotationModifier extends GenericAlignRotationModifier implements Spec
public function apply(ImageInterface $image): ImageInterface
{
$image->core()->setNative(
$image->core()->native()->autorot()
// autorot() does not seem to work with the default sequential access of this library
Core::ensureInMemory($image->core())->native()->autorot()
);

return $image;
Expand Down
20 changes: 20 additions & 0 deletions tests/Unit/Modifiers/AlignRotationModifierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,29 @@ public function testApply(): void
$image = (new ImageManager(Driver::class, autoOrientation: false))->read(
$this->getTestResourcePath('orientation.jpg')
);

$this->assertColor(250, 2, 3, 255, $image->pickColor(3, 3));
$result = $image->orient();
$this->assertColor(1, 0, 254, 255, $image->pickColor(3, 3));
$this->assertColor(1, 0, 254, 255, $result->pickColor(3, 3));
}

/**
* According to libvips/libvips#4475 you can't use autorot with
* orientated JPEGs and sequential access. This test checks the negative
* scenario, before the fix.
*/
public function testAutoOrientationSave(): void
{
$tmpFile = sys_get_temp_dir() . '/out.jpg';

(new ImageManager(Driver::class, autoOrientation: true))->read(
$this->getTestResourcePath('orientation.jpg')
)->save($tmpFile);

$this->assertFileExists($tmpFile);

// remove tmp file
unlink($tmpFile);
}
}