相信大家在做项目的时候会遇到在canvas里加入图片时,图片发生90°,180°的旋转。当时的你肯定时懵逼的,为毛。
其实这就是图片的EXIF搞的鬼。

什么是EXIF

简单来说,Exif 信息就是由数码相机在拍摄过程中采集一系列的信息,然后把信息放置在我们熟知的 JPEG/TIFF 文件的头部,也就是说 Exif信息是镶嵌在 JPEG/TIFF 图像文件格式内的一组拍摄参数,它就好像是傻瓜相机的日期打印功能一样,只不过 Exif信息所记录的资讯更为详尽和完备。Exif 所记录的元数据信息非常丰富,主要包含了以下几类信息:

  • 拍摄日期
  • 摄器材(机身、镜头、闪光灯等
  • 拍摄参数(快门速度、光圈F值、ISO速度、焦距、测光模式等
  • 图像处理参数(锐化、对比度、饱和度、白平衡等)
  • 图像描述及版权信息
  • GPS定位数据
  • 缩略图

这里面就包含了图片的角度信息,就是说你用手机拍照时是不是倒着拍还是侧着拍,这些都是有记录的。

接下来就是教大家怎么获取图片内的exif信息

先给大家看看exif信息都存在哪里:(角度就在0x0112)

  1. // 这里的获取exif要将图片转ArrayBuffer对象,这里假设获取了图片的baes64
  2. // 步骤一
  3. // base64转ArrayBuffer对象
  4. function base64ToArrayBuffer(base64) {
  5. base64 = base64.replace(/^data\:([^\;]+)\;base64,/gmi, '');
  6. var binary = atob(base64);
  7. var len = binary.length;
  8. var buffer = new ArrayBuffer(len);
  9. var view = new Uint8Array(buffer);
  10. for (var i = 0; i < len; i++) {
  11. view[i] = binary.charCodeAt(i);
  12. }
  13. return buffer;
  14. }
  15. // 步骤二,Unicode码转字符串
  16. // ArrayBuffer对象 Unicode码转字符串
  17. function getStringFromCharCode(dataView, start, length) {
  18. var str = '';
  19. var i;
  20. for (i = start, length += start; i < length; i++) {
  21. str += fromCharCode(dataView.getUint8(i));
  22. }
  23. return str;
  24. }
  25. // 步骤三,获取jpg图片的exif的角度(在ios体现最明显)
  26. function getOrientation(arrayBuffer) {
  27. var dataView = new DataView(arrayBuffer);
  28. var length = dataView.byteLength;
  29. var orientation;
  30. var exifIDCode;
  31. var tiffOffset;
  32. var firstIFDOffset;
  33. var littleEndian;
  34. var endianness;
  35. var app1Start;
  36. var ifdStart;
  37. var offset;
  38. var i;
  39. // Only handle JPEG image (start by 0xFFD8)
  40. if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
  41. offset = 2;
  42. while (offset < length) {
  43. if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
  44. app1Start = offset;
  45. break;
  46. }
  47. offset++;
  48. }
  49. }
  50. if (app1Start) {
  51. exifIDCode = app1Start + 4;
  52. tiffOffset = app1Start + 10;
  53. if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
  54. endianness = dataView.getUint16(tiffOffset);
  55. littleEndian = endianness === 0x4949;
  56. if (littleEndian || endianness === 0x4D4D /* bigEndian */) {
  57. if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
  58. firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
  59. if (firstIFDOffset >= 0x00000008) {
  60. ifdStart = tiffOffset + firstIFDOffset;
  61. }
  62. }
  63. }
  64. }
  65. }
  66. if (ifdStart) {
  67. length = dataView.getUint16(ifdStart, littleEndian);
  68. for (i = 0; i < length; i++) {
  69. offset = ifdStart + i * 12 + 2;
  70. if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) {
  71. // 8 is the offset of the current tag's value
  72. offset += 8;
  73. // Get the original orientation value
  74. orientation = dataView.getUint16(offset, littleEndian);
  75. // Override the orientation with its default value for Safari (#120)
  76. if (IS_SAFARI_OR_UIWEBVIEW) {
  77. dataView.setUint16(offset, 1, littleEndian);
  78. }
  79. break;
  80. }
  81. }
  82. }
  83. return orientation;
  84. }

方法getStringFromCharCode(arrayBuffer)返回的orientation就是图片的方向也就是旋转的值,再对应下面的表,对图片进行处理

orientation值 旋转角度
1
3 180°
6 顺时针90°
8 逆时针90°

大家可以先判断图片Exif的orientation值再根据上表对应的旋转值,在canvas上对图片进行反方向旋转消除影响

之后我会对canvas上如何旋转进行详细讲解。

