IOS照片顛倒分析及移動/頁面端的處理策略和思路


 

前言:
  前幾天, 寫了一篇關於IOS手機上傳照片顛倒的技術分析文章: IOS照片顛倒分析及PHP服務端的處理.   

  不過其思路是從服務器來進行處理的, 這種做法相當普遍.
  今天來講述下, 如何從移動端/頁面端, 來解決這個問題, 側重於講講思路.
  

意義:
  但移動互聯網有它獨特的背景, 至今降耗電和省流量, 是很多移動端產品孜孜努力的方向.
  再者移動端手機的照片大小, 普遍較大, 因此直接往服務器傳, 往往會消耗很多流量, 在弱網環境下, 用戶等待的時間也長, 時常會失敗, 體驗非常不好. 因此移動端/頁面端(webapp)進行圖片的壓縮/縮放, 就非常有意義了.
  同時, 既然已經做了圖片的壓縮和大小縮放, 何不一起把圖片的旋轉也一起搞定.

可行性分析:
  由於IOS照片圖片顛倒, 是以為IOS的不作為, 不過其寫入了Orientation信息到EXIF信息頭中(jpeg和tiff文件).
  想要解決顛倒問題, 先要看, 能否在移動/頁面端, 獲取到EXIF信息.
  幸好, 我們擁有exif.js, 這個開源的js工具庫, 幫我們鋪好了路.
  這是資料鏈接: Exif.js 讀取圖像的元數據 http://code.ciaoca.com/javascript/exif-js/ .
  其對圖片EXIF信息頭的處理, 非常的簡潔:
  *) html的相關代碼:

<input type="file" accept="image/*" capture="camera" onchange="selectFileImage(this);">

  *) exif的使用代碼片段:

function selectFileImage(file) {
  var Orientation = null;
  //獲取照片方向角屬性,用戶旋轉控制
  EXIF.getData(file, function() {
    EXIF.getAllTags(this);
    Orientation = EXIF.getTag(this, 'Orientation');
  });
}

  這邊變量file為, input控件選擇具體圖片文件后得到的對象, Orientation即是旋轉信息.
  Orientation的取值和含義:

旋轉角度
參數
1
順時針90°
6
逆時針90°
8
180°
3

 

顛倒和縮放:
  在頁面端, 需要處理是的限制大小尺寸, 比如設置一個最大寬度值(限寬不限高), 同時又要解決圖片旋轉問題.
  其思路是借助canvas重繪來實現, 1). 先確定旋轉方向, 2). 圖片尺寸縮小調整 3). 確定canvas大小, 4). 繪制過程.

image = new Image();
image.onload = function() {
  var canvas = document.getElementById("myCanvas");
  var expectWidth, expectHeight;
  // *) 確定目標的寬和高
  if ( Orientation == 6 || Orientation == 8 ) {
    expectWidth = image.height;
    expectHeight = image.width;
  } else {
    expectWidth = image.width;
    expectHeight = image.height;
  }

  // *) 最大寬度限制及縮小變化
  var MAX_WIDTH = 480;
  if ( expectWidth > MAX_WIDTH ) {
    expectHeight = expectHeight * MAX_WIDTH / expectWidth;
    expectWidth = MAX_WIDTH;
  }

  if ( Orientation == 6 ) {
    // 順時針90°
    ctx.save();
    ctx.translate(expectWidth/2, expectHeight/2);
    ctx.rotate(90 * Math.PI / 180.0);
    ctx.drawImage(image, -expectHeight/2, -expectWidth/2, expectHeight, expectWidth);
  } else if ( Orientation == 8 ) {
    // 逆時針90°
    ctx.save();
    ctx.translate(expectWidth/2, expectHeight/2);
    ctx.rotate(270 * Math.PI / 180.0);
    ctx.drawImage(image, -expectHeight/2, -expectWidth/2, expectHeight, expectWidth);
    ctx.restore();
  } else if ( Orientation == 3 ) {
    // 180°
    ctx.save();
    ctx.translate(expectWidth/2, expectHeight/2);
    ctx.rotate(Math.PI);
    ctx.drawImage(image, -expectWidth/2, -expectHeight/2, expectWidth, expectHeight);
    ctx.restore();
  } else {
    ctx.drawImage(image, 0, 0, expectWidth, expectHeight);
  }

  // *) 獲取旋轉和壓縮后的圖片數據.
  var imagedata = canvas.toDataURL("image/png");

}

  整個流程相對, 還是比較簡單的.

  這邊講講canvas的drawImage, 如何去繪制旋轉圖片的思路的.
  1). 先把原點移至canvas的中點, translate
  2). 進行旋轉操作, rorate
  3). 進行繪制, 此時canvas的繪制區域坐標范圍為(-w/2, -h/2, w/2, h/2), 需要注意下.

 

圖片上傳:
  圖片壓縮和旋轉后, 圖片的數據上傳, 又是怎么實現的呢?
  一種思路, 就是上文提到的:

var imageData = canvas.toDataURL("image/png");

  其本質的工作, 就是把圖片的二進制數據, 轉換為了base64編碼后的數據, 這樣就可以通過普通的Ajax來上傳了, 也就實現了文件的異步上傳工作.

 

php和nginx文章的相關列表:
  • nginx服務配置---php服務接入 
  • nginx+tomcat集群配置(1)---根目錄設定和多后端分發配置 
  • nginx+tomcat集群配置(2)---靜態和動態資源的分離
  • nginx+tomcat集群配置(3)---獲取真實客戶端IP 
  • nginx+tomcat集群配置(4)--rewrite規則和多應用根目錄設定思路 

 

后記:
  應該說有幸吧, 通過這個簡單的例子, 追蹤定位, 到最后的問題解決, 其實學到了很多. 以前確實猶如井底之蛙, 以為很多問題, 只是一時疏忽而已, 在小的問題, 在背后也有大學問, 感謝每一天, 無論晴雨, 都是美好的一天.

 

個人站點&公眾號:

    個人微信公眾號: 小木的智慧屋

    個人游戲作品集站點(尚在建設中...): www.mmxfgame.com

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM