Problem/Motivation

Drupal has various bugs with uploaded images that include image orientation from image EXIF data. Many modern phones use this, including iphone.

  1. With the default GD2 image toolkit, images appear rotated / upside down in Drupal because the toolkit discards EXIF orientation. There is a detailed description of this case in #3211441: Images incorrectly oriented because GD toolkit discards EXIF orientation.
  2. With the imagemagick toolkit, any image effects are applied incorrectly, for example the width and height may be swapped. The orientation is correct provided the browser supports it. According to can-i-use in September 2024, 95.4% of browsers did have this support, with most of the exceptions being software from 2020 or earlier.

Solutions in contrib

Enable EXIF Orientation, which resets all images to the natural orientation when the are first uploaded. There are some bugs which I hopefully fixed in #3477919: Refactor the image rotation logic.
With Image Effects module, add the 'auto orientation' effect at the start of all image styles. However this won't help if the image field has an upload constraint including maximum dimensions (with GD2, the EXIF orientation is lost on upload; with imagemagick the maximum dimensions are applied with height/width swapped, which is of course undetectable if they are equal).

Workaround

It seems likely the most image enhancement software (I tested GIMP) resaves the image without orientation, so avoiding the bug. This means that commercial sites with expert photographers potentially don't see the bug.

Proposed resolution

Create a new image toolkit operation named AutoOrient.

