Skip to content

Instantly share code, notes, and snippets.

@laziel
Created May 16, 2019 10:12
Show Gist options
  • Save laziel/f699c6f4abff32b1b7503968deb61e3c to your computer and use it in GitHub Desktop.
Save laziel/f699c6f4abff32b1b7503968deb61e3c to your computer and use it in GitHub Desktop.
EXIF image orientation
/**
* Get image orientation from EXIF header
*
* Referenced:
* - https://gist.github.com/nezed/d536ccdace84c6f2ef13da47a8fd6bdb
* - https://gist.github.com/wonnage/9d2e73d9228f5a0b300d75babe2c3796
* - https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image-meta.js
*
* @param {String} imageUrl
* @return {Promise}
*/
async function getImageOrientation(imageUrl) {
try {
const arrayBuffer = await fetchAsArrayBuffer(imageUrl);
const dataView = new DataView(arrayBuffer.slice(0, 64 * 1024));
// Check for the JPEG marker
if (dataView.getUint16(0, false) !== 0xFFD8) {
throw new Error(`File is not a .jpeg`);
}
let offset = 2; // advance past the jpeg header
while (offset < dataView.byteLength) {
const marker = dataView.getUint16(offset, false);
offset += 2;
if (marker == 0xFFE1) { // APP1 marker
// ascii hex values of the string 'Exif'
if (dataView.getUint32(offset += 2, false) !== 0x45786966) {
throw new Error(`No EXIF start tag found`);
}
// Now determine the endianness of the tags
// by checking the 8 byte TIFF header
const littleEndian =
dataView.getUint16(offset += 6, false) === 0x4949;
offset += dataView.getUint32(offset + 4, littleEndian);
const tags = dataView.getUint16(offset, littleEndian);
offset += 2;
for (let i = 0; i < tags; i++) {
const pos = offset + i * 12;
const tag = dataView.getUint16(pos, littleEndian);
if (tag === 0x0112) { // orientaion tag found
return dataView.getUint16(pos + 8, littleEndian);
}
}
} else if ((marker & 0xFF00) !== 0xFF00) {
break;
} else {
offset += dataView.getUint16(offset, false);
}
}
throw new Error(`No orientation defined`);
} catch (e) {
console.debug(e);
return 0;
}
}
function fetchAsArrayBuffer(url) {
return new Promise(resolve => {
const xhr = new XMLHttpRequest();
xhr.open(`get`, url, true);
xhr.responseType = `arraybuffer`;
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
resolve(xhr.response);
}
};
xhr.onerror = () => {
throw new Error(`Cannot get the file`);
};
xhr.send();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment