PC端、移动端手机竖拍原图压缩上传顺时针旋转90°的解决方案

问题背景

最近在作的项目中,无论是移动端仍是后台系统都涉及到了手机照片压缩上传的问题,作完功能测试的时候发现图片回显的时候有些顺时针旋转了90°(竖拍照片,无论是ios仍是android都存在这问题),后来百度了一下才知道是跟图片的EXIF(可交换图像文件格式)中的Orientation(旋转参数)有关,那么问题就好处理了,咱们能够获取上传图片的Orientation值,根据不一样的值对图片作旋转处理。javascript

Orientation旋转参数的介绍与获取

可交换图像文件格式(Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的,能够记录数码照片的属性信息和拍摄数据。只要是数码相机(包括手机)拍出来的照片都带有这个参数,旋转的方向有四种状况。exif.js能够帮助咱们获取Orientation值(exif.js读取图像的元数据),后来我以import EXIF from './exif.js'方式引入发现文件中的EXIF方法并无对外暴露出来,所以稍稍改写了一下。这是新的exif.js(大家能够引用这个exif.js
图片描述
引用exif.js后,获取Orientation的核心代码,记得先var Orientation声明Orientationjava

EXIF.getData(img, function () {//获取照片Orientation,主要是修复竖拍照片顺时针旋转90°的问题(Orientation:6)
    EXIF.getAllTags(this);
    Orientation = EXIF.getTag(this, 'Orientation');
});

canvas 的 rotate() 方法对不一样的Orientation值旋转处理

ctx.rotate(angle);

方法介绍参照canvas rotate() android

旋转的中心点默认是canvas 的起点,即圆点位置(0, 0)。旋转的原理以下图:
图片描述ios

旋转以后,若是从圆点(0, 0)进行 drawImage(),那么画出来的位置就是在左图中的旋转90°后的位置,不在可视区域。旋转以后,坐标轴也跟着旋转了,想要显示在可视区域呢,须要将 ( 0, 0 ) 点往 y 轴的反方向移 y 个单位,此时的起始点则为 ( x, -y )(这种状况就是咱们使用手机竖拍图片上传后顺时针旋转90°的状况)。canvas

同理,能够得到旋转 -90°后的起始点为 ( -x, y ),旋转 180 度后的起始点为 ( -x, -y )。
核心代码以下测试

var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// 设置 canvas 的宽度和高度  
// canvas.width = w;
// canvas.height = h;
// ctx.drawImage(img, 0, 0, w, h);
if (Orientation == 3) {
    canvas.width = w;
    canvas.height = h;
    ctx.rotate(Math.PI);
    ctx.drawImage(img, 0, 0, -w, -h);
} else if (Orientation == 8) {
    canvas.width = h;
    canvas.height = w;
    ctx.rotate(Math.PI * 3 / 2);
    ctx.drawImage(img, 0, 0, -w, h);
} else if (Orientation == 6) {
    canvas.width = h;
    canvas.height = w;
    ctx.rotate(Math.PI / 2);
    ctx.drawImage(img, 0, 0, w, -h);
} else {
    canvas.width = w;
    canvas.height = h;
    ctx.drawImage(img, 0, 0, w, h);
}

图片压缩

随着手机拍照像素愈来愈高,照片大小愈来愈大。图片上传的压缩通常是:第一是对上传的图片宽高作大小限制。this

// 不要超出最大宽度  
var w = Math.min(_this.maxWidth, img.width);
// 高度按比例计算  
var h = img.height * (w / img.width);

第二是经过canvas.toDataURL(type, encoderOptions)方法设置压缩比,方法参考canvas.toDataUrl()spa

核心代码以下:code

setQuality: function (file) {
//alert(file.size+','+this.maxSize);
if (file.size < 1024 * 1024) {//0-1mb
    this.quality = 0.4;
}
if (file.size < 1024 * 1024 && file.size > 1024 * 1024 * 2) {//1-2mb
    this.quality = 0.3;
}
if (file.size < 1024 * 1024 * 3 && file.size > 1024 * 1024 * 2) {//2-3mb
    this.quality = 0.2;
}
if (file.size < 1024 * 1024 * 4 && file.size > 1024 * 1024 * 3) {//3-4mb
    this.quality = 0.15;
}
if (file.size < 1024 * 1024 * 5 && file.size > 1024 * 1024 * 4) {//4-5mb
    this.quality = 0.12;
}
if (file.size < 1024 * 1024 * 6 && file.size > 1024 * 1024 * 5) {//5-6mb
    this.quality = 0.11;
}
if (file.size < 1024 * 1024 * 7 && file.size > 1024 * 1024 * 6) {//6-7mb
    this.quality = 0.1;
}
if (file.size < 1024 * 1024 * 8 && file.size > 1024 * 1024 * 7) {//7-8mb
    this.quality = 0.08;
}
if (file.size < 1024 * 1024 * 10 && file.size > 1024 * 1024 * 8) {//8-10mb
    this.quality = 0.06;
}
}
var base64 = canvas.toDataURL('image/jpeg', _this.quality);
setTimeout(function () {
    _this.imgData[id].uploadFiles.push(base64);
    _this.imgData[id].filesLength = _this.imgData[id].uploadFiles.length;
}, 100);

小结

拍照上传功能可拆分为图片压缩以及对获取到数码图片Orientation值进行相应的处理。这是小白第一次写技术贴,可能我写得并非我想表达的,写得很差的地方请各位大神指点,有疑问的能够留言交流。orm

相关文章
相关标签/搜索