使用Exif-js获取图片拍摄方向

使用Exif-js获取图片拍摄方向

1. EXIF介绍

EXIF信息,是可交换图像文件的缩写,是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。EXIF可以附加于JPEG、TIFF、RIFF等文件之中,为其增加有关数码相机拍摄信息的内容和索引图或图像处理软件的版本信息。(来自百度百科)

2. 拍摄方向(Orientation字段)

Orientation字段取值及其含义

Value0th Row0th Column
1topleft side
2topright side
3bottomright side
4bottomleft side
5left sidetop
6right sidetop
7right sidebottom
8left sidebottom

对应的显示效果

3. 代码实现

基于exif-js库实现,首先通过请求获取图片资源的blob格式,然后调用EXIF库的getData接口解析,最后返回 Orientation 字段即可。

import EXIF from 'exif-js';

function doTest(
  image: HTMLImageElement,
  callback: (res: { Orientation: number }, msg: string) => void
) {
  try {
    (<any>EXIF).enableXmp();
    EXIF.getData(<any>image, function () {
      callback(EXIF.getAllTags(this), 'success');
    });
  } catch (error) {
    callback({ Orientation: -1 }, 'exif exception');
  }
}

function getBlob(imgSrc: string, timeout: number, callback: (url: string) => void) {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', imgSrc, true);
  xhr.timeout = timeout * 1000;
  xhr.responseType = 'blob';

  xhr.onload = function (e) {
    if (xhr.readyState === 4) {
      if (xhr.status === 200) {
        const blob = this.response;
        callback(window.URL.createObjectURL(blob));
      } else {
        callback('');
      }
    }
  };

  xhr.onerror = function (e) {
    callback('');
  };

  xhr.send(null);
}

export const getExif = (
  image: string | HTMLImageElement,
  timeout: number,
  callback: (res: { Orientation: number },
    msg: string) => void
) => {
  if (Object.prototype.toString.call(image) == '[object String]') {
    getBlob(<string>image, timeout, (blobSrc) => {
      let hasReturn = false;
      if (!blobSrc) {
        if (!hasReturn) {
          hasReturn = true;
          callback({ Orientation: -1 }, 'getBlob error');
        }
        return;
      }

      const timer = setTimeout(() => {
        if (!hasReturn) {
          hasReturn = true;
          callback({ Orientation: -1 }, 'img onload timeout: ' + blobSrc);
        }
      }, timeout * 1000);

      let tmpImg = new Image();

      tmpImg.onload = function () {
        clearTimeout(timer);
        if (!hasReturn) {
          hasReturn = true;
          doTest(tmpImg, callback);
        }
      }

      tmpImg.onerror = function () {
        clearTimeout(timer);
        if (!hasReturn) {
          hasReturn = true;
          callback({ Orientation: -1 }, 'img onerror: ' + blobSrc);
        }
      }

      tmpImg.onabort = function () {
        clearTimeout(timer);
        if (!hasReturn) {
          hasReturn = true;
          callback({ Orientation: -1 }, 'img onabort: ' + blobSrc);
        }
      }

      tmpImg.src = blobSrc;
    })
  } else {
    doTest(<HTMLImageElement>image, callback);
  }
}