这个问题之因此不常发现,是由于咱们不多加载手机拍摄的图片,更少加载图片被人为旋转过的图片。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
复制代码