Skip to content

Commit

Permalink
Handle mirrored image uploads correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonkelly committed Jan 2, 2025
1 parent 3db93e8 commit 37b895b
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
- Deprecated the `ucfirst` Twig filter. `capitalize` should be used instead.

## Extensibility
- Added `craft\helpers\Image::EXIF_IFD0_ROTATE_0_MIRRORED`.
- Added `craft\helpers\Image::EXIF_IFD0_ROTATE_0`.
- Added `craft\helpers\Image::EXIF_IFD0_ROTATE_180_MIRRORED`.
- Added `craft\helpers\Image::EXIF_IFD0_ROTATE_270_MIRRORED`.
- Added `craft\helpers\Image::EXIF_IFD0_ROTATE_90_MIRRORED`.
- `GuzzleHttp\Client` is now instantiated via `Craft::createObject()`. ([#16366](https://github.com/craftcms/cms/pull/16366))
- `craft\helpers\DateTimeHelper::humanDuration()` now has a `$language` argument. ([#16332](https://github.com/craftcms/cms/pull/16332))

Expand All @@ -21,4 +26,5 @@
- Pages which contain image transform generation URLs now set no-cache headers. ([#16195](https://github.com/craftcms/cms/discussions/16195))
- Action requests (such as `actions/app/health-check`) now send no-cache headers by default. ([#16364](https://github.com/craftcms/cms/pull/16364))
- Fixed a bug where `craft\config\GeneralConfig::safeMode()` set Safe Mode to `false` by default.
- Fixed a bug where Craft wasn’t auto-rotating or flipping images uploaded with a mirrored EXIF orientation.
- Updated Twig to 3.15. ([#16207](https://github.com/craftcms/cms/discussions/16207))
10 changes: 10 additions & 0 deletions src/helpers/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,18 @@
*/
class Image
{
/** @since 4.14.0 */
public const EXIF_IFD0_ROTATE_0 = 1;
/** @since 4.14.0 */
public const EXIF_IFD0_ROTATE_0_MIRRORED = 2;
public const EXIF_IFD0_ROTATE_180 = 3;
/** @since 4.14.0 */
public const EXIF_IFD0_ROTATE_180_MIRRORED = 4;
/** @since 4.14.0 */
public const EXIF_IFD0_ROTATE_90_MIRRORED = 5;
public const EXIF_IFD0_ROTATE_90 = 6;
/** @since 4.14.0 */
public const EXIF_IFD0_ROTATE_270_MIRRORED = 7;
public const EXIF_IFD0_ROTATE_270 = 8;

/**
Expand Down
38 changes: 22 additions & 16 deletions src/services/Images.php
Original file line number Diff line number Diff line change
Expand Up @@ -379,27 +379,33 @@ public function rotateImageByExifData(string $filePath): bool
$image = new \Imagick($filePath);
$orientation = $image->getImageOrientation();

$degrees = false;

switch ($orientation) {
case ImageHelper::EXIF_IFD0_ROTATE_180:
$degrees = 180;
break;
case ImageHelper::EXIF_IFD0_ROTATE_90:
$degrees = 90;
break;
case ImageHelper::EXIF_IFD0_ROTATE_270:
$degrees = 270;
break;
}

if ($degrees === false) {
$degrees = match ($orientation) {
ImageHelper::EXIF_IFD0_ROTATE_180, ImageHelper::EXIF_IFD0_ROTATE_180_MIRRORED => 180,
ImageHelper::EXIF_IFD0_ROTATE_90, ImageHelper::EXIF_IFD0_ROTATE_90_MIRRORED => 90,
ImageHelper::EXIF_IFD0_ROTATE_270, ImageHelper::EXIF_IFD0_ROTATE_270_MIRRORED => 270,
default => 0,
};

$mirrored = match ($orientation) {
ImageHelper::EXIF_IFD0_ROTATE_0_MIRRORED, ImageHelper::EXIF_IFD0_ROTATE_180_MIRRORED,
ImageHelper::EXIF_IFD0_ROTATE_90_MIRRORED, ImageHelper::EXIF_IFD0_ROTATE_270_MIRRORED => true,
default => false,
};

if ($degrees === 0 && !$mirrored) {
return false;
}

/** @var Raster $image */
$image = $this->loadImage($filePath);
$image->rotate($degrees);

if ($degrees !== 0) {
$image->rotate($degrees);
}

if ($mirrored) {
$image->flipHorizontally();
}

return $image->saveAs($filePath, true);
}
Expand Down

0 comments on commit 37b895b

Please sign in to comment.