Reset orientation on upload, similar to EXIF Orientation module. This works by creating a new upload constraint that runs AutoOrient, which we can add in ImageWidget::formElement().

  • + Simple and the existing code is close to what we want in Core.
  • - The extra conversion could reduce image quality slightly (however the phone image is likely much higher resolution than needed for web, so it's likely irrelevant).

Alternative

Reset orientation at the start of processing for an image style, similar to Image Effects. This works by creating a new 'auto orient' image effect. However we should run it automatically, without requiring the admin to configure it, and also hide it from the image style UI.

Remaining tasks

User interface changes

API changes

Data model changes

Original report

so...i still see rotated image issues...

we fought this in d7, and hoped for better image orientation detection in d8...

Example:
http://foodtron.org/node/11

What does the wisdom of the group recommend?

Do we need another exif autodetect magic hack module?

this has been an issue for over 4 years...inherited by d8...

It was just a normal photo taken on my iphone 6s...and i remember this all the way back to iphone 3...

same pic on the phone via email comes out fine. attaching original pic to this thread.

@geerlingguy suggests:
The 'auto orientation' effect is part of 'Image Effects' (the spiritual successor to imagecache actions from D7): https://www.drupal.org/project/image_effects

See: https://github.com/drupal-media/image_effects#introduction (it's supported by both GD and ImageMagick).

Looks like it's not in core, though :(

Looks like this (https://www.drupal.org/node/2284577) is the closest thing to possibly making that happen. Outside of the media project, it looks like there's not much interest in doing the work :(

@barrett suggests:
And thus round 5274 of the Small Core vs Expected OOTB Functionality fight is begun....

It seems reasonable to me that whatever system provides image upload and display functionality should also have capability to figure out which way is up in the image.

@mark-trapp suggests:
This tends to happen when taking photos using a mobile device that allows you to access the shutter with a hardware button (like a volume button): iPhones and some (most?) Android phones have this feature.

Here's an article explaining the problem for iPhone (though you can find people confused about it on Android as well): http://iphonephotographyschool.com/iphone-photos-upside-down/

CommentFileSizeAuthor
#17 2664632-17.patch10.08 KBmorenstrat
image1.jpeg3.37 MBjacov

Comments

jacov created an issue. See original summary.

swentel’s picture

Title: D8 images upside down exif orientation » Add Auto orientation image effect
Version: 8.0.x-dev » 8.1.x-dev
Category: Bug report » Feature request
Priority: Major » Normal

It's available in https://www.drupal.org/project/image_effects so that's the way to go for now.
Moving to feature request.

wim leers’s picture

jacov’s picture

Issue summary: View changes
jacov’s picture

Issue tags: -Needs issue summary update +Review changes updated...
tim.plunkett’s picture

Issue tags: -Review changes updated...

That's not a real issue tag. And the issue summary is now missing the "Remaining tasks", "User interface changes", "API changes", and "Data model changes" sections...

jacov’s picture

Issue summary: View changes
mondrake’s picture

IMHO the problem here is a bit more complicated.

Adding an 'Auto orientation' effect will only work on building derivative images, i.e. on image files that are already uploaded.

But:
1) should it be added to all default styles (thumbnail, medium, large, etc.)? If so, why not to any style? But in that case, logically the auto orientation is not an effect, but something that needs to happen earlier than the image style loop of effects.
2) the Image field allows to set maximum image dimensions on the field definition (actually they are called 'Maximum image resolution', but there's a #847098: Revise image field min/max settings help text form for clarity to address that). Now, if an uploaded image exceeds those dimensions, it will be scaled to the maximum dimensions in file_validate_image_resolution before saving to disk. The scaling is performed via the image toolkit operation, which in the case of GD toolkit leads to dropping any EXIF metadata from the uploaded image. Result: it will no longer be possible to auto orient the uploaded image during a derivative generation process.

So it looks to me if this has to be addressed in core, it should rather be addressed on the Image field level, by adding an option to autorotate the image at the time of upload before the Exif info is lost. This will have the benefit of not needing to have an autorotation effect on all the image styles. But this would need (a) an autorotate image toolkit operation in core for GD, which in turn would require (b) to have core supporting a standard approach on getting Exif metadata from images, so that other toolkits can provide their own implementation. For (b), there's #2630242: Provide methods to retrieve EXIF image information via the Image object for discussion.

dman’s picture

Good analysis from @mondrake
We pondered much the same questions over in imagecache_actions when we introduced the autorotate action. I knew that a post-processing plugin wasn't *really* the appropriate place for such a process to live, yet could not imagine at what point further upstream it should live.

I agree - If this were to be added, it should be at a higher point in the system, like at upload/registration time, with a global flag that autocorrects all images if possible.

But EXIF support in PHP was significantly tedious. Hopefully there is a much nicer toolkit library to help us with that

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jacov’s picture

Category: Feature request » Bug report
Priority: Normal » Major

this is still a big problem.

majority of pictures coming from smartphones today are iphone, hence this makes Drupal buggy out of the box.

see issue here:
http://slime.bar/

tim.plunkett’s picture

Category: Bug report » Feature request

It can be major, but the absence of an important feature is not a bug, it's still a feature request.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

morenstrat’s picture

Assigned: Unassigned » morenstrat
Issue tags: +SprintWeekend2017, +SprintWeekendBerlin
morenstrat’s picture

Assigned: morenstrat » Unassigned
StatusFileSize
new10.08 KB

This patch simply copies the auto orient GD operation and auto orient image effect from the Image Effects moduleand adds them to Core. Namespaces, class names and annotations were adapted, particularly the GD operation name in order to not collide with the module's operation.

hansfn’s picture

Status: Active » Reviewed & tested by the community

I have tested the patch in comment 17 and it works perfectly for Drupal 8.2.6. I know this comment (and status change) isn't enough to get the patch into core, but at least other people finding this issue can know that it actually works.

PS! After applying the patch, clear cache and add the "Automatically correct orientation" effect as the first effect for all (used) image styles.

wim leers’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests
  1. +++ b/core/modules/image/src/Plugin/ImageEffect/AutoOrientateImageEffect.php
    @@ -0,0 +1,191 @@
    + *   id = "image_auto_orientate",
    ...
    +class AutoOrientateImageEffect extends ConfigurableImageEffectBase implements ContainerFactoryPluginInterface {
    

    Is "orientate" correct English?

  2. +++ b/core/modules/image/src/Plugin/ImageEffect/AutoOrientateImageEffect.php
    @@ -0,0 +1,191 @@
    +      // Issue a warning if the PHP EXIF extension is not enabled.
    

    Pointless comment.

  3. +++ b/core/modules/image/src/Plugin/ImageEffect/AutoOrientateImageEffect.php
    @@ -0,0 +1,191 @@
    +      '#markup' => $this->t("<p>Certain cameras can embed <em>orientation</em> information into image
    +        files when they save them. This information is embedded in an EXIF tag
    +        and can be used to rotate images to their correct position for display.
    +        <em>Not all cameras or images contain this information.</em>
    +        This process is only useful for images that contain this information,
    +        whereas for other images it is harmless.
    +        </p>
    +        <p>Although most modern browsers do support the orientation tag, the
    +        information may get lost or become incorrect by other operations.
    +        So, to support all browsers and prevent rotation errors, it is better to
    +        start each image style with this effect.
    +        </p>
    +        <p>The expected/supported values are:<br/>
    +        <strong>Tag</strong>: <code>0x0112  Orientation

    +

    +

      +
    • 1 = Horizontal (normal)
    • +

    • 3 = Rotate 180
    • +

    • 6 = Rotate 90 CW
    • +

    • 8 = Rotate 270 CW
    • +

    +

    Wikipedia: Exchangeable image file format

    + "),

    This looks… strange.

  4. +++ b/core/modules/image/src/Plugin/ImageEffect/AutoOrientateImageEffect.php
    @@ -0,0 +1,191 @@
    +    // Test to see if EXIF is supported by the image format.
    +    if (in_array($image->getMimeType(), ['image/jpeg', 'image/tiff'])) {
    

    This is not testing if EXIF is supported. This is hardcoding a list of MIME types. Let's then move them to a class constant.

  5. +++ b/core/modules/image/src/Plugin/ImageEffect/AutoOrientateImageEffect.php
    @@ -0,0 +1,191 @@
    +      // Hand over to toolkit.
    

    Pointless comment.

  6. +++ b/core/modules/image/src/Plugin/ImageEffect/AutoOrientateImageEffect.php
    @@ -0,0 +1,191 @@
    +    // Test to see if EXIF is supported by the image format.
    ...
    +    if (!in_array($mime_type, ['image/jpeg', 'image/tiff'])) {
    

    Same test again. Should probably then also have a protected helper method.

  7. +++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/AutoOrientate.php
    @@ -0,0 +1,77 @@
    +      // @todo: Add horizontal and vertical flips etc.
    +      // imagecopy seems to be able to mirror, see conmments on
    

    Do we need to fix this TODO or not?

    Also: s/conmments/comments/

  8. +++ b/core/modules/system/src/Plugin/ImageToolkit/Operation/gd/AutoOrientate.php
    @@ -0,0 +1,77 @@
    +      // @todo: Create sample set for tests.
    

    Yes, this is the most important information: this is very much missing test coverage.

mondrake’s picture

Re. #19.7 and #19.8, see #2857260: Auto orientation: GD toolkit operation does not cover all cases, tests missing in the contrib module.

In general, just moving the effect/toolkit ops from contrib to core does not address comments between #8 and #12.

nathaniel’s picture

This contrib module seems to be working nicely for iPhone photos:
https://www.drupal.org/project/exif_orientation

It rotates the images in hook_file_presave, so it happens before file_validate_image_resolution in the photos module.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

alan d.’s picture

Just found that this is an incomplete solution for the EXIF orientation, there are some "Flipped" versions that need to be rotated and flipped... which is a bigger issue requiring image rotate to handle this, so a followup child issue rather than a reason to hold this one up.

I'm sure there are better references, but this was the first one I found when looking for what a 5 state meant (degrees = 90 AND flipped)

http://www.impulseadventure.com/photo/exif-orientation.html

EXIF Orientation Value Row #0 is: Column #0 is:
1 Top Left side
2* Top Right side
3 Bottom Right side
4* Bottom Left side
5* Left side Top
6 Right side Top
7* Right side Bottom
8 Left side Bottom

NOTE: Values with "*" are uncommon since they represent "flipped" orientations.

mondrake’s picture

@Alan D. these cases were dealt with in Image Effects #2857260: Auto orientation: GD toolkit operation does not cover all cases, tests missing, see #20. If the current version of the effect there works as expected, then it might be worth updating the patch here to reflect those changes.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

candelas’s picture

Hello,

Any patch for Drupal 11 and 10?
Thanks

Edit: I see that Image Effects has the option, but it would be nice to have it in core for people that don't use this module.

adamps’s picture

I've just hit the rotated images problem on a site, so I've done some research.

This issue seems to be unclear:

  • The problem/motivation is "images uploaded from mobile devices such as iphone appear rotated / upside down in Drupal", which would be a bug.
  • The issue title is "Add Auto orientation image effect" which would be a feature.
  • The "proposed resolution" suggests that the second item would solve the first, but I believe that it's not really true.....

As far as I can see, in 2024 most browsers do support EXIF orientation. The main reason for the wrong orientation is that Drupal has stripped the EXIF metadata without correcting the orientation. The GD library appears to do this when it applies most image effects.

So analysing the proposed solution:

  1. In the case of an image style applying the image effect, the orientation effect could fix the bug. The site admin would need to apply the orientation effect first on all image styles. However this seems like bad UI as the admin is being forced to apply an effect that they don't expect to need in order to workaround a bug.
  2. Another case an image field constraint applying an image effect (most likely FileImageDimensions). In this case the correct orientation is lost before the file is ever saved, so there's no possible fix.

So in summary I believe that the "Auto orientation image effect" would be either a poor fix or no fix at all to the problem/motivation.

adamps’s picture

There is a similar issue #3211441: Images incorrectly oriented because GD toolkit discards EXIF orientation that is less active, but seems much more clear. The title and problem/motivation are consistent, and the proposed resolution is much more heading in the right direction: add exif_orientation module code into core.

I took a quick look and here's a quick summary of what I found:

  • The approach taken is to apply auto-orientation immediately when an image is uploaded. This has some potential downsides: it reduces image quality a little; it may remove EXIF data that the site owner needs, for example a contractual commitment to retain copyright information; it won't help with images that have already been uploaded.
  • The module is minimally maintained and and has quite a few open bugs, especially when using D10.3.
  • Even after fixing those, I feel that the code isn't the best approach that we would take in Core, partly inevitably so because Core doesn't expose the necessary hooks.

Still, the module is a good starting point, and it helped point me in the right direction, so thank you to the developers and maintainers.

adamps’s picture

I propose instead that we make the fix in the place where the problem is introduced: GDToolkit. The GD2 library loses EXIF data on many operations. Before doing such an operation, then the Drupal wrapper code should apply auto-orientation.

Perhaps another image toolkit is able to do many operations preserving EXIF data, in which case it won't need the same fix. A site admin may have chosen the other image toolkit exactly because they needed to preserve EXIF copyright statements. Therefore the fix should be specific to the image toolkit wrapper for whatever operations need it in that toolkit.

adamps’s picture

Issue summary: View changes
adamps’s picture

Sorry I belatedly see that I have duplicated #8 however that information wasn't in the IS. Hopefully I've helped future readers understand the key point by @mondrake.

  • We can add an image effect as a feature and it makes some useful code available.
  • However it won't (without further work) solve the bug that EXIF orientation data is already lost on upload.
  • Really we'd like the auto-rotate to happen automatically rather than the site admin needing to remember to add it in the UI.
adamps’s picture

Title: Add Auto orientation image effect » Bugs with images that include image orientation from image EXIF data
Category: Feature request » Bug report
Issue summary: View changes

I updated the IS with all my findings. I feel it's a bug not a feature, however feel free to reset if you don't agree.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.