關於瀏覽器加載照片方向問題的研究

目錄

  • 問題描述
  • 瞭解手機拍攝方向
  • 關於照片的EXIF信息
  • html如何加載圖片
  • 遇到這種問題咱們如何解決?
    • 解決思路
    • exif.js的使用
      • 1. 先引用js文件
      • 2. 使用方法得到對應img圖片的exif信息
      • 3. 根據Orientation的值不爲6,判斷須要進行旋轉,使用css進行相應的
    • 旋轉exif.js原理思路
    • 一些專有名詞?
      • ArrayBuffer?
      • DataView?

問題描述

這個問題之因此不常發現,是由於咱們不多加載手機拍攝的圖片,更少加載圖片被人爲旋轉過的圖片。javascript

在咱們加載圖片的時候,瀏覽器有時候加載帶有旋轉信息的圖像文件的時候方向有旋轉的誤差,下面就是深度剖析一下這個問題和解決方案。css

瞭解手機拍攝方向

一張圖帶你瞭解手機拍攝方向和在手機系統中呈現的樣式。 html

手機拍攝方向.png
這些照片拍出來,無論呈現是否是正的,EXIF裏面的旋轉信息都爲1,表示正方向。

能夠看出來,java

若是是垂直方向拍出來的,會根據橫向縱向進行方向的調整。 若是是水平方向拍出來的,由於沒法判斷手機的方向,因此拍的老是按照橫短豎長爲正方向。數組

關於照片的EXIF信息

Exif就是用來記錄拍攝圖像時的各類信息:瀏覽器

  • 圖像信息(廠商,分辨率等)緩存

  • 相機拍攝記錄(ISO,白平衡,飽和度,銳度等)編輯器

  • 縮略圖(縮略圖寬度,高度等)工具

  • gps(拍攝時的經度,緯度,高度)等ui

將這些信息按照JPEG文件標準放在圖像文件二進制流的頭部。

瀏覽器如何加載圖片

那麼一個圖片如何加載的呢?上面的圖片使用了<div>+backgroundImage<img>+src兩種方式渲染。

瀏覽器正常加載圖片.png
能夠看出來,渲染的效果和手機剛拍攝的展現的效果是同樣的。

那麼咱們如今,點擊圖片右鍵將圖片進行旋轉。再看效果。

向右旋轉.png

  • 第一張照片順時針旋轉一次

  • 第二張照片順時針旋轉兩次

  • 第三張照片順時針旋轉一次

  • 第四張照片逆時針旋轉一次

    旋轉以後的圖片方向.png
    這個時候,發現加載的方向依舊和沒有旋轉過是同樣的。 (爲了不是沒刷新啥的,我還修改了一下樣式)
    旋轉以後沒有任何變化.png
    而後咱們再將圖片使用圖片工具打開,進行旋轉保存,查看效果。
    使用照片編輯器編輯圖片.png


使用畫板編輯圖片.png
而後在瀏覽器展現看,發現瀏覽器加載的圖片進行了旋轉
旋轉以後沒有任何變化.png
能夠看出來,在html進行加載的時候,根據不一樣的渲染方式,會有不同的展現。緣由是什麼呢?

  • 使用電腦右鍵的旋轉或者手機直接旋轉

只是更改了圖像附加的EXIF的一些旋轉信息,自己圖片的元數據並無進行改變。

  • 使用圖畫工具或者照片編輯器進行旋轉保存

會直接更改圖片的元數據,並將當前的EXIF旋轉信息置爲正方向。

瀏覽器會根據圖片自己的元數據進行渲染。會忽略EXIF裏面的旋轉信息Orientation,永遠展現的是Orientation爲1的方向。

遇到這種問題咱們如何解決?

解決思路

只要咱們能夠獲取到圖片自己的信息,就能夠對其方向進行判斷了。 可是自己文件並無給咱們暴露那些接口獲取信息,使用原生方法比較複雜。 還好的是有一個插件exif.js 解決了這個問題。

exif.js插件API

exif.js的使用

1. 先引用js文件

<script src="exif.js"></script>
複製代碼

2. 使用方法得到對應img圖片的exif信息

EXIF.getData(document.getElementById('img'), function(){
  EXIF.getAllTags(this); //獲取全部信息,以對象形式返回
  EXIF.getTag(this, 'Orientation')	//獲取圖像的Orientation指定屬性值
  EXIF.pretty(this); //獲取全部信息,以字符串形式返回
});
複製代碼

3. 根據Orientation的值不爲6,判斷須要進行旋轉,使用css進行相應的旋轉

根據值的不一樣作不一樣的旋轉

可供參考的exif-orientation說明

exif-orientation說明.png

參數 0行(未旋轉上) 0列(未旋轉左) 旋轉(方法不少)
1
2 水平翻轉
3 180°
4 垂直翻轉
5 順時針90°+水平翻轉
6 順時針90°
7 順時針90°+垂直翻轉
8 逆時針90°

exif.js原理思路

  1. 首先定義了一套16進制數據對應的種類標記,已經種類對應的值的含義
    EXIF tags.png
  2. 根據圖片的加載途徑不一樣,異曲同工的轉化成ArrayBuffer對象,並建立一個DataView對象進行操做。
    exif流程圖.png
  3. 根據一套規則去解析ArrayBuffer對象
  • 先判斷其是否是jpeg圖片文件**(照片只存儲jpg格式,不存儲png格式,因此不須要進行png文件的考慮)**

二進制文件經過文件頭識別文件類型

jpeg的頭文件標識是(0xFF, 0xD8),這是JPEG協議規定的

用16進制轉化爲10進製爲(255,216),若是是jpeg文件咱們就進行下一步解析。

二進制文件類型.png

  • 而後找到對應的Exif字母標記,找到開始讀取信息
  1. 匹配上面的鍵值對,進行配對輸出。
    最終輸出exif對象.png

一些專有名詞?

ArrayBuffer?

ArrayBuffer MDN

arrayBuffer.png

ArrayBuffer 對象 用來表示通用的、固定長度的原始二進制數據緩衝區。

根據不一樣的類型進行區分

  • Uint8Array是無符號八進制數組

  • Int8Array是有符號八進制數組

  • Int16Array是有符號16進制數組。

其中ArrayBuffer對象不能直接操做,原型鏈上也沒有暴露的方法,全部只能經過類型數組對象DataView對象來操做,它們會將緩衝區中的數據表示爲特定的格式,並經過這些格式來讀寫緩衝區的內容。

DataView?

DataView MDN

dataView.png

DataView對象用於呈現指定的緩存區數據,能夠認爲是一個二進制解釋器,下面的不一樣的方法,就是根據不一樣的位數去取數據進行解析。

var buffer = new ArrayBuffer(16);
var dv = new DataView(buffer);

dv.setInt16(0, 42);
dv.getInt16(0); //42
複製代碼
相關文章
相關標籤/搜索