[英]How to draw photo with correct orientation in canvas after capture photo by using input[type='file'] in mobile web browser?
I am making a simple web app in mobile which allow visitor to capture photo by using html5 input[type=file] element. 我在移动设备上制作一个简单的网络应用程序,允许访问者使用html5输入[type = file]元素捕获照片。 Then I will display it on the web for preview, and then visitor can choose to upload the photo to my server for other purpose(ie: upload to FB)
然后我会在网上显示它以供预览,然后访问者可以选择将照片上传到我的服务器用于其他目的(即:上传到FB)
I find a problem on the orientation of photo when I take photo using my iPhone and hold vertically.The photo is in a correct orientation in tag. 当我使用iPhone拍照并垂直握持时,我发现照片方向有问题。照片的标签方向正确。 However, when I try to draw it into canvas by using drawImage() method, it is drawn 90 degree rotated.
但是,当我尝试使用drawImage()方法将其绘制到画布中时,它会被旋转90度。
I have tried to take photo in 4 orientations, only one of them can draw a correct image in canvas, others are rotated or even flipped upside down. 我试图以4个方向拍摄照片,其中只有一个可以在画布上绘制正确的图像,其他图像可以旋转,甚至可以颠倒翻转。
Well, I am confused to get the correct orientation to fix this problem... Thanks for helping... 好吧,我很困惑,以获得正确的方向来解决这个问题...感谢您的帮助......
here is my code, mostly copy from MDN 这是我的代码,主要是来自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>
You'll need to read the exif data and check if exif.Orientation is one of the following: 您需要读取exif数据并检查exif.Orientation是否为以下之一:
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;
}
};
Ben's great answer pointed me in the right direction but as far as I can tell the actual rotations are incorrect (at least they were for me) and don't cover all possible cases. Ben的好回答指出了我正确的方向,但据我所知,实际轮换是不正确的(至少他们是我的),并没有涵盖所有可能的情况。 The solution below worked for me.
下面的解决方案对我有用。 It is based on the one found in the JavaScript-Load-Image library (which I found via this great SO question ).
它基于JavaScript-Load-Image库中的一个 (我通过这个伟大的SO问题找到了它 )。 Note that I also had to translate the Canvas context to the center as it originates from the top left corner when rotating).
请注意,我还必须将Canvas上下文转换为中心,因为它在旋转时从左上角开始)。
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;
}
};
add exif.js to your project, then: 将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);
});
The orientation block (using translate and rotate) is copied from https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image-orientation.js and so I consider it well proven. 方向块(使用翻译和旋转)是从https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image-orientation.js复制的,因此我认为它已得到充分证明。 It certainly worked perfectly for me, whereas other approaches didn't.
它对我来说当然很有效,而其他方法则没有。
Based on your answers, I created a function to auto rotate iphone photo to right direction. 根据你的答案,我创建了一个功能,将iphone照片自动旋转到正确的方向。
Just pass in an input.files[0] and an optional max width or height, it'll output a blob used for form submit. 只需传入一个input.files [0]和一个可选的最大宽度或高度,它就会输出一个用于表单提交的blob。
https://github.com/gonnavis/iphone_photo_rotation_adjust https://github.com/gonnavis/iphone_photo_rotation_adjust
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.