這個問題之因此不常發現,是由於咱們不多加載手機拍攝的圖片,更少加載圖片被人爲旋轉過的圖片。javascript
在咱們加載圖片的時候,瀏覽器有時候加載帶有旋轉信息的圖像文件的時候方向有旋轉的誤差,下面就是深度剖析一下這個問題和解決方案。css
一張圖帶你瞭解手機拍攝方向和在手機系統中呈現的樣式。 html
能夠看出來,java
若是是
垂直方向
拍出來的,會根據橫向縱向進行方向的調整。 若是是水平方向
拍出來的,由於沒法判斷手機的方向,因此拍的老是按照橫短豎長爲正方向。數組
Exif就是用來記錄拍攝圖像時的各類信息:瀏覽器
圖像信息(廠商,分辨率等)緩存
相機拍攝記錄(ISO,白平衡,飽和度,銳度等)編輯器
縮略圖(縮略圖寬度,高度等)工具
gps(拍攝時的經度,緯度,高度)等ui
將這些信息按照JPEG文件標準放在圖像文件二進制流的頭部。
那麼一個圖片如何加載的呢?上面的圖片使用了<div>+backgroundImage
和<img>+src
兩種方式渲染。
那麼咱們如今,點擊圖片右鍵將圖片進行旋轉。再看效果。
第一張照片順時針旋轉一次
第二張照片順時針旋轉兩次
第三張照片順時針旋轉一次
第四張照片逆時針旋轉一次
發現加載的方向依舊和沒有旋轉過是同樣的。
(爲了不是沒刷新啥的,我還修改了一下樣式)
- 使用電腦右鍵的旋轉或者手機直接旋轉
只是更改了圖像附加的EXIF的一些旋轉信息,自己圖片的元數據並無進行改變。
- 使用圖畫工具或者照片編輯器進行旋轉保存
會直接更改圖片的元數據,並將當前的EXIF旋轉信息置爲正方向。
瀏覽器會根據圖片自己的元數據進行渲染。會忽略EXIF裏面的旋轉信息Orientation,永遠展現的是Orientation爲1的方向。
只要咱們能夠獲取到圖片自己的信息,就能夠對其方向進行判斷了。 可是自己文件並無給咱們暴露那些接口獲取信息,使用原生方法比較複雜。 還好的是有一個插件exif.js
解決了這個問題。
<script src="exif.js"></script>
複製代碼
EXIF.getData(document.getElementById('img'), function(){
EXIF.getAllTags(this); //獲取全部信息,以對象形式返回
EXIF.getTag(this, 'Orientation') //獲取圖像的Orientation指定屬性值
EXIF.pretty(this); //獲取全部信息,以字符串形式返回
});
複製代碼
根據值的不一樣作不一樣的旋轉
參數 | 0行(未旋轉上) | 0列(未旋轉左) | 旋轉(方法不少) |
---|---|---|---|
1 |
上 | 左 | 0° |
2 | 上 | 右 | 水平翻轉 |
3 |
下 | 右 | 180° |
4 | 下 | 左 | 垂直翻轉 |
5 | 左 | 上 | 順時針90°+水平翻轉 |
6 |
右 | 上 | 順時針90° |
7 | 右 | 下 | 順時針90°+垂直翻轉 |
8 |
左 | 下 | 逆時針90° |
ArrayBuffer對象
,並建立一個DataView對象
進行操做。
ArrayBuffer對象
(照片只存儲jpg格式,不存儲png格式,因此不須要進行png文件的考慮)
**二進制文件經過文件頭識別文件類型
jpeg的頭文件標識是(0xFF, 0xD8),這是JPEG協議規定的
用16進制轉化爲10進製爲(255,216),若是是jpeg文件咱們就進行下一步解析。
ArrayBuffer 對象
用來表示通用的、固定長度的原始二進制數據緩衝區。根據不一樣的類型進行區分
Uint8Array
是無符號八進制數組
Int8Array
是有符號八進制數組
Int16Array
是有符號16進制數組。其中
ArrayBuffer對象
不能直接操做,原型鏈上也沒有暴露的方法,全部只能經過類型數組對象
或DataView對象
來操做,它們會將緩衝區中的數據表示爲特定的格式,並經過這些格式來讀寫緩衝區的內容。
DataView對象
用於呈現指定的緩存區數據,能夠認爲是一個二進制解釋器,下面的不一樣的方法,就是根據不一樣的位數去取數據進行解析。
var buffer = new ArrayBuffer(16);
var dv = new DataView(buffer);
dv.setInt16(0, 42);
dv.getInt16(0); //42
複製代碼