圖片的Exif信息

/**
 * http://blog.csdn.net/libins/article/details/50973498
 * http://blog.csdn.net/han_jiang_xue/article/details/8266207
 * http://www.360doc.com/content/17/0219/18/37253146_630338662.shtml
 * 默認角度
 * 0° =1
 * 順時針90° =6
 * 逆時針90° =8
 * 180° =3
 */
const defaultOrientation = 1
/**
 * https://github.com/exif-js/exif-js/blob/master/exif.js#L107
 */
const TiffTags = 0x0112
/**
 * https://github.com/exif-js/exif-js/blob/master/exif.js#L534
 * @param {*} dataView
 * @param {*} dirStart
 * @param {*} littleEndian
 */
const readTagValue = (dataView, dirStart, littleEndian) => {
  // 第一個  圖像文件目錄Image File Directory(IFD)
  var entries = dataView.getUint16(dirStart, littleEndian)
  var entryOffset
  var i
  for (i = 0; i < entries; i++) {
    // Directory Entry(DE)
    entryOffset = dirStart + i * 12 + 2
    if (TiffTags === dataView.getUint16(entryOffset, littleEndian)) {
      // short, 16 bit int
      return dataView.getUint16(entryOffset + 8, littleEndian)
    }
  }
  return defaultOrientation
}
/**
 * https://github.com/exif-js/exif-js/blob/master/exif.js#L394
 * https://github.com/exif-js/exif-js/blob/master/exif.js#L651
 * @param {*} arrayBuf  reader.readAsArrayBuffer(file)
 */
const readExif = (arrayBuf) => {
  var dataView = new DataView(arrayBuf)
  var offset = 2
  var length = dataView.byteLength
  while (offset < length) {
    // 判斷是不是標記 0xFF+標記號(1個字節(jié))+數(shù)據(jù)大小描述符(2個字節(jié))+數(shù)據(jù)內(nèi)容(n個字節(jié))
    if (dataView.getUint8(offset) !== 0xFF) break
    // Exif 使用APP1(0xFFE1)
    if (dataView.getUint8(offset + 1) === 0xE1) {
      offset = offset + 4
      // Exif 數(shù)據(jù)開始于ASCII字符 "Exif" 和2個字節(jié)的0x00, 后面才是 Exif的數(shù)據(jù)
      // E = 0x45  |  x = 0x78 | i =0x69 | f =0x66
      if (dataView.getUint32(offset) !== (0x45000000 | 0x780000 | 0x6900 | 0x66)) {
        return defaultOrientation
      }
      var littleEndian
      offset = offset + 6

      // TIFF格式中前8個字節(jié)是 TIFF 頭. 其中最開始的前2個字節(jié)定義了 TIFF 數(shù)據(jù)的字節(jié)序.
      // 如果這個值是 0x4949="II"的話, 就表示按照 "Intel" 的字節(jié)序(Little Endian) 來排列數(shù)據(jù).
      // 如果是 0x4d4d="MM",則說明按照 "Motorola" 的字節(jié)序(Big Endian)來排列數(shù)據(jù)

      // 隨后的兩個字節(jié)是一個2字節(jié)長度的固定值 0x002A. ,
      // getUint16 第二個參數(shù)  如果為 false 或未定義,則應(yīng)讀取一個 big-endian 值,否則應(yīng)讀取一個 little-endian 值。
      // 如果數(shù)據(jù)使用 Intel 字節(jié)序, 則這兩個 字節(jié)的數(shù)據(jù)排列為"0x2a,0x00".
      // 如果是 Motorola 的, 則是 "0x00,0x2a"
      if (dataView.getUint16(offset) === 0x4949 && dataView.getUint16(offset + 2, true) === 0x2A00) {
        littleEndian = true
      } else if (dataView.getUint16(offset) === 0x4D4D && dataView.getUint16(offset + 2) === 0x002A) {
        littleEndian = false
      } else {
        return defaultOrientation
      }
      var firstIFDOffset = dataView.getUint32(offset + 4, littleEndian)
      // TIFF頭的最后的 4個字節(jié)是到第一個IFD 偏移量的值是 '0x00000008'.
      if (firstIFDOffset < 0x00000008) {
        return defaultOrientation
      }
      return readTagValue(dataView, offset + firstIFDOffset, littleEndian)
    } else {
      offset += 2 + dataView.getUint16(offset + 2)
    }
  }
  return defaultOrientation
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容