Accessing JPEG EXIF Rotation Data In JavaScript On The Client Side
Answer :
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' />
values:
-2: not jpeg -1: not defined
For those using Typescript, you can use the following code:
export const getOrientation = (file: File, callback: Function) => { var reader = new FileReader(); reader.onload = (event: ProgressEvent) => { if (! event.target) { return; } const file = event.target as FileReader; const view = new DataView(file.result as ArrayBuffer); if (view.getUint16(0, false) != 0xFFD8) { return callback(-2); } const length = view.byteLength let offset = 2; while (offset < length) { if (view.getUint16(offset+2, false) <= 8) return callback(-1); let marker = view.getUint16(offset, false); offset += 2; if (marker == 0xFFE1) { if (view.getUint32(offset += 2, false) != 0x45786966) { return callback(-1); } let little = view.getUint16(offset += 6, false) == 0x4949; offset += view.getUint32(offset + 4, little); let tags = view.getUint16(offset, little); offset += 2; for (let 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); }
You can use the exif-js library in combination with the HTML5 File API: http://jsfiddle.net/xQnMd/1/.
$("input").change(function() { var file = this.files[0]; // file fr = new FileReader; // to read file contents fr.onloadend = function() { // get EXIF data var exif = EXIF.readFromBinaryFile(new BinaryFile(this.result)); // alert a value alert(exif.Make); }; fr.readAsBinaryString(file); // read the file });
Firefox 26 supports image-orientation: from-image
: images are displayed portrait or landscape, depending on EXIF data. (See sethfowler.org/blog/2013/09/13/new-in-firefox-26-css-image-orientation.)
There is also a bug to implement this in Chrome.
Beware that this property is only supported by Firefox and is likely to be deprecated.
Comments
Post a Comment