Images captured by iOS device cameras often appear rotated 90 degrees when displayed in web applications. This occurs due to orientation metdaata stored in the image's EXIF data, which requires manual correction for proper rendering. The issue primarily affects iOS and certain Samsung devices.
The solution involves reading EXIF orientation tags using the exif.js library and applying corrective transformations via the Canvas API.
Orientation Correction Function
function normalizeImageOrientation(context, sourceImg, orientationFlag, imgWidth, imgHeight) {
switch(orientationFlag) {
case 3:
context.rotate(Math.PI);
context.drawImage(sourceImg, -imgWidth, -imgHeight, imgWidth, imgHeight);
break;
case 6:
context.rotate(Math.PI/2);
context.drawImage(sourceImg, 0, -imgWidth, imgHeight, imgWidth);
break;
case 8:
context.rotate(-Math.PI/2);
context.drawImage(sourceImg, -imgHeight, 0, imgHeight, imgWidth);
break;
case 2:
context.scale(-1, 1);
context.drawImage(sourceImg, -imgWidth, 0, imgWidth, imgHeight);
break;
case 4:
context.scale(-1, 1);
context.rotate(Math.PI);
context.drawImage(sourceImg, -imgWidth, -imgHeight, imgWidth, imgHeight);
break;
case 5:
context.scale(-1, 1);
context.rotate(Math.PI/2);
context.drawImage(sourceImg, 0, -imgWidth, imgHeight, imgWidth);
break;
case 7:
context.scale(-1, 1);
context.rotate(-Math.PI/2);
context.drawImage(sourceImg, -imgHeight, 0, imgHeight, imgWidth);
break;
default:
context.drawImage(sourceImg, 0, 0, imgWidth, imgHeight);
}
}
Implemantation Example
document.querySelector('#fileInput').addEventListener('change', function(event) {
const imageFile = event.target.files[0];
if (!imageFile) return;
let orientation = 1;
EXIF.getData(imageFile, function() {
const metadata = EXIF.getAllTags(this);
orientation = metadata.Orientation || 1;
});
const reader = new FileReader();
reader.onload = function(e) {
const loadedImage = new Image();
loadedImage.onload = function() {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 150;
canvas.height = 150;
ctx.fillStyle = '#FFF';
ctx.fillRect(0, 0, 150, 150);
normalizeImageOrientation(ctx, loadedImage, orientation, 150, 150);
const processedData = canvas.toDataURL('image/jpeg', 0.8);
const previewElement = document.getElementById('imagePreview');
previewElement.src = processedData;
previewElement.style.display = 'block';
};
loadedImage.src = e.target.result;
};
reader.readAsDataURL(imageFile);
});