HTML5 移动端“拍照”图片上传后角度问题
现象
在移动端页面中采用 file 调用原生的图片上传功能时候,发现上传后的图片角度会有奇怪的现象。如竖屏拍照的图片,上传后是倒立的。如果是需要做旋转预览的话,这个时候需要额外做一些工作。
原因
不多说,自己上网查。
解决方案。
来自于:https://github.com/Tencent/weui.js?files=1
辅助函数:
function dataURItoBuffer(dataURI){
var byteString = atob(dataURI.split(',')[1]);
var buffer = new ArrayBuffer(byteString.length);
var view = new Uint8Array(buffer);
for (var i = 0; i < byteString.length; i++) {
view[i] = byteString.charCodeAt(i);
}
return buffer;
}
function dataURItoBlob(dataURI) {
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
var buffer = dataURItoBuffer(dataURI);
return new Blob([buffer], {type: mimeString});
}
/**
* 获取图片的orientation
* ref to http://stackoverflow.com/questions/7584794/accessing-jpeg-exif-rotation-data-in-javascript-on-the-client-side
*/
function getOrientation(buffer){
var view = new DataView(buffer);
if (view.getUint16(0, false) != 0xFFD8) return -2;
var length = view.byteLength, offset = 2;
while (offset < length) {
var marker = view.getUint16(offset, false);
offset += 2;
if (marker == 0xFFE1) {
if (view.getUint32(offset += 2, false) != 0x45786966) return -1;
var little = view.getUint16(offset += 6, false) == 0x4949;
offset += view.getUint32(offset + 4, little);
var tags = view.getUint16(offset, little);
offset += 2;
for (var i = 0; i < tags; i++)
if (view.getUint16(offset + (i * 12), little) == 0x0112)
return view.getUint16(offset + (i * 12) + 8, little);
}
else if ((marker & 0xFF00) != 0xFF00) break;
else offset += view.getUint16(offset, false);
}
return -1;
}
/**
* 修正拍照时图片的方向
* ref to http://stackoverflow.com/questions/19463126/how-to-draw-photo-with-correct-orientation-in-canvas-after-capture-photo-by-usin
*/
function orientationHelper(canvas, ctx, orientation) {
const w = canvas.width, h = canvas.height;
if(orientation > 4){
canvas.width = h;
canvas.height = w;
}
switch (orientation) {
case 2:
ctx.translate(w, 0);
ctx.scale(-1, 1);
break;
case 3:
ctx.translate(w, h);
ctx.rotate(Math.PI);
break;
case 4:
ctx.translate(0, h);
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, -h);
break;
case 7:
ctx.rotate(0.5 * Math.PI);
ctx.translate(w, -h);
ctx.scale(-1, 1);
break;
case 8:
ctx.rotate(-0.5 * Math.PI);
ctx.translate(-w, 0);
break;
}
}
在操作 img2DataURL 类似的过程中,调用如下:
// 图片方向角
var orientation = null;
var src = null;
var fid = file.id;
var reader = new FileReader();
reader.readAsDataURL(file.attributes.h5File);
reader.onload = function (e) {
var image = new Image();
image.src = e.target.result;
orientation = getOrientation(dataURItoBuffer(e.target.result));
console.log('orientation',orientation)
image.onload = function () {
var canvas = document.createElement("canvas");
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
var ctx = canvas.getContext("2d");
if(orientation > 0){
orientationHelper(canvas, ctx, orientation);
}
ctx.drawImage(this, 0, 0, this.naturalWidth, this.naturalHeight);
src = canvas.toDataURL(file.attributes.h5File.type, .8);
var tmpl = '<li class="weui-uploader__file weui-uploader__file_status" data-fid="' + fid + '"style="background-image:url(#url#)"><div class="weui-uploader__file-content"></div></li>';
$uploaderFiles.append($(tmpl.replace('#url#', src)));
};
};
即可修正在预览中的图片角度问题。