js获取图片的EXIF,解决图片旋转问题的更多相关文章

  1. jquery图片延迟加载方案解决图片太多加载缓慢问题

    当在做一个图片展示站的时候,一个页面加载的图片过多会,如果服务器的带宽跟不上,明显会感觉到页面很卡,严重的浏览器也会崩溃,所以我推荐采用即看即所得的模式,当滚动到下一屏时才进行加载图片. 注意:即便如 ...

  2. cocos2d-x JS 获取当前系统时间(解决屏幕双击点击事件)

    记录一下,好开心,感觉今天自己又学到东西了,对于屏幕双击事件本来还毫无头绪的,今天得以解决总算没白费加班,其实原理很简单:就是在点击事件里做一个判断,这个判断就是需要获取当前系统的时间的毫秒差,第一次 ...

  3. js点击获取—通过JS获取图片的绝对对坐标位置

    一.通过JS获取鼠标点击时图片的相对坐标位置 源代码如下所示:  <!DOCTYPE html> <html lang="en"> <head> ...

  4. js点击获取—通过JS获取图片的相对坐标位置

    一.通过JS获取鼠标点击时图片的相对坐标位置 源代码如下所示: <!DOCTYPE html> <html lang="en"> <head> ...

  5. JS实现图片base64转blob对象,压缩图片,预览图片,图片旋转到正确角度

    base64转blob对象 /** 将base64转换为文件对象 * @param {String} base64 base64字符串 * */ var convertBase64ToBlob = f ...

  6. IOS: 使用imageIO获取和修改图片的exif信息

    使用imageIO获取和修改图片的exif信息 一幅图片除了包含我们能看见的像素信息,背后还包含了拍摄时间,光圈大小,曝光等信息.UIImage类将这些细节信息都隐藏了起来,只提供我们关心的图片尺寸, ...

  7. 使用C#进行图片转换格式,缩放,自动旋转,保留exif(转载)

    这几天心血来潮做了一个批量图片缩放,转换格式,并且可以根据exif的信息旋转图片,校正exif信息后保存的小程序.根据配置文件 指定需要的功能. 1 2 3 4 5 6 7 8 9 10 11 12 ...

  8. js手写图片查看器(图片的缩放、旋转、拖拽)

    在做一次代码编辑任务中,要查看图片器.在时间允许的条件下,放弃了已经封装好的图片jq插件,现在自己手写js实现图片的缩放.旋转.推拽功能! 具体代码如下: <!DOCTYPE html> ...

  9. js实现图片查看器(图片的缩放、旋转、拖拽)

    一.关于图片查看器. 目前网络上能找到的图片查看器很多,谁便一搜就能出来.如:jquery.iviewer.js.Viewer.js这两个js文件,其中功能也足够满足大部分开发需求.但是单纯的就想实现 ...

随机推荐

  1. eclipse环境下基于已构建struts2项目整合spring+hibernate

    本文是基于已构建的struts2项目基础上整合 spring+hibernate,若读者还不熟悉struts2项目,请先阅读 eclipse环境下基于tomcat-7.0.82构建struts2项目 ...

  2. easyUI整合富文本编辑器KindEditor详细教程(附源码)

    原因 在今年4月份的时候写过一篇关于easyui整合UEditor的文章Spring+SpringMVC+MyBatis+easyUI整合优化篇(六)easyUI与富文本编辑器UEditor整合,从那 ...

  3. JAVA提高十八:Vector&Stack深入分析

    前面我们已经接触过几种数据结构了,有数组.链表.Hash表.红黑树(二叉查询树),今天再来看另外一种数据结构:栈. 什么是栈呢,我们先看一个例子:栈就相当于一个很窄的木桶,我们往木桶里放东西,往外拿东 ...

  4. OC语言的面向对象—类和对象、方法

    1. 面向对象和面向过程思想 OC是面向对象的,C是面向过程的.面向对象和面向过程只是解决问题的两种不同思想 1. 面向对象和面向过程的区别 1) 以用电脑听歌为例子 a) 面向过程 ➢ 打开电脑 ➢ ...

  5. Server SQL2008对文件的基础操作(1)

    1.一个文件的基本框架为:文件名.文件地址.文件大小.文件最大的大小.文件的增量(Filegrowth). 2.文件有mdf.ndf.ldf 三种文件的区别. 3.文件组可以进行文件的管理 FileG ...

  6. unity中.meta提交错误操作导致空脚本

    工作时遇到了一个奇葩的问题,同事做的界面,再策划那里死活无法运行,其他同事的都没有问题.简单一查,是界面上挂了个空脚本,但是同事提交了对应的脚本,其他人那里脚本是正常.随后想到是否是.meta的问题. ...

  7. Libevent 事件管理和添加事件

    /**   我们先来看一下事件的创建*/struct event * event_new(struct event_base *base, evutil_socket_t fd, short even ...

  8. ##6.1 Neutron控制节点-- openstack pike

    ##6.1 Neutron控制节点 openstack pike 安装 目录汇总 http://www.cnblogs.com/elvi/p/7613861.html ##6.1 Neutron控制节 ...

  9. SQL Server学习之路(八):扩展SQL语句

    0.目录 1.问题描述 2.第一种方法 通过GROUP BY子句解决 3.第二种方法 通过聚合函数解决 4.第三种方法 在select...from...中的from后面嵌套一个表 5.第四种方法 在 ...

  10. Python的Web应用框架--Django

    一:简介 python的web框架有很多,个人查了一下,有Django.Pylons. Tornado.Bottle和Flask等,其中使用人数最多的是Django,而我学习Django也是因为ope ...