Orientación Exif del lado del cliente JS: rotar y reflejar imágenes JPEG

Resuelto flexponsive asked hace 10 años • 14 respuestas

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:

Resumen de orientaciones EXIF

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

flexponsive avatar Dec 16 '13 05:12 flexponsive
Aceptado

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 :)

flexponsive avatar Dec 15 '2013 22:12 flexponsive

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;
};
WunderBart avatar Nov 29 '2016 13:11 WunderBart

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:

  1. ctx.transform(1, 0, 0, 1, 0, 0);
  2. ctx.transform(-1, 0, 0, 1, width, 0);
  3. ctx.transform(-1, 0, 0, -1, width, height);
  4. ctx.transform(1, 0, 0, -1, 0, height);
  5. ctx.transform(0, 1, 1, 0, 0, 0);
  6. ctx.transform(0, 1, -1, 0, height, 0);
  7. ctx.transform(0, -1, -1, 0, height, width);
  8. ctx.transform(0, -1, 1, 0, 0, width);

Antes de dibujar la imagen en ctx.

Mederr avatar Jul 07 '2015 15:07 Mederr

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)

  1. 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.

  2. entonces básicamente lo que haremos es

    a - cargar la imagen usandowindow.loadImage()

    b - leer etiquetas exif usandowindow.EXIF.getData()

    c - convierte la imagen en lienzo y corrige la orientación de la imagen usandowindow.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;
}
Fareed Alnamrouti avatar Sep 08 '2016 06:09 Fareed Alnamrouti