《PHP實戰:php中照片旋轉 (orientation) 問題的正確處理》要點:
本文介紹了PHP實戰:php中照片旋轉 (orientation) 問題的正確處理,希望對您有用。如果有疑問,可以聯系我們。
PHP實例前言
PHP實例iPhone和一些數碼相機在拍照的時候往往會在圖片里面加入很多的照片信息(exif),比如拍照時間、光圈大小、曝光時間、GSP地理信息以及拍攝時相機傾斜狀態等等,這些信息往往會提供給某些系統來對圖片進行正確的顯示,但是我們在對處理圖片的時候通常會丟失掉那些圖片信息,這就會導致顯示出現問題,很典型的一個顯示錯誤就是對Iphone拍攝的照片進行剪裁之后發現圖片旋轉了90度,這個時候就需要對圖片進行相應的處理.
PHP實例背景
PHP實例博主是在一個小項目中遇到的這個問題,這個項目雖然小,但是涉及到的各種坑真的可以寫一篇比較長的技術文章了,這里先不描述,后面單獨發一篇關于這個項目的文章,把所涉及到的知識點以及坑點一一描述.
PHP實例這個小項目中遇到的問題之一就是,我需要使用html5的canvas把讀取到的圖片進行剪裁,然后渲染到畫布上.很簡單的一個需求,但是在Iphone上測試經常會看到剪裁完之后圖片自動旋轉了90度,安卓機上不存在這個問題.
PHP實例分析
PHP實例之前就遇到過這個問題,iPhone拍攝的照片復制到win7上打開圖片就是一個倒過來的,而在手機上看卻沒有問題,這就是因為exif信息在搞鬼,簡單點說exif就是保留了圖片的拍攝參數,顯示的時候程序會讀取圖片的exif信息,如果exif信息不存在,那么圖片就是按照最原始的形式顯示,如果有exif信息,程序就會按照exif來.
PHP實例這里博主遇到的情況是圖片在進行剪裁的時候導致exif信息丟失,本來程序讀取exif中圖片要求順時針旋轉90°,現在exif丟失,程序讀不到,默認圖片不用旋轉,那么我們看到的圖片就是倒著的,這里應該怎么解決呢?
PHP實例在這個項目中,由于讀取的圖片存在跨域問題,不能直接對本地的圖片進行裁剪,所以是先上傳到遠程服務器,生成一個遠程的地址,然后再用canvas讀取遠程地址,這樣就解決了跨域問題.
PHP實例現在擺在博主面前就有兩種解決方案了
PHP實例對這兩種方案進行對比,第一種方案看起來確實挺適合,直接在前端進行處理,這里會非常節省服務器資源,但是缺點也很明顯,canvas對圖片的渲染有一定的限制,當圖片過大的時候渲染就會失敗,而在這個項目中客戶要求最后生成的圖片一定要高清大圖,上傳的照片一般都有3~5M大小,這么大的圖片大多數時候canvas都無法處理.
PHP實例exif.js的原理其實比較簡單,就是把圖片轉換成base64字符串,對其中的信息進行解析,所以一旦要對大圖進行處理的時候就會出現問題,數據量太大,導致失敗.
PHP實例第一種方案不可行就只能選擇第二種方案了,項目后端使用php做中轉處理,前面說了需要生成一個遠程地址,php負責把接收到的圖片存儲在遠程服務器,然后返回一個地址給前端,這里只需要在存儲之前對圖片做處理就可以解決這個問題.
PHP實例解決
PHP實例首先給出完整代碼,然后對代碼進行解釋
PHP實例
include_once ("../weixin/jssdk.php");
$jssdk = new JSSDK("wx**************", "******************************");
$access_token = $jssdk->getAccessToken();
$media_id = $_POST['i'];
$savePathFile = '/upload/temps/'.date('YmdHis').rand(1000,9999).'.jpg';
$targetName = __DIR__.$savePathFile;
$str = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=".$access_token."&media_id=".$media_id;
$image = imagecreatefromstring(file_get_contents($str));
$exif = exif_read_data($str);
if(!empty($exif['Orientation'])) {
switch($exif['Orientation']) {
case 8:
$image = imagerotate($image,90,0);
break;
case 3:
$image = imagerotate($image,180,0);
break;
case 6:
$image = imagerotate($image,-90,0);
break;
}
}
imagejpeg($image,$targetName);
echo json_encode(array("code"=>0,'d'=>$exif['Orientation'],"path"=>$savePathFile));
PHP實例看起來確實比較簡單,主要還是調用了一些內部函數,處理起來就方便多了.
PHP實例這個項目使用了微信的上傳接口,所以php需要從微信的臨時服務器上把用戶上傳的圖片取回來,通過file_get_contents方法就能快速拿到,當然也可以用curl來做.接著使用imagecreatefromstring創建一個圖片的緩存,正常情況下如果不需要對圖片進行處理,那么接下來就可以直接存儲了,這里我們還需要對圖片進行一些操作.
PHP實例通過 exif_read_data 方法可以直接讀取到圖片的exif信息.
PHP實例注意:exif_read_data 這個方法是exif擴展里面的方法,如果不能執行,請檢查擴展是否安裝,是否開啟等.
PHP實例exif模塊里面還有很多有意思的方法,可以拿來做很多有用的東西,比如拿來批量采集并分析圖片,提取圖片信息等.
PHP實例
if(!empty($exif['Orientation'])) {
switch($exif['Orientation']) {
case 8:
$image = imagerotate($image,90,0);
break;
case 3:
$image = imagerotate($image,180,0);
break;
case 6:
$image = imagerotate($image,-90,0);
break;
}
}
PHP實例這一段就很容易看懂了,就是判斷圖片的旋轉狀態,對圖片進行旋轉處理imagerotate方法很好用,當然同類的還有好多函數,可以去了解下,如果你正在做圖片處理,這些函數應該會有很大的幫助.
PHP實例最后使用 imagejpeg 方法把處理過的圖片寫入到磁盤,然后返回一個包含遠程地址的json到前端.
PHP實例注意:我這里沒有做異常捕獲,正常情況下文件io操作都必須要做異常捕獲,這里的代碼只為了說明使用方法,所以省略了這一步.
PHP實例總結
PHP實例在這個小項目中,最為常見的問題就是在php函數的使用上,同一種效果可以使用多個函數進行處理,選擇一個簡潔高效的函數非常重要,在使用第三方擴展的時候務必確認擴展是否安裝,擴展依賴的插件是否安裝,是否已經開啟,是否有其他額外的附加條件等.
PHP實例前端方面需要知道所使用的js插件有那些附加功能,如果api文章不夠清晰可以直接打開插件源碼,通常情況下,一個出色的插件往往會在未壓縮的代碼里面寫明所有接口的使用方法,以及注意事項,使用條件等.
PHP實例此外,還需要對不常見的情況進行判定,當出現一些詭異bug的時候就應該考慮是否是因為當前所給的參數不符合規范,或者超出了規范允許的范圍,上面說道的圖片轉base64格式的大小限制就是一個很難被發現的問題,博主在調試的時候對生成的數據進行觀察才發現,當出現大圖的時候就會轉換失敗.
PHP實例好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流.
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/1784.html