关于浏览器加载照片方向问题的研究

目录

  • 问题描述
  • 了解手机拍摄方向
  • 关于照片的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
复制代码
相关文章
相关标签/搜索