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