getdata - load image function javascript
Orientación Exif del lado del cliente JS: Girar y duplicar imágenes JPEG (9)
Las fotos de la cámara digital a menudo se guardan como JPEG con una etiqueta EXIF de "orientación". Para que se muestre correctamente, las imágenes deben rotarse / reflejarse según la orientación que se establezca, pero los navegadores ignoran esta información que representa la imagen. Incluso en aplicaciones web comerciales grandes, el soporte para la orientación EXIF puede ser irregular 1 . La misma fuente también proporciona un buen resumen de las 8 orientaciones diferentes que un JPEG puede tener:
Las imágenes de muestra están disponibles en 4 .
La pregunta es ¿cómo rotar / duplicar la imagen en el lado del cliente para que se muestre correctamente y se pueda seguir procesando 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, que requieren el uso de webworkers 3 .
Las herramientas de consola pueden reorientar correctamente las imágenes 5 . Un script PHP que resuelve el problema está disponible a las 6
Además de la respuesta de @fareed namrouti,
Esto debería usarse si la imagen debe examinarse desde un elemento de entrada de archivo
<input type="file" name="file" id="file-input"><br/>
image after transform: <br/>
<div id="container"></div>
<script>
document.getElementById(''file-input'').onchange = function (e) {
var image = e.target.files[0];
window.loadImage(image, function (img) {
if (img.type === "error") {
console.log("couldn''t load image:", img);
} else {
window.EXIF.getData(image, function () {
console.log("load image done!");
var orientation = window.EXIF.getTag(this, "Orientation");
var canvas = window.loadImage.scale(img,
{orientation: orientation || 0, canvas: true, maxWidth: 200});
document.getElementById("container").appendChild(canvas);
// or using jquery $("#container").append(canvas);
});
}
});
};
</script>
Estoy usando una solución mixta (php + css).
Los contenedores son necesarios para:
- contenedor
div.imgCont2
necesario para rotar; - contenedor
div.imgCont1
necesario para alejar elwidth:150%
; -
div.imgCont
Contenedor de contenido necesario para las barras de desplazamiento, cuando la imagen es zoomOut.
.
<?php
$image_url = ''your image url.jpg'';
$exif = @exif_read_data($image_url,0,true);
$orientation = @$exif[''IFD0''][''Orientation''];
?>
<style>
.imgCont{
width:100%;
overflow:auto;
}
.imgCont2[data-orientation="8"]{
transform:rotate(270deg);
margin:15% 0;
}
.imgCont2[data-orientation="6"]{
transform:rotate(90deg);
margin:15% 0;
}
.imgCont2[data-orientation="3"]{
transform:rotate(180deg);
}
img{
width:100%;
}
</style>
<div class="imgCont">
<div class="imgCont1">
<div class="imgCont2" data-orientation="<?php echo($orientation) ?>">
<img src="<?php echo($image_url) ?>">
</div>
</div>
</div>
He escrito un pequeño script php que rota la imagen. Asegúrese de guardar la imagen a favor de simplemente recalcularla en cada solicitud.
<?php
header("Content-type: image/jpeg");
$img = ''IMG URL'';
$exif = @exif_read_data($img,0,true);
$orientation = @$exif[''IFD0''][''Orientation''];
if($orientation == 7 || $orientation == 8) {
$degrees = 90;
} elseif($orientation == 5 || $orientation == 6) {
$degrees = 270;
} elseif($orientation == 3 || $orientation == 4) {
$degrees = 180;
} else {
$degrees = 0;
}
$rotate = imagerotate(imagecreatefromjpeg($img), $degrees, 0);
imagejpeg($rotate);
imagedestroy($rotate);
?>
Aclamaciones
La respuesta de WunderBart fue la mejor para mí. Tenga en cuenta que puede acelerar mucho si sus imágenes son a menudo el camino correcto, simplemente probando la orientación primero y eludiendo el resto del código si no se requiere rotación.
Poniendo toda la información de wunderbart juntos, algo como esto;
var handleTakePhoto = function () {
let fileInput: HTMLInputElement = <HTMLInputElement>document.getElementById(''photoInput'');
fileInput.addEventListener(''change'', (e: any) => handleInputUpdated(fileInput, e.target.files));
fileInput.click();
}
var handleInputUpdated = function (fileInput: HTMLInputElement, fileList) {
let file = null;
if (fileList.length > 0 && fileList[0].type.match(/^image///)) {
isLoading(true);
file = fileList[0];
getOrientation(file, function (orientation) {
if (orientation == 1) {
imageBinary(URL.createObjectURL(file));
isLoading(false);
}
else
{
resetOrientation(URL.createObjectURL(file), orientation, function (resetBase64Image) {
imageBinary(resetBase64Image);
isLoading(false);
});
}
});
}
fileInput.removeEventListener(''change'');
}
// from http://.com/a/32490603
export function getOrientation(file, callback) {
var reader = new FileReader();
reader.onload = function (event: any) {
var view = new DataView(event.target.result);
if (view.getUint16(0, false) != 0xFFD8) return callback(-2);
var length = view.byteLength,
offset = 2;
while (offset < length) {
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.slice(0, 64 * 1024));
};
export 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;
}
Para aquellos que tienen un archivo de un control de entrada, no saben cuál es su orientación, son un poco perezosos y no desean incluir una gran biblioteca a continuación, el código provisto por @WunderBart se fusionó con la respuesta a la que se vincula ( https://.com/a/32490603 ) que encuentra la orientación.
function getDataUrl(file, callback2) {
var callback = function (srcOrientation) {
var reader2 = new FileReader();
reader2.onload = function (e) {
var srcBase64 = e.target.result;
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
callback2(canvas.toDataURL());
};
img.src = srcBase64;
}
reader2.readAsDataURL(file);
}
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) {
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);
}
que fácilmente se puede llamar como tal
getDataUrl(input.files[0], function (imgBase64) {
vm.user.BioPhoto = imgBase64;
});
Si
width = img.width;
height = img.height;
var ctx = canvas.getContext(''2d'');
Entonces puede usar estas transformaciones para convertir la imagen en orientación 1
De 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
bien, además de la respuesta @ user3096626, creo que será más útil si alguien proporcionó el ejemplo del código, el siguiente ejemplo le mostrará cómo corregir la orientación de la imagen proviene de url (imágenes remotas):
Solución 1: usando javascript (recomendado)
Debido a que load-image library no extrae las etiquetas exif de las imágenes url solamente (file / blob), usaremos las exif-js y JavaScript-Load-Image javascript, 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, así que usamos 2.1
entonces, básicamente, lo que haremos es
a - carga la imagen usando
window.loadImage()
b - lee las etiquetas
window.EXIF.getData()
usandowindow.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
aqui 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 puede obtener la imagen como base64 del objeto canvas y colocarla en el atributo img src, por lo que con jQuery puede 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: utilizando html (hack 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 directamente dentro de una nueva pestaña sin ningún html (jajaja, no sé por qué), así que básicamente puedes mostrar tu imagen usando iframe poniendo el atributo ifrme src como URL de la imagen directamente:
<iframe src="/my-image.jpg"></iframe>
Solución 3: uso de CSS (solo Firefox y Safari en iOS)
existe un atributo css3 para corregir la orientación de la imagen, pero el problema solo está funcionando en firefox y safari / ios, pero vale la pena mencionarlo porque pronto estará disponible para todos los navegadores (información de soporte del caniuse de caniuse )
img {
image-orientation: from-image;
}
El proyecto github JavaScript-Load-Image proporciona una solución completa al problema de orientación EXIF, girando / duplicando imágenes correctamente para las 8 orientaciones exif. Vea la demostración en línea de la orientación javascript exif
La imagen se dibuja en un lienzo HTML5. Su representación correcta se implementa en js/load-image-orientation.js través de operaciones de lienzo.
Espero que esto le ahorre a alguien más algo de tiempo, y le enseñe a los motores de búsqueda sobre esta gema de código abierto :)
La transformación de contexto de Mederr funciona a la perfección. Si necesita extraer la orientación solo use esta función ; no necesita ninguna biblioteca EXIF de lectura. A continuación se muestra una función para volver a establecer la orientación en la imagen base64. Aquí hay un violín para eso . También preparé un violín con la demostración de extracción de 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;
};