Orientación Exif del lado del cliente JS: rotar y reflejar imágenes JPEG
Las fotografías de las cámaras digitales suelen guardarse como JPEG con una etiqueta EXIF de "orientación". Para mostrarse correctamente, las imágenes deben rotarse/reflejarse según la orientación establecida, pero los navegadores ignoran esta información al representar la imagen. Incluso en aplicaciones web comerciales de gran tamaño, la compatibilidad con la orientación EXIF puede ser irregular 1 . La misma fuente también proporciona un buen resumen de las 8 orientaciones diferentes que puede tener un JPEG:
Las imágenes de muestra están disponibles en 4 .
La pregunta es ¿cómo rotar/reflejar la imagen en el lado del cliente para que se muestre correctamente y pueda procesarse aún más si es necesario?
Hay bibliotecas JS disponibles para analizar datos EXIF, incluido el atributo de orientación 2 . Flickr notó un posible problema de rendimiento al analizar imágenes grandes, lo que requiere el uso de trabajadores web 3 .
Las herramientas de la consola pueden reorientar correctamente las imágenes 5 . Un script PHP que resuelve el problema está disponible en 6
El proyecto github JavaScript-Load-Image proporciona una solución completa al problema de orientación EXIF, rotando/reflejando correctamente imágenes para las 8 orientaciones exif. Vea la demostración en línea de la orientación exif de JavaScript
La imagen se dibuja en un lienzo HTML5. Su representación correcta se implementa en js/load-image-orientation.js mediante operaciones de lienzo.
Espero que esto le ahorre algo de tiempo a alguien más y enseñe a los motores de búsqueda sobre esta joya de código abierto :)
La transformación de contexto de Mederr funciona perfectamente. Si necesita extraer la orientación, utilice únicamente esta función ; no necesita ninguna biblioteca de lectura EXIF. A continuación se muestra una función para restablecer la orientación en una imagen base64. Aquí tienes un violín para ello . También preparé una demostración de extracción de violín con orientación .
function resetOrientation(srcBase64, srcOrientation, callback) {
var img = new Image();
img.onload = function() {
var width = img.width,
height = img.height,
canvas = document.createElement('canvas'),
ctx = canvas.getContext("2d");
// set proper canvas dimensions before transform & export
if (4 < srcOrientation && srcOrientation < 9) {
canvas.width = height;
canvas.height = width;
} else {
canvas.width = width;
canvas.height = height;
}
// transform context before drawing image
switch (srcOrientation) {
case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
case 3: ctx.transform(-1, 0, 0, -1, width, height); break;
case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
case 6: ctx.transform(0, 1, -1, 0, height, 0); break;
case 7: ctx.transform(0, -1, -1, 0, height, width); break;
case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
default: break;
}
// draw image
ctx.drawImage(img, 0, 0);
// export base64
callback(canvas.toDataURL());
};
img.src = srcBase64;
};
Si
width = img.width;
height = img.height;
var ctx = canvas.getContext('2d');
Luego puedes usar estas transformaciones para convertir la imagen a la orientación 1.
Desde la orientación:
ctx.transform(1, 0, 0, 1, 0, 0);
ctx.transform(-1, 0, 0, 1, width, 0);
ctx.transform(-1, 0, 0, -1, width, height);
ctx.transform(1, 0, 0, -1, 0, height);
ctx.transform(0, 1, 1, 0, 0, 0);
ctx.transform(0, 1, -1, 0, height, 0);
ctx.transform(0, -1, -1, 0, height, width);
ctx.transform(0, -1, 1, 0, 0, width);
Antes de dibujar la imagen en ctx.
ok, además de la respuesta de @user3096626, creo que será más útil si alguien proporcionara un ejemplo de código. El siguiente ejemplo le mostrará cómo corregir la orientación de la imagen proveniente de la URL (imágenes remotas):
Solución 1: usar javascript (recomendado)
Debido a que la biblioteca de carga de imágenes no extrae etiquetas exif solo de imágenes de URL (archivo/blob), usaremos las bibliotecas javascript exif-js y de carga de imágenes , así que primero agregue estas bibliotecas a su página de la siguiente manera:
<script src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.1.0/exif.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image-scale.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image-orientation.min.js"></script>
Tenga en cuenta que la versión 2.2 de exif-js parece tener problemas, por lo que utilizamos la 2.1.
entonces básicamente lo que haremos es
a - cargar la imagen usando
window.loadImage()
b - leer etiquetas exif usando
window.EXIF.getData()
c - convierte la imagen en lienzo y corrige la orientación de la imagen usando
window.loadImage.scale()
d - coloque el lienzo en el documento
aquí tienes :)
window.loadImage("/your-image.jpg", function (img) {
if (img.type === "error") {
console.log("couldn't load image:", img);
} else {
window.EXIF.getData(img, function () {
var orientation = EXIF.getTag(this, "Orientation");
var canvas = window.loadImage.scale(img, {orientation: orientation || 0, canvas: true});
document.getElementById("container").appendChild(canvas);
// or using jquery $("#container").append(canvas);
});
}
});
Por supuesto, también puedes obtener la imagen como base64 desde el objeto lienzo y colocarla en el atributo img src, así que usando jQuery puedes hacerlo;)
$("#my-image").attr("src",canvas.toDataURL());
aquí está el código completo en: github: https://github.com/digital-flowers/loadimage-exif-example
Solución 2: usar html (truco de navegador)
Hay un truco muy rápido y fácil, la mayoría de los navegadores muestran la imagen en la orientación correcta si la imagen se abre dentro de una nueva pestaña directamente sin ningún html (LOL, no sé por qué), así que básicamente puedes mostrar tu imagen usando iframe. poniendo el atributo iframe src como la URL de la imagen directamente:
<iframe src="/my-image.jpg"></iframe>
Solución 3: usar css (solo Firefox y Safari en iOS)
Hay un atributo css3 para corregir la orientación de la imagen, pero vale la pena mencionar el problema de que solo funciona en Firefox y Safari/IOS porque pronto estará disponible para todos los navegadores (información de soporte del navegador de caniuse ) .
img {
image-orientation: from-image;
}