Closed gbresciano closed 4 years ago
+1 I just ran into the same issue as well.
It seems that the latest version of safari autorotates based on EXIF data and then the image loader rotates again
Yes, I can confirm that this is the case, I've removed the orientation attribute and indeed the correct orientation is rendered!
I suspect this might be linked to the implementation of a new css property called image-orientation (https://webkit.org/css-status/#property-image-orientation)
As a temporary workaround, I'm only enabling the orientation option if the image-orientation css property is not available
{ orientation: document.createElement('img').style.imageOrientation === undefined }
Thanks @gbresciano for this research and workaround!
I just noticed firefox has css image-orientation but doesn't rotate the photo automatically, so the workaround is not good
I was going to work-around this by checking for the version of Safari, but I have noticed that if you choose to resize on iOS or iPados then it strips the exif data. So now I don't now what to do.
What about checking if default-orientation computed value is "from-image" and disabling orientation if that is the case?
{ orientation: getComputedStyle(document.body).imageOrientation !== 'from-image' }
Would it be possible for the library to just force to use image-orientation: 'none' when generating the image? Does canvas drawImage respect that?
Edit: I'm afraid on safari canvas doesn't care about that and uses the default image-from behaviour: check this url on safari: https://mcc.id.au/2020/image-orientation/ Related chromium issue: https://github.com/w3c/csswg-drafts/issues/4666
Thanks for the report @gbresciano and everyone's comments. As visible from @beavis chromium issue link, the same problem affects the next major version of Chrome (v81).
I have not found a good workaround using the style.imageOrientation
property on either the img
or document.body
elements.
I was originally hoping that I can set img.style.imageOrientation = 'none'
before drawing into the canvas
element from the img
source, but this had no effect.
I do have a workaround testing EXIF image orientation support the same as in the unit tests: https://github.com/blueimp/JavaScript-Load-Image/blob/452adbfc9f4980e0bed0d97d19fc2343475c447f/test/test.js#L839-L854 But that means including a 713 Bytes JPEG image (might be possible to make it smaller) in the library itself.
Will test a bit further before pushing a fix.
I was originally hoping that I can set
img.style.imageOrientation = 'none'
before drawing into thecanvas
element from theimg
source, but this had no effect.
That was my initial thought and in chrome canary looks like it's actually working, either setting it on the image or in the canvas element makes it render in the original orientation, but seems safari does not support that, you can check it on last row of images here: https://mcc.id.au/2020/image-orientation/
But that means including a 713 Bytes JPEG image (might be possible to make it smaller) in the library itself.
I was testing checking against computed value of imageOrientation property, not sure how safe or future proof this is. Would this 329 bytes jpg work for the check? https://raw.githubusercontent.com/beavis/orientation/master/orientation6.jpg
Yes, that looks usable.
I was thinking about basing a minimum file on https://github.com/mathiasbynens/small/blob/master/jpeg.jpg, but I've only ever researched JPEG image headers, not JPEG image content.
I can't decode that one, seems it's an arithmetic JPG but it that works for your test it will be smaller for sure. I just created a sample 2x1 black image with an image editor and ran jpegoptim against it then added the exif field. In case you need it I just added an MIT license readme to that repo, but I don't mind about that at all, take the file as yours.
By the way, looks like safari ignoring image-context: none on canvas drawImage is a bug that has already been patched: https://bugs.webkit.org/show_bug.cgi?id=209849
Good news about the safari patch, that would allow a workaround without a test image.
Didn't know that jpegoptim
works that well for minimal files, I'll use the same approach, thanks.
Which tool did you use to add the EXIF info?
I have a 350 bytes file that is black/white 1x2 pixels and has the Orientation flag, transplanted via jhead
, but was wondering if there's a better tool.
Which tool did you use to add the EXIF info?
I just used a GUI for exiftool, not sure if that works any better than your approach.
Thanks!
Edit: I've found a way to only write the minimal headers with exiftool.
For reference, here's the command-line I used to create a 350 bytes version with EXIF Orientation
and IPTC ObjectName
properties:
exiftool -all= -Orientation#=6 -YCbCrPositioning= -ResolutionUnit= -YResolution= -XResolution= -ObjectName=test image.jpg
I've released blueimp-load-image@2.29.0
that fixes this orientation issue.
thanks @blueimp!
Orientation is fixed but something wrong with data.originalHeight and data.originalWidth; On desktop it returns width and height as before orientation fix, on mobile chrome it returns viseverse
The originalWidth
/originalHeight
properties are set on image load:
https://github.com/blueimp/JavaScript-Load-Image/blob/ff22e11daa25d0cff328124abf1cca22ffaa4be5/js/load-image.js#L132-L140
For browsers with automatic image orientation support, those properties will reflect the dimensions of the image after orientation correction.
Yes, but there is no consistency, I can not relay on originalWidth/originalHeight
any more, I have an image A.jpg and it has vary dimensions from browser to browser, so only one solution I found it is using width and height from exif but it is strange
That inconsistency comes from the difference in browser support.
If exif parsing is enabled, we could normalize the originalWidth/originalHeight
properties, but then we have an inconsistency between loading an image with exif parsing enabled and loading one without. It might still be worth it though, so I'll think about introducing this normalization.
Now I need to do like this (also I need to swap w/h if it is rotated):
const orient = data.exif ? data.exif.get('Orientation') : null;
const oWidth = data.exif ? (data.exif[256] || data.originalWidth) : data.originalWidth;
const oHeight = data.exif ? (data.exif[257] || data.originalHeight) : data.originalHeight;
let width = oWidth;
let height = oHeight;
if (4 < orient && orient < 9) {
width = oHeight;
height = oWidth;
}
I've added original width+height dimensions normalization in this commit: https://github.com/blueimp/JavaScript-Load-Image/commit/61761388e0b9fff19acef3c4d5c1413c11b8c843 It will be part of the next release.
Hi, first, I want to thank you for this library. It's been very useful for me.
It seems that there's a problem with the last version of safari. When loading a portrait image (orientation = 6) it shows up as a landscape image You can reproduce it with this image in the demo and you'll notice that the result is rotated as in this screenshot:
This doesn't happen in chrome.
Can you help?
Thanks!