Je crée une application Web simple dans mobile qui permet au visiteur de capturer une photo en utilisant l'élément html5 input [type = file]. Ensuite, je vais l'afficher sur le Web pour la prévisualisation, puis le visiteur peut choisir de télécharger la photo sur mon serveur à d'autres fins (par exemple: télécharger au format FB)
Je trouve un problème d'orientation de la photo lorsque je prends une photo à l'aide de mon iPhone et que je la tiens à la verticale. La photo est correctement orientée. Cependant, lorsque j'essaie de le dessiner dans la zone de dessin à l'aide de la méthode drawImage (), il est dessiné pivoté à 90 degrés.
J'ai essayé de prendre une photo dans 4 orientations, une seule d'entre elles peut dessiner une image correcte dans la toile, les autres sont pivotées ou même retournées.
Eh bien, je suis confus d’obtenir la bonne orientation pour résoudre ce problème ... Merci de votre aide ...
voici mon code, surtout une copie 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>
Vous devrez lire les données exif et vérifier si exif.Orientation est l’un des suivants:
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 réponse de Ben m'a bien orientée, mais pour autant que je sache, les rotations sont incorrectes (du moins elles l'ont été pour moi) et ne couvrent pas tous les cas possibles. La solution ci-dessous a fonctionné pour moi. Il est basé sur celui trouvé dans la bibliothèque JavaScript-Load-Image (que j'ai trouvée via this great SO question ). Note que je devais également traduire le contexte Canvas au centre car il provient du coin supérieur gauche lors de la rotation).
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;
}
};
ajoutez exif.js à votre projet, puis:
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);
});
Le bloc d’orientation (en utilisant translations et rotation) est copié à partir de https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image-orientation.js et ainsi de suite. Je considère que c'est bien prouvé. Cela a certainement fonctionné parfaitement pour moi, contrairement aux autres approches.
Si vous voulez juste la balise Orientation, utilisez exif.js :
EXIF.getData(file, function () {
alert(this.exifdata.Orientation);
});
Dans mes tests, l'appareil photo iOS ne renvoie que 1,3,6 ou 8.
Sur la base de vos réponses, j'ai créé une fonction permettant de faire pivoter automatiquement l'iPhone photo dans la bonne direction.
Il suffit de passer un input.files [0] et une largeur ou hauteur maximale optionnelle, il générera un blob utilisé pour la soumission du formulaire.
https://github.com/gonnavis/iphone_photo_rotation_adjust