目錄
- 問(wèn)題描述
- 了解手機(jī)拍攝方向
- 關(guān)于照片的EXIF信息
- html如何加載圖片
- 遇到這種問(wèn)題我們?nèi)绾谓鉀Q键菱?
- 解決思路
- exif.js的使用
- 1. 先引用js文件
- 2. 使用方法獲得對(duì)應(yīng)img圖片的exif信息
- 3. 根據(jù)Orientation的值不為6,判斷需要進(jìn)行旋轉(zhuǎn)惨寿,使用css進(jìn)行相應(yīng)的
- 旋轉(zhuǎn)exif.js原理思路
- 一些專有名詞段审?
- ArrayBuffer巩梢?
- DataView叛本?
問(wèn)題描述
這個(gè)問(wèn)題之所以不常發(fā)現(xiàn),是因?yàn)槲覀兒苌偌虞d手機(jī)拍攝的圖片,更少加載圖片被人為旋轉(zhuǎn)過(guò)的圖片羞秤。
在我們加載圖片的時(shí)候呀舔,瀏覽器有時(shí)候加載帶有旋轉(zhuǎn)信息的圖像文件的時(shí)候方向有旋轉(zhuǎn)的偏差好乐,下面就是深度剖析一下這個(gè)問(wèn)題和解決方案止潘。
了解手機(jī)拍攝方向
一張圖帶你了解手機(jī)拍攝方向和在手機(jī)系統(tǒng)中呈現(xiàn)的樣式云挟。
這些照片拍出來(lái),不管呈現(xiàn)是不是正的哺哼,EXIF里面的旋轉(zhuǎn)信息都為1佩抹,表示正方向。
可以看出來(lái)取董,
如果是
垂直方向
拍出來(lái)的棍苹,會(huì)根據(jù)橫向縱向進(jìn)行方向的調(diào)整。
如果是水平方向
拍出來(lái)的茵汰,因?yàn)闊o(wú)法判斷手機(jī)的方向枢里,所以拍的總是按照橫短豎長(zhǎng)為正方向。
關(guān)于照片的EXIF信息
Exif就是用來(lái)記錄拍攝圖像時(shí)的各種信息:
圖像信息(廠商蹂午,分辨率等)
相機(jī)拍攝記錄(ISO栏豺,白平衡,飽和度画侣,銳度等)
縮略圖(縮略圖寬度冰悠,高度等)
gps(拍攝時(shí)的經(jīng)度堡妒,緯度配乱,高度)等
將這些信息按照J(rèn)PEG文件標(biāo)準(zhǔn)放在圖像文件二進(jìn)制流的頭部。
html如何加載圖片
那么一個(gè)圖片如何加載的呢皮迟?上面的圖片使用了<div>+backgroundImage
和<img>+src
兩種方式渲染搬泥。
可以看出來(lái),渲染的效果和手機(jī)剛拍攝的展示的效果是一樣的伏尼。
那么我們現(xiàn)在忿檩,點(diǎn)擊圖片右鍵將圖片進(jìn)行旋轉(zhuǎn)。再看效果爆阶。
第一張照片順時(shí)針旋轉(zhuǎn)一次
第二張照片順時(shí)針旋轉(zhuǎn)兩次
第三張照片順時(shí)針旋轉(zhuǎn)一次
-
第四張照片逆時(shí)針旋轉(zhuǎn)一次
旋轉(zhuǎn)之后的圖片方向.png
這個(gè)時(shí)候燥透,發(fā)現(xiàn)加載的方向依舊和沒(méi)有旋轉(zhuǎn)過(guò)是一樣的。
(為了避免是沒(méi)刷新啥的辨图,我還修改了一下樣式)
旋轉(zhuǎn)之后沒(méi)有任何變化.png
然后我們?cè)賹D片使用圖片工具打開(kāi)班套,進(jìn)行旋轉(zhuǎn)保存,查看效果故河。
使用照片編輯器編輯圖片.png
然后在瀏覽器展示看吱韭,發(fā)現(xiàn)瀏覽器加載的圖片進(jìn)行了旋轉(zhuǎn)
可以看出來(lái),在html進(jìn)行加載的時(shí)候鱼的,根據(jù)不同的渲染方式理盆,會(huì)有不一樣的展示痘煤。原因是什么呢?
- 使用電腦右鍵的旋轉(zhuǎn)或者手機(jī)直接旋轉(zhuǎn)
只是更改了圖像附加的EXIF的一些旋轉(zhuǎn)信息猿规,本身圖片的元數(shù)據(jù)并沒(méi)有進(jìn)行改變衷快。
- 使用圖畫(huà)工具或者照片編輯器進(jìn)行旋轉(zhuǎn)保存
會(huì)直接更改圖片的元數(shù)據(jù),并將當(dāng)前的EXIF旋轉(zhuǎn)信息置為正方向姨俩。
瀏覽器會(huì)根據(jù)圖片本身的元數(shù)據(jù)進(jìn)行渲染烦磁。會(huì)忽略EXIF里面的旋轉(zhuǎn)信息Orientation,永遠(yuǎn)展示的是Orientation為1的方向哼勇。
遇到這種問(wèn)題我們?nèi)绾谓鉀Q都伪?
解決思路
只要我們可以獲取到圖片本身的信息,就可以對(duì)其方向進(jìn)行判斷了积担。 但是本身文件并沒(méi)有給我們暴露那些接口獲取信息陨晶,使用原生方法比較復(fù)雜。 還好的是有一個(gè)插件exif.js
解決了這個(gè)問(wèn)題帝璧。
exif.js的使用
1. 先引用js文件
<script src="exif.js"></script>
2. 使用方法獲得對(duì)應(yīng)img圖片的exif信息
EXIF.getData(document.getElementById('img'), function(){
EXIF.getAllTags(this); //獲取所有信息先誉,以對(duì)象形式返回
EXIF.getTag(this, 'Orientation') //獲取圖像的Orientation指定屬性值
EXIF.pretty(this); //獲取所有信息,以字符串形式返回
});
3. 根據(jù)Orientation的值不為6的烁,判斷需要進(jìn)行旋轉(zhuǎn)褐耳,使用css進(jìn)行相應(yīng)的旋轉(zhuǎn)
根據(jù)值的不同做不同的旋轉(zhuǎn)
參數(shù) | 0行(未旋轉(zhuǎn)上) | 0列(未旋轉(zhuǎn)左) | 旋轉(zhuǎn)(方法很多) |
---|---|---|---|
1 |
上 | 左 | 0° |
2 | 上 | 右 | 水平翻轉(zhuǎn) |
3 |
下 | 右 | 180° |
4 | 下 | 左 | 垂直翻轉(zhuǎn) |
5 | 左 | 上 | 順時(shí)針90°+水平翻轉(zhuǎn) |
6 |
右 | 上 | 順時(shí)針90° |
7 | 右 | 下 | 順時(shí)針90°+垂直翻轉(zhuǎn) |
8 |
左 | 下 | 逆時(shí)針90° |
exif.js原理思路
-
首先定義了一套16進(jìn)制數(shù)據(jù)對(duì)應(yīng)的種類標(biāo)記,已經(jīng)種類對(duì)應(yīng)的值的含義
EXIF tags.png - 根據(jù)圖片的加載途徑不同渴庆,殊途同歸的轉(zhuǎn)化成
ArrayBuffer對(duì)象
铃芦,并創(chuàng)建一個(gè)DataView對(duì)象
進(jìn)行操作。
exif流程圖.png - 根據(jù)一套規(guī)則去解析
ArrayBuffer對(duì)象
- 先判斷其是不是jpeg圖片文件
(照片只存儲(chǔ)jpg格式襟雷,不存儲(chǔ)png格式刃滓,所以不需要進(jìn)行png文件的考慮)
二進(jìn)制文件通過(guò)文件頭識(shí)別文件類型
jpeg的頭文件標(biāo)識(shí)是(0xFF, 0xD8),這是JPEG協(xié)議規(guī)定的
用16進(jìn)制轉(zhuǎn)化為10進(jìn)制為(255,216)耸弄,如果是jpeg文件我們就進(jìn)行下一步解析咧虎。
- 然后找到對(duì)應(yīng)的Exif字母標(biāo)記,找到開(kāi)始讀取信息
-
匹配上面的鍵值對(duì)计呈,進(jìn)行配對(duì)輸出砰诵。
最終輸出exif對(duì)象.png
一些專有名詞?
ArrayBuffer捌显?
ArrayBuffer 對(duì)象
用來(lái)表示通用的茁彭、固定長(zhǎng)度的原始二進(jìn)制數(shù)據(jù)緩沖區(qū)。根據(jù)不同的類型進(jìn)行區(qū)分
Uint8Array
是無(wú)符號(hào)八進(jìn)制數(shù)組
Int8Array
是有符號(hào)八進(jìn)制數(shù)組
Int16Array
是有符號(hào)16進(jìn)制數(shù)組苇瓣。其中
ArrayBuffer對(duì)象
不能直接操作尉间,原型鏈上也沒(méi)有暴露的方法,所有只能通過(guò)類型數(shù)組對(duì)象
或DataView對(duì)象
來(lái)操作,它們會(huì)將緩沖區(qū)中的數(shù)據(jù)表示為特定的格式哲嘲,并通過(guò)這些格式來(lái)讀寫緩沖區(qū)的內(nèi)容贪薪。
DataView?
DataView對(duì)象
用于呈現(xiàn)指定的緩存區(qū)數(shù)據(jù)眠副,可以認(rèn)為是一個(gè)二進(jìn)制解釋器画切,下面的不同的方法,就是根據(jù)不同的位數(shù)去取數(shù)據(jù)進(jìn)行解析囱怕。
var buffer = new ArrayBuffer(16);
var dv = new DataView(buffer);
dv.setInt16(0, 42);
dv.getInt16(0); //42