python-pillow / Pillow

Python Imaging Library (Fork)
https://python-pillow.org
Other
12.29k stars 2.23k forks source link

CR2 / TIFF image loads with incorrectly applied orientation / rotation #8554

Open Knio opened 18 hours ago

Knio commented 18 hours ago

What did you do?

Opening a .CR2 image loads the image with an incorrectly applied EXIF orientation. The end result in one case is that the image is flipped upsidedown.

Windows explorer and Adobe bridge both show the image correctly in previews, and when opening the full image. image

What did you expect to happen?

Do not rotate the image at all, and expose the EXIF tag to the user -or- just orient properly

What actually happened?

Incorrect image

What are your OS, Python and Pillow versions?

--------------------------------------------------------------------
Pillow 11.0.0
Python 3.12.1 (tags/v3.12.1:2305ca5, Dec  7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)]
--------------------------------------------------------------------
Python executable is C:\Program Files\Python312\python.exe
System Python files loaded from C:\Program Files\Python312
--------------------------------------------------------------------
Python Pillow modules loaded from C:\Users\Tom\AppData\Roaming\Python\Python312\site-packages\PIL
Binary Pillow modules loaded from C:\Users\Tom\AppData\Roaming\Python\Python312\site-packages\PIL
--------------------------------------------------------------------
--- PIL CORE support ok, compiled for 11.0.0
*** TKINTER support not installed
--- FREETYPE2 support ok, loaded 2.13.3
--- LITTLECMS2 support ok, loaded 2.16
--- WEBP support ok, loaded 1.4.0
--- JPEG support ok, compiled for libjpeg-turbo 3.0.4
--- OPENJPEG (JPEG2000) support ok, loaded 2.5.2
--- ZLIB (PNG/ZIP) support ok, loaded 1.3.1
--- LIBTIFF support ok, loaded 4.6.0
*** RAQM (Bidirectional Text) support not installed
*** LIBIMAGEQUANT (Quantization method) support not installed
*** XCB (X protocol) support not installed
--------------------------------------------------------------------
import sys

import pathlib
import PIL.Image
import PIL.ImageCms

from PIL import report

root = pathlib.Path(r'.')
img_path = root / '_MG_6885.CR2'

img = PIL.Image.open(img_path)

print(f'format:{img.format} mode:{img.mode} size:{img.size}')
for k, v in img.getexif().items():
  print(f'{k}: {v!r}')

img.save(img_path.with_suffix('.plain.jpg'), format='JPEG')

img = PIL.ImageOps.exif_transpose(img)
img.save(img_path.with_suffix('.exif_transpose.jpg'), format='JPEG')

_MG_6885.zip

Knio commented 18 hours ago

NOTE: Commenting out this line of code fixes the issue, at least in the sense of then it does not rotate at all (and is in the native sensor orientation) However, the orientation tag is still not exposed to img.getexif() for some reason

https://github.com/python-pillow/Pillow/blob/main/src/PIL/TiffImagePlugin.py#L1317-L1319

radarhere commented 17 hours ago

It's not yet clear to me why the final image is unexpected.

exiftool _MG_6885.CR2 prints out 'Orientation : Rotate 90 CW', and that is what Pillow is applying to the data that it reads.

However, the orientation tag is still not exposed to img.getexif() for some reason

When a TIFF image is automatically transposed on load, del self.tag_v2[ExifTags.Base.Orientation] removes the orientation tag so that it isn't seen by getexif(). This is deliberate, so that exif_transpose() won't see that the tag is still there and try to transpose the image again, leading to a double transpose.

Knio commented 6 hours ago

Sorry, I meant in my test I commented out all 3 lines there

radarhere commented 2 hours ago

If I make that change, I do see the Orientation tag printed out by your script.

import pathlib
import PIL.Image, PIL.ExifTags

root = pathlib.Path(r'.')
img_path = root / '_MG_6885.CR2'

img = PIL.Image.open(img_path)

print(img.getexif()[PIL.ExifTags.Base.Orientation])  # 6