JS Client-Side Exif Orientation: Rotate and Mirror JPEG Images
The github project JavaScript-Load-Image provides a complete solution to the EXIF orientation problem, correctly rotating/mirroring images for all 8 exif orientations. See the online demo of javascript exif orientation
The image is drawn onto an HTML5 canvas. Its correct rendering is implemented in js/load-image-orientation.js through canvas operations.
Hope this saves somebody else some time, and teaches the search engines about this open source gem :)
Accessing JPEG EXIF rotation data in JavaScript on the client side
If you only want the orientation tag and nothing else and don't like to include another huge javascript library I wrote a little code that extracts the orientation tag as fast as possible (It uses DataView and readAsArrayBuffer
which are available in IE10+, but you can write your own data reader for older browsers):
function getOrientation(file, callback) { var reader = new FileReader(); reader.onload = function(e) {
var view = new DataView(e.target.result); if (view.getUint16(0, false) != 0xFFD8) { return callback(-2); } var length = view.byteLength, offset = 2; while (offset < length) { if (view.getUint16(offset+2, false) <= 8) return callback(-1); var marker = view.getUint16(offset, false); offset += 2; if (marker == 0xFFE1) { if (view.getUint32(offset += 2, false) != 0x45786966) { return callback(-1); }
var little = view.getUint16(offset += 6, false) == 0x4949; offset += view.getUint32(offset + 4, little); var tags = view.getUint16(offset, little); offset += 2; for (var i = 0; i < tags; i++) { if (view.getUint16(offset + (i * 12), little) == 0x0112) { return callback(view.getUint16(offset + (i * 12) + 8, little)); } } } else if ((marker & 0xFF00) != 0xFF00) { break; } else { offset += view.getUint16(offset, false); } } return callback(-1); }; reader.readAsArrayBuffer(file);}
// usage:var input = document.getElementById('input');input.onchange = function(e) { getOrientation(input.files[0], function(orientation) { alert('orientation: ' + orientation); });}
<input id='input' type='file' />
Trying to fix the orientation of image on client side with jQuery. [EXIF is not defined]
Does this work?
function readURLimg(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
var img = $('#img-file')
img.attr('src', e.target.result).width('50%').height('auto');
fixExifOrientation(img)
}
reader.readAsDataURL(input.files[0]);
}
}
function fixExifOrientation($img) {
$img.on('load', function() {
EXIF.getData($img[0], function() {
console.log('Exif=', EXIF.getTag(this, "Orientation"));
switch(parseInt(EXIF.getTag(this, "Orientation"))) {
case 2:
$img.addClass('flip'); break;
case 3:
$img.addClass('rotate-180'); break;
case 4:
$img.addClass('flip-and-rotate-180'); break;
case 5:
$img.addClass('flip-and-rotate-270'); break;
case 6:
$img.addClass('rotate-90'); break;
case 7:
$img.addClass('flip-and-rotate-90'); break;
case 8:
$img.addClass('rotate-270'); break;
}
});
});
}
Different rotation of image on PC and through input type file
There are two main metadata tags for specifying image orientation:
Orientation: [TopLeft, BottomRight, RightTop, LeftBottom]
and
exif:Orientation: [1, 3, 6, 8]
I suspect your image was taken by a device, which uses exif:Orientation
meta tag. Ubuntu default image viewer supports exif:Orientation
and thus it displays the image correctly. Browsers, however, do not support this tag (for backward compatibility reasons) and they have to fall back to the default orientation which is rotated 90 deg to right in your case.
You could solve your issue by supplementing your images with the Orientation
meta tag. This could be done with most image viewing software by simply rotating your image and saving it in place (in Ubuntu you will see the image rotated properly, so simply rotate it in any direction and rotate it back and save).
How to adjust the orientation of a image in order to show proper preview of the image?
How about just rotating the image with CSS?
reader.onload = function (e) {
$(elm).css({
"background-image":"url('"+e.target.result+"')",
"transform": "rotate(90deg)"
});
}
Edit: Well, after a brief dive into the world of EXIF data, I think I might have a solution for you. I borrowed Ali's getOrientation() function, as @Nick suggested, and then I just corrected the orientation with CSS as follows:
function correctOrientation(element, orientation){
switch (orientation) {
case 2: $(element).css("transform", "scaleX(-1)");
break;
case 3: $(element).css("transform", "rotate(180deg)");
break;
case 4: $(element).css("transform", "rotate(180deg) scaleX(-1)");
break;
case 5: $(element).css("transform", "rotate(-90deg) scaleX(-1)");
break;
case 6: $(element).css("transform", "rotate(90deg)");
break;
case 7: $(element).css("transform", "rotate(90deg) scaleX(-1)");
break;
case 8: $(element).css("transform", "rotate(-90deg)");
break;
default: break;
}
}
fiddle
And if you need example files to test it, get them here.
Edit: Placing the uploaded image in an <img>
instead of the div's background-image:
https://jsfiddle.net/ynzvtLe2/2/
How to apply EXIF orientation
To be sure the image displays correctly regardless of browser and exif orientation, you need to have javascript that does the rotation and puts the image on a canvas. This protects it from "double-rotation" where the rotation is natively supported, e.g. safari.
I solved this problem using the JavaScript-Load-Image project from github, which makes it very easy; see my answer here: JS Client-Side Exif Orientation: Rotate and Mirror JPEG Images
How to apply EXIF orientation
To be sure the image displays correctly regardless of browser and exif orientation, you need to have javascript that does the rotation and puts the image on a canvas. This protects it from "double-rotation" where the rotation is natively supported, e.g. safari.
I solved this problem using the JavaScript-Load-Image project from github, which makes it very easy; see my answer here: JS Client-Side Exif Orientation: Rotate and Mirror JPEG Images
Related Topics
Navigator.Geolocation.Getcurrentposition Sometimes Works Sometimes Doesn'T
Trying to Fire the Onload Event on Script Tag
Const in JavaScript: When to Use It and Is It Necessary
Why Does Instanceof Return False for Some Literals
How to Get Element by Innertext
Jquery.Parsejson Throws "Invalid JSON" Error Due to Escaped Single Quote in JSON
Asynchronous for Cycle in JavaScript
Dealing with Float Precision in JavaScript
Are JavaScript Arrays Primitives? Strings? Objects
How to Get Node Datum on Mouseover in D3 V6
JavaScript Unit Test Tools for Tdd
What Are the Differences Between JSON and JavaScript Object
Issue in Returning Data Retrieved from Db Queries Called in the Loop
Getting Around X-Frame-Options Deny in a Chrome Extension
JavaScript Setinterval and 'This' Solution
How to Render an Array of Objects in React
Regex for JavaScript to Allow Only Alphanumeric
Why JavaScript Treats a Number as Octal If It Has a Leading Zero