Image Orientation
上次的笔记被吞了...有点服气
// 用于修复图片朝向,在手机端拍摄时,图像的朝向信息存储在EXIF中。这里需要传入base64,可以适用src.data提取。
const resetOrientation = (srcBase64, srcOrientation) => {
console.log(srcOrientation, '检测的');
return new Promise(resolve => {
var img = new Image();
img.onload = function() {
var width = img.width,
height = img.height,
canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
// set proper canvas dimensions before transform & export
if (4 < srcOrientation && srcOrientation < 9) {
canvas.width = height;
canvas.height = width;
} else {
canvas.width = width;
canvas.height = height;
}
// transform context before drawing image
switch (srcOrientation) {
case 2:
ctx.transform(-1, 0, 0, 1, width, 0);
break;
case 3:
ctx.transform(-1, 0, 0, -1, width, height);
break;
case 4:
ctx.transform(1, 0, 0, -1, 0, height);
break;
case 5:
ctx.transform(0, 1, 1, 0, 0, 0);
break;
case 6:
ctx.transform(0, 1, -1, 0, height, 0);
break;
case 7:
ctx.transform(0, -1, -1, 0, height, width);
break;
case 8:
ctx.transform(0, -1, 1, 0, 0, width);
break;
default:
break;
}
// draw image
ctx.drawImage(img, 0, 0);
// export base64
resolve(canvas.toDataURL('image/jpeg'));
};
img.src = srcBase64;
});
};
// 用于提取图像信息,适用于<input type="file" capture="camera"/>的场景
const getOrientation = file => {
return new Promise((resolve, reject) => {
var reader = new FileReader();
reader.onload = event => {
if (!event.target) {
return;
}
const file = event.target;
const view = new DataView(file.result);
if (view.getUint16(0, false) !== 0xffd8) {
// JPEG 文件头检测
return resolve(-2);
}
const length = view.byteLength;
let offset = 2;
while (offset < length) {
if (view.getUint16(offset + 2, false) <= 8) return resolve(-1);
let marker = view.getUint16(offset, false);
offset += 2;
if (marker === 0xffe1) {
// EXIF 头检测
if (view.getUint32((offset += 2), false) !== 0x45786966) {
return resolve(-1);
}
let little = view.getUint16((offset += 6), false) === 0x4949;
offset += view.getUint32(offset + 4, little);
let tags = view.getUint16(offset, little);
offset += 2;
for (let i = 0; i < tags; i++) {
if (view.getUint16(offset + i * 12, little) === 0x0112) {
return resolve(view.getUint16(offset + i * 12 + 8, little));
}
}
} else if ((marker & 0xff00) !== 0xff00) {
break;
} else {
offset += view.getUint16(offset, false);
}
}
return resolve(-1);
};
reader.readAsArrayBuffer(file);
});
};
// API友好的方法,传入File自动修正。
const fixOrientation = async file => {
return new Promise(async (resolve, reject) => {
const orientation = await getOrientation(file);
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
// console.log(reader.result);
resolve(resetOrientation(reader.result, orientation));
};
});
};
export default {
resetOrientation,
getOrientation,
fixOrientation
};
使用示例:
let b64 = await fixorientation.fixOrientation(file);