이 글에서는 모바일 기기에 업로드된 이미지를 회전하고 압축할 때 발생하는 문제에 대한 해결책을 제시합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
머리말
휴대폰에서 웹페이지의 입력태그를 통해 사진을 촬영하고 업로드할 경우, 아이폰 및 개별 삼성모바일을 포함한 일부 휴대폰에서는 사진이 90도 회전되는 문제가 발생할 수 있습니다. 전화기. 이 문제는 휴대폰을 세로로 촬영할 때만 발생하며, 가로로 촬영한 사진은 정상적으로 표시됩니다. 따라서 휴대폰의 카메라 각도를 조정하여 사진을 회전시키면 이 문제를 해결할 수 있습니다.
Orientation
이 매개변수는 모든 사진에서 사용할 수 없지만 휴대폰으로 촬영한 사진에는 이 매개변수가 있습니다.
회전 각도 | 매개변수 값 |
---|---|
0° | 1 |
90° 시계 방향 | 6 |
90° 시계 반대 방향 | 8 |
180° | 3 |
매개변수가 1이면 디스플레이가 정상이고, 이러한 가로 샷에서는 디스플레이가 정상입니다. 즉, Orientation = 1인 휴대폰에서는 세로 샷 매개변수가 6입니다.
Orientation 매개변수를 얻으려면 EXIF.js 라이브러리를 통해 조작할 수 있습니다. EXIF.js는 기능이 많고 크기가 크므로 압축하지 않은 상태에서는 30k로 모바일 페이지 로딩에 큰 영향을 미칩니다. 그리고 Orientation 정보만 가져오면 되므로 EXIF.js 라이브러리에서 일부 코드를 삭제하고 코드를 몇 KB로 줄였습니다.
exif.js가 오리엔테이션을 가져옵니다:
EXIF.getData(file, function() { var Orientation = EXIF.getTag(this, 'Orientation'); });
file은 입력 파일 형식으로 업로드된 파일입니다. 업로드된 파일은 fileReader.readAsDataURL(file)을 통해 미리 볼 수 있습니다. 이에 대해 확실하지 않은 경우 다음을 확인할 수 있습니다. HTML5 고급 시리즈: 파일 업로드 및 다운로드
Rotation
회전에는 캔버스 회전이 필요합니다. ( ) 방법.
ctx.rotate(angle);
rotate 메소드의 매개변수는 회전 호입니다. 각도는 라디안으로 변환되어야 합니다. 도 * Math.PI / 180
회전의 중심점은 기본적으로 캔버스의 시작점, 즉 (0, 0)에 있습니다. 회전의 원리는 다음과 같습니다.
회로도를 회전
한 후 (0, 0) 지점에서 drawImage()를 수행하면 그려진 위치는 왼쪽 그림에서 90도 회전한 후의 위치가 되며 보이는 영역은 아닙니다. 회전 후 좌표축도 회전하여 가시 영역에 표시하려면 이때 y축의 반대 방향으로 (0, 0) 지점을 이동해야 합니다. (0, -y )입니다.
마찬가지로 -90도 회전한 후의 시작점은 (-x, 0)이고, 180도 회전한 후의 시작점은 (-x, -y)입니다.
압축
휴대폰으로 찍은 사진은 용량이 너무 크고, base64로 인코딩한 사진은 원본 사진보다 크기가 커지므로 업로드 시 압축이 꼭 필요합니다. 오늘날의 휴대폰은 매우 높은 픽셀을 가지고 있으며, 촬영된 사진의 너비와 높이는 수천 픽셀에 달하므로 캔버스를 사용하여 사진을 렌더링하는 것은 상대적으로 느립니다.
그래서 첫 번째 단계는 업로드된 사진의 너비와 높이를 제한하고 너비나 높이가 특정 범위를 초과하는지 확인한 다음 너비와 높이를 동일하게 압축하는 것입니다.
var ratio = width / height;if(imgWidth > imgHeight && imgWidth > xx){ imgWidth = xx; imgHeight = Math.ceil(xx / ratio); }else if(imgWidth yy){ imgWidth = Math.ceil(yy * ratio); imgHeight = yy; }
두 번째 단계는 canvas.toDataURL() 메서드를 통해 사진 품질을 압축하는 것입니다.
canvas.toDataURL("image/jpeg", 1);
toDataURL() 메서드는 이미지 표시가 포함된 데이터 URI를 반환합니다. 두 개의 매개변수를 사용하세요. 첫 번째 매개변수는 이미지 형식이고 기본값은 image/png입니다. 두 번째 매개변수는 압축 품질입니다. 지정된 이미지 형식이 image/jpeg 또는 image/webp인 경우 이미지 품질을 0에서 1까지 선택할 수 있습니다.
Summary
위 내용을 바탕으로 예시 코드에는 간소화된 EXIF.js 라이브러리 주소가 포함되어 있습니다: file-demo
주요 핵심 코드는 다음과 같습니다.
<input><img alt="모바일 이미지 업로드 회전 및 압축 문제 해결" > <script></script> <script> var ipt = document.getElementById('files'), img = document.getElementById('preview'), Orientation = null; ipt.onchange = function () { var file = ipt.files[0], reader = new FileReader(), image = new Image(); if(file){ EXIF.getData(file, function() { Orientation = EXIF.getTag(this, 'Orientation'); }); reader.onload = function (ev) { image.src = ev.target.result; image.onload = function () { var imgWidth = this.width, imgHeight = this.height; // 控制上传图片的宽高 if(imgWidth > imgHeight && imgWidth > 750){ imgWidth = 750; imgHeight = Math.ceil(750 * this.height / this.width); }else if(imgWidth < imgHeight && imgHeight > 1334){ imgWidth = Math.ceil(1334 * this.width / this.height); imgHeight = 1334; } var canvas = document.createElement("canvas"), ctx = canvas.getContext('2d'); canvas.width = imgWidth; canvas.height = imgHeight; if(Orientation && Orientation != 1){ switch(Orientation){ case 6: // 旋转90度 canvas.width = imgHeight; canvas.height = imgWidth; ctx.rotate(Math.PI / 2); // (0,-imgHeight) 从모바일 이미지 업로드 회전 및 압축 문제 해결那里获得的起始点 ctx.drawImage(this, 0, -imgHeight, imgWidth, imgHeight); break; case 3: // 旋转180度 ctx.rotate(Math.PI); ctx.drawImage(this, -imgWidth, -imgHeight, imgWidth, imgHeight); break; case 8: // 旋转-90度 canvas.width = imgHeight; canvas.height = imgWidth; ctx.rotate(3 * Math.PI / 2); ctx.drawImage(this, -imgWidth, 0, imgWidth, imgHeight); break; } }else{ ctx.drawImage(this, 0, 0, imgWidth, imgHeight); } img.src = canvas.toDataURL("image/jpeg", 0.8); } } reader.readAsDataURL(file); } }</script>
요약: 위 내용은 전체 내용입니다. 이 글이 모든 분들의 공부에 도움이 되었으면 좋겠습니다. 더 많은 관련 튜토리얼을 보려면 JavaScript 비디오 튜토리얼, jQuery 비디오 튜토리얼, bootstrap 튜토리얼을 방문하세요!
위 내용은 모바일 이미지 업로드 회전 및 압축 문제 해결의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!