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

相關文章
相關標籤/搜索