js获取图片的EXIF,解决图片旋转问题

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

什么是EXIF

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

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

这里面就包含了图片的角度信息,就是说你用手机拍照时是不是倒着拍还是侧着拍,这些都是有记录的。
接下来就是教大家怎么获取图片内的exif信息
先给大家看看exif信息都存在哪里:(角度就在0x0112
exif信息的地址

// 这里的获取exif要将图片转ArrayBuffer对象,这里假设获取了图片的baes64
// 步骤一
// base64转ArrayBuffer对象
  function base64ToArrayBuffer(base64) {
    base64 = base64.replace(/^data:([^;]+);base64,/gmi, '');
    var binary = atob(base64);
    var len = binary.length;
    var buffer = new ArrayBuffer(len);
    var view = new Uint8Array(buffer);
    for (var i = 0; i < len; i++) {
      view[i] = binary.charCodeAt(i);
    }
    return buffer;
  }
// 步骤二,Unicode码转字符串
// ArrayBuffer对象 Unicode码转字符串
  function getStringFromCharCode(dataView, start, length) {
    var str = '';
    var i;
    for (i = start, length += start; i < length; i++) {
      str += fromCharCode(dataView.getUint8(i));
    }
    return str;
  }

// 步骤三,获取jpg图片的exif的角度(在ios体现最明显)
  function getOrientation(arrayBuffer) {
    var dataView = new DataView(arrayBuffer);
    var length = dataView.byteLength;
    var orientation;
    var exifIDCode;
    var tiffOffset;
    var firstIFDOffset;
    var littleEndian;
    var endianness;
    var app1Start;
    var ifdStart;
    var offset;
    var i;
    // Only handle JPEG image (start by 0xFFD8)
    if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
      offset = 2;
      while (offset < length) {
        if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
          app1Start = offset;
          break;
        }
        offset++;
      }
    }
    if (app1Start) {
      exifIDCode = app1Start + 4;
      tiffOffset = app1Start + 10;
      if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
        endianness = dataView.getUint16(tiffOffset);
        littleEndian = endianness === 0x4949;

        if (littleEndian || endianness === 0x4D4D /* bigEndian */) {
          if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
            firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);

            if (firstIFDOffset >= 0x00000008) {
              ifdStart = tiffOffset + firstIFDOffset;
            }
          }
        }
      }
    }
    if (ifdStart) {
      length = dataView.getUint16(ifdStart, littleEndian);

      for (i = 0; i < length; i++) {
        offset = ifdStart + i * 12 + 2;
        if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) {

          // 8 is the offset of the current tag's value
          offset += 8;

          // Get the original orientation value
          orientation = dataView.getUint16(offset, littleEndian);

          // Override the orientation with its default value for Safari (#120)
          if (IS_SAFARI_OR_UIWEBVIEW) {
            dataView.setUint16(offset, 1, littleEndian);
          }
          break;
        }
      }
    }
    return orientation;
  }

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

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

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

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

原文地址:https://www.cnblogs.com/suyuanli/p/8168407.html