dfa1234 / ngx-image-compress

Angular library for uploading and compressing images
https://image-library.app
MIT License
86 stars 37 forks source link

EXIF Orientation may already be applied by the canvas #64

Closed byronigoe closed 2 years ago

byronigoe commented 2 years ago

CanvasRenderingContext2D.drawImage() automatically rotates the JPEG image based on the EXIF Orientation flag. Therefore applying the detected orientation a second time will rotate the image too much.

Perhaps it did not used to be the case, and perhaps it is not the case in some browsers, but at least it is in Chrome 95.0.4638.69

Here is an image I made for testing. The arrow points to the left in the raw data, but the EXIF Orientation value of 6 causes it to point up. up_exif

dfa1234 commented 2 years ago

Not linked to issue but thank a lot @byronigoe for you contribution. Yesterday I merged your changes (on 2 PR I had to apply them manually because of conflict, since I also sent a lot of change myself, but it's there)

If Chrome is changing its internal canvas API it's a big issue, I will test it asap

dfa1234 commented 2 years ago

I finally did a meaningful test and for what I see here, there is no problem. As you can see in the screenshot, here the result image point on the right in Chrome Version 97.0.4692.99 (Official Build) (64-bit)

The first image is the raw data, the arrow is pointing up.

The second image is the result of the compression. It's pointing on the right as expected. Why? If you run exiftool on your image, here what I get:

$ exiftool -Orientation up_exif.jpg
Orientation                     : Rotate 90 CW

So the arrow need to rotate 90 degree clockwise, and so is the result in the canvas.

Here the screenshot. I added your image to the list of demo-able images, if anyone need to be convinced:

Screenshot 2022-01-31 235313

byronigoe commented 2 years ago

@dfa1234 Your test shows the problem. The raw data has the arrow pointing left. Only after applying the EXIF orientation will the arrow point up (as you can see in the browser, which applies it). So, if you are getting the arrow pointing right, then you have rotated it again.

dfa1234 commented 2 years ago

@byronigoe you are perfectly right Here the file when I open it with GIMP image

It's a bummer. All the complexity some year ago was that the browser was not taking in account the rotation when drawing on the canvas with CanvasRenderingContext2D.drawImage() I need to dig a little more to understand what happened with this method implementation. BTW the problem is the same with an up-to-date version or firefox (on windows)

Edit:

Here our problem on [MDN website](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage#:~:text=In%20some%20older%20browser%20versions%2C%C2%A0drawImage()%20will%20ignore%20all%20EXIF%20metadata%20in%20images%2C%20including%20the%20Orientation.%20This%20behavior%20is%20especially%20troublesome%20on%20iOS%20devices.%20You%20should%20detect%20the%20Orientation%20yourself%20and%20use%20rotate()%20to%20make%20it%20right.)

Notes In some older browser versions, drawImage() will ignore all EXIF metadata in images, including the Orientation. This behavior is especially troublesome on iOS devices. You should detect the Orientation yourself and use rotate() to make it right.

Edit 2:

Maybe it's possible to test the browser version or just disable the code about the EXIF orentation. We will check the options soons More informations here : w3c/csswg-drafts#4666

dfa1234 commented 2 years ago

Tested on an real iphone 11 device, the test is OK

image

dfa1234 commented 2 years ago

Chrome 80 was ok (release date: February 4, 2020). The new canvas API seems to be from Chrome 81+ (release date: April 7, 2020)

chrome 79