휴대폰에서 웹페이지의 입력 태그를 통해 사진을 촬영하고 업로드할 때, iPhone 및 특정 삼성 휴대폰을 포함한 일부 휴대폰에서는 사진이 90도 회전되는 문제가 발생할 수 있습니다. 이 문제는 휴대폰을 세로로 촬영할 때만 발생하며, 가로로 촬영한 사진은 정상적으로 표시됩니다. 따라서 휴대폰의 카메라 각도를 조정하여 사진을 회전시키면 이 문제를 해결할 수 있습니다.
모든 사진에 이 매개변수가 있는 것은 아니지만 휴대폰으로 촬영한 사진에는 이 매개변수가 있습니다.
회전 각도 | 매개변수 값 |
---|---|
0° | 1 |
90° 시계 방향 | 6 |
90° 시계 반대 방향 | 8 |
180° | 3 |
매개변수가 1이면 디스플레이가 정상이고, 이러한 가로 샷에서는 디스플레이가 정상입니다. 즉, Orientation = 1인 휴대폰에서는 세로 샷 매개변수가 6입니다.
Orientation 매개변수를 얻으려면 EXIF.js 라이브러리를 통해 조작할 수 있습니다. EXIF.js는 많은 기능을 가지고 있으며 압축되지 않은 상태에서는 크기도 매우 큽니다. 이는 모바일 페이지 로딩에 큰 영향을 미칩니다. 그리고 Orientation 정보만 가져오면 되므로 EXIF.js 라이브러리에서 일부 코드를 삭제하고 코드를 몇 KB로 줄였습니다.
exif.js가 Orientation을 가져옵니다:
EXIF.getData(file, function() { var Orientation = EXIF.getTag(this, 'Orientation');});
file은 입력 파일 형식으로 업로드된 파일입니다. 업로드된 파일은 fileReader.readAsDataURL(file)을 통해 미리 볼 수 있습니다. 이에 대해 확실하지 않은 경우 다음을 확인할 수 있습니다. HTML5 고급 시리즈: 파일 업로드 및 다운로드
Rotation에는 다음의rotate() 메서드를 사용해야 합니다. 캔버스.
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 < imgHeight && imgHeight > 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까지 선택할 수 있습니다.
위 내용을 바탕으로 예시 코드에는 단순화된 EXIF.js 라이브러리 주소가 포함되어 있습니다: file-demo
주요 핵심 코드는 다음과 같습니다:
<input type="file" id="files" ><img src="blank.gif" id="preview" alt="모바일 이미지 업로드, 회전, 압축 솔루션" > <script src="small-exif.js?1.1.11"></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>
위 내용은 모바일 이미지 업로드, 회전, 압축 솔루션의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!