Как нарисовать фотографию с правильной ориентацией на холсте после захвата фотографии с помощью ввода[type= 'file'] в мобильном веб-браузере?
Я делаю простое веб-приложение в мобильном телефоне, которое позволяет посетителю захватывать фотографию с помощью элемента ввода html5[type=file]. Затем я покажу его в интернете для предварительного просмотра, а затем посетитель может выбрать, чтобы загрузить фотографию на мой сервер для других целей (т. е.: загрузить в FB)
Я нахожу проблему с ориентацией фотографии, когда я фотографирую с помощью своего iPhone и удерживаю вертикально.Фото в правильной ориентации в теге. Однако, когда я пытаюсь нарисовать его на холсте с помощью drawImage () метод, он рисуется на 90 градусов повернут.
Я попытался сфотографировать в 4 направлениях, только один из них может нарисовать правильное изображение на холсте, другие поворачиваются или даже переворачивается вверх ногами.
Ну, я смущен, чтобы получить правильную ориентацию, чтобы исправить эту проблему... Спасибо за помощь...
вот мой код, в основном копия из 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>
5 ответов:
вам нужно будет прочитать данные exif и проверить, если exif.Ориентация является одним из следующих:
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; } };
JavaScript-Load-Image library (который я нашел через это великий так вопрос). Обратите внимание, что мне также пришлось перевести контекст холста в центр, поскольку он исходит из верхнего левого угла, когда вращающийся.)
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; } };
добавить exif.js к вашему проекту, то:
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); });
блок ориентации (с помощью translate и rotate) копируется из https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image-orientation.js и поэтому я считаю это хорошо доказанным. Это, конечно, отлично работало для меня, в то время как другие подходы не сделали.
Если вы просто хотите тег ориентации, используя exif.js:
EXIF.getData(file, function () { alert(this.exifdata.Orientation); });
в моих тестах камера iOS возвращает только 1,3,6 или 8.
на основе ваших ответов, я создал функцию автоматического поворота iphone фото в правильном направлении.
Просто пройдите во вход.файлы[0] и необязательная максимальная ширина или высота, он будет выводить большой двоичный объект, используемый для отправки формы.
https://github.com/gonnavis/iphone_photo_rotation_adjust