javascript - perspectiva - dibujos para dibujar
¿Cómo dibujar una foto con la orientación correcta en el lienzo después de capturar la foto usando la entrada[type=''file''] en el navegador web móvil? (5)
De acuerdo con sus respuestas, creé una función para rotar automáticamente la foto de iphone en la dirección correcta.
Simplemente transfiera input.files [0] y un ancho o alto máximo opcional; generará un blob utilizado para enviar formularios.
https://github.com/gonnavis/iphone_photo_rotation_adjust
Estoy creando una aplicación web simple en dispositivos móviles que permite al visitante capturar fotos utilizando el elemento html5 input [type = file]. Luego lo mostraré en la web para obtener una vista previa, y luego el visitante puede optar por cargar la foto en mi servidor para otro fin (es decir: subir a FB)
Encuentro un problema en la orientación de la foto cuando tomo una foto usando mi iPhone y la sostengo verticalmente. La foto está en la orientación correcta en la etiqueta. Sin embargo, cuando intento dibujarlo en lienzo utilizando el método drawImage (), se dibuja 90 grados girados.
Intenté tomar fotos en 4 orientaciones, solo una de ellas puede dibujar una imagen correcta en el lienzo, otras pueden girar o incluso voltearse boca abajo.
Bueno, estoy confundido por la orientación correcta para solucionar este problema ... Gracias por ayudarme ...
aquí está mi código, en su mayoría copia de MDN
<div class="container">
<h1>Camera API</h1>
<section class="main-content">
<p>A demo of the Camera API, currently implemented in Firefox and Google Chrome on Android. Choose to take a picture with your device''s camera and a preview will be shown through createObjectURL or a FileReader object (choosing local files supported too).</p>
<p>
<form method="post" enctype="multipart/form-data" action="index.php">
<input type="file" id="take-picture" name="image" accept="image/*">
<input type="hidden" name="action" value="submit">
<input type="submit" >
</form>
</p>
<h2>Preview:</h2>
<div style="width:100%;max-width:320px;">
<img src="about:blank" alt="" id="show-picture" width="100%">
</div>
<p id="error"></p>
<canvas id="c" width="640" height="480"></canvas>
</section>
</div>
<script>
(function () {
var takePicture = document.querySelector("#take-picture"),
showPicture = document.querySelector("#show-picture");
if (takePicture && showPicture) {
// Set events
takePicture.onchange = function (event) {
showPicture.onload = function(){
var canvas = document.querySelector("#c");
var ctx = canvas.getContext("2d");
ctx.drawImage(showPicture,0,0,showPicture.width,showPicture.height);
}
// Get a reference to the taken picture or chosen file
var files = event.target.files,
file;
if (files && files.length > 0) {
file = files[0];
try {
// Get window.URL object
var URL = window.URL || window.webkitURL;
// Create ObjectURL
var imgURL = URL.createObjectURL(file);
// Set img src to ObjectURL
showPicture.src = imgURL;
// Revoke ObjectURL
URL.revokeObjectURL(imgURL);
}
catch (e) {
try {
// Fallback if createObjectURL is not supported
var fileReader = new FileReader();
fileReader.onload = function (event) {
showPicture.src = event.target.result;
};
fileReader.readAsDataURL(file);
}
catch (e) {
// Display error message
var error = document.querySelector("#error");
if (error) {
error.innerHTML = "Neither createObjectURL or FileReader are supported";
}
}
}
}
};
}
})();
</script>
Deberá leer los datos exif y comprobar si exif.Orientation es uno de los siguientes:
fileReader.onloadend = function() {
var exif = EXIF.readFromBinaryFile(new BinaryFile(this.result));
switch(exif.Orientation){
case 8:
ctx.rotate(90*Math.PI/180);
break;
case 3:
ctx.rotate(180*Math.PI/180);
break;
case 6:
ctx.rotate(-90*Math.PI/180);
break;
}
};
La gran respuesta de Ben me apuntó en la dirección correcta, pero por lo que puedo decir, las rotaciones reales son incorrectas (al menos lo fueron para mí) y no cubren todos los casos posibles. La solución a continuación funcionó para mí. Se basa en el que se encuentra en la biblioteca JavaScript-Load-Image (que encontré a través de esta gran pregunta SO ). Tenga en cuenta que también tuve que traducir el contexto Canvas al centro, ya que se origina desde la esquina superior izquierda al girar).
fileReader.onloadend = function() {
var exif = EXIF.readFromBinaryFile(new BinaryFile(this.result));
switch(exif.Orientation){
case 2:
// horizontal flip
ctx.translate(canvas.width, 0);
ctx.scale(-1, 1);
break;
case 3:
// 180° rotate left
ctx.translate(canvas.width, canvas.height);
ctx.rotate(Math.PI);
break;
case 4:
// vertical flip
ctx.translate(0, canvas.height);
ctx.scale(1, -1);
break;
case 5:
// vertical flip + 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.scale(1, -1);
break;
case 6:
// 90° rotate right
ctx.rotate(0.5 * Math.PI);
ctx.translate(0, -canvas.height);
break;
case 7:
// horizontal flip + 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.translate(canvas.width, -canvas.height);
ctx.scale(-1, 1);
break;
case 8:
// 90° rotate left
ctx.rotate(-0.5 * Math.PI);
ctx.translate(-canvas.width, 0);
break;
}
};
Si solo desea la etiqueta de orientación, usando exif.js :
EXIF.getData(file, function () {
alert(this.exifdata.Orientation);
});
En mis pruebas, la cámara iOS solo devuelve 1,3,6 u 8.
agrega exif.js a tu proyecto, luego:
EXIF.getData(file,function() {
var orientation = EXIF.getTag(this,"Orientation");
var can = document.createElement("canvas");
var ctx = can.getContext(''2d'');
var thisImage = new Image;
thisImage.onload = function() {
can.width = thisImage.width;
can.height = thisImage.height;
ctx.save();
var width = can.width; var styleWidth = can.style.width;
var height = can.height; var styleHeight = can.style.height;
if (orientation) {
if (orientation > 4) {
can.width = height; can.style.width = styleHeight;
can.height = width; can.style.height = styleWidth;
}
switch (orientation) {
case 2: ctx.translate(width, 0); ctx.scale(-1,1); break;
case 3: ctx.translate(width,height); ctx.rotate(Math.PI); break;
case 4: ctx.translate(0,height); ctx.scale(1,-1); break;
case 5: ctx.rotate(0.5 * Math.PI); ctx.scale(1,-1); break;
case 6: ctx.rotate(0.5 * Math.PI); ctx.translate(0,-height); break;
case 7: ctx.rotate(0.5 * Math.PI); ctx.translate(width,-height); ctx.scale(-1,1); break;
case 8: ctx.rotate(-0.5 * Math.PI); ctx.translate(-width,0); break;
}
}
ctx.drawImage(thisImage,0,0);
ctx.restore();
var dataURL = can.toDataURL();
// at this point you can save the image away to your back-end using ''dataURL''
}
// now trigger the onload function by setting the src to your HTML5 file object (called ''file'' here)
thisImage.src = URL.createObjectURL(file);
});
El bloque de orientación (que usa traducir y rotar) se copia de https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image-orientation.js, así que lo considero bien probado. Ciertamente funcionó perfectamente para mí, mientras que otros enfoques no lo hicieron.