모바일 웹 브라우저에서 입력 [type = 'file']을 사용하여 사진을 캡처 한 후 캔버스에서 올바른 방향으로 사진을 그리는 방법은 무엇입니까?
방문자가 html5 input [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>
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의 훌륭한 대답은 저를 올바른 방향으로 지적했지만 실제 회전이 잘못되었음을 알 수있는 한 (적어도 저를위한 것이 었습니다) 가능한 모든 경우를 다루지는 않습니다. 아래 솔루션이 저에게 효과적이었습니다. 이것은 JavaScript-Load-Image 라이브러리 에서 찾은 것을 기반으로합니다 ( 이 훌륭한 SO 질문을 통해 찾았습니다 ). 회전 할 때 왼쪽 상단 모서리에서 시작되므로 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;
}
};
프로젝트 에 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. It certainly worked perfectly for me, whereas other approaches didn't.
If you just want the Orientation tag, using exif.js:
EXIF.getData(file, function () {
alert(this.exifdata.Orientation);
});
In my tests, iOS camera only returns 1,3,6 or 8.
Based on your answers, I created a function to auto rotate iphone photo to right direction.
Just pass in an input.files[0] and an optional max width or height, it'll output a blob used for form submit.
https://github.com/gonnavis/iphone_photo_rotation_adjust
'UFO ET IT' 카테고리의 다른 글
std :: set과 std :: vector의 차이점은 무엇입니까? (0) | 2020.11.21 |
---|---|
R에서 데이터 프레임과 목록의 차이점은 무엇입니까? (0) | 2020.11.21 |
동일한 도메인의 CORS 오류? (0) | 2020.11.21 |
Java Annotation에서 문자열 배열을 설정하는 방법 (0) | 2020.11.21 |
gc () 명령을 사용하여 R에서 가비지 수집을 강제 실행 (0) | 2020.11.21 |