Image Orientation

上次的笔记被吞了...有点服气


// 用于修复图片朝向,在手机端拍摄时,图像的朝向信息存储在EXIF中。这里需要传入base64,可以适用src.data提取。
const resetOrientation = (srcBase64, srcOrientation) => {
  console.log(srcOrientation, '检测的');
  return new Promise(resolve => {
    var img = new Image();
    img.onload = function() {
      var width = img.width,
        height = img.height,
        canvas = document.createElement('canvas'),
        ctx = canvas.getContext('2d');
      // set proper canvas dimensions before transform & export
      if (4 < srcOrientation && srcOrientation < 9) {
        canvas.width = height;
        canvas.height = width;
      } else {
        canvas.width = width;
        canvas.height = height;
      }
      // transform context before drawing image
      switch (srcOrientation) {
        case 2:
          ctx.transform(-1, 0, 0, 1, width, 0);
          break;
        case 3:
          ctx.transform(-1, 0, 0, -1, width, height);
          break;
        case 4:
          ctx.transform(1, 0, 0, -1, 0, height);
          break;
        case 5:
          ctx.transform(0, 1, 1, 0, 0, 0);
          break;
        case 6:
          ctx.transform(0, 1, -1, 0, height, 0);
          break;
        case 7:
          ctx.transform(0, -1, -1, 0, height, width);
          break;
        case 8:
          ctx.transform(0, -1, 1, 0, 0, width);
          break;
        default:
          break;
      }
      // draw image
      ctx.drawImage(img, 0, 0);
      // export base64
      resolve(canvas.toDataURL('image/jpeg'));
    };
    img.src = srcBase64;
  });
};
// 用于提取图像信息,适用于<input type="file" capture="camera"/>的场景
const getOrientation = file => {
  return new Promise((resolve, reject) => {
    var reader = new FileReader();
    reader.onload = event => {
      if (!event.target) {
        return;
      }
      const file = event.target;
      const view = new DataView(file.result);
      if (view.getUint16(0, false) !== 0xffd8) {
        // JPEG 文件头检测
        return resolve(-2);
      }
      const length = view.byteLength;
      let offset = 2;
      while (offset < length) {
        if (view.getUint16(offset + 2, false) <= 8) return resolve(-1);
        let marker = view.getUint16(offset, false);
        offset += 2;
        if (marker === 0xffe1) {
          // EXIF 头检测
          if (view.getUint32((offset += 2), false) !== 0x45786966) {
            return resolve(-1);
          }
          let little = view.getUint16((offset += 6), false) === 0x4949;
          offset += view.getUint32(offset + 4, little);
          let tags = view.getUint16(offset, little);
          offset += 2;
          for (let i = 0; i < tags; i++) {
            if (view.getUint16(offset + i * 12, little) === 0x0112) {
              return resolve(view.getUint16(offset + i * 12 + 8, little));
            }
          }
        } else if ((marker & 0xff00) !== 0xff00) {
          break;
        } else {
          offset += view.getUint16(offset, false);
        }
      }
      return resolve(-1);
    };
    reader.readAsArrayBuffer(file);
  });
};
// API友好的方法,传入File自动修正。
const fixOrientation = async file => {
  return new Promise(async (resolve, reject) => {
    const orientation = await getOrientation(file);
    var reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      // console.log(reader.result);
      resolve(resetOrientation(reader.result, orientation));
    };
  });
};
export default {
  resetOrientation,
  getOrientation,
  fixOrientation
};

使用示例:


let b64 = await fixorientation.fixOrientation(file);