iphone新版safari竖屏拍照旋转90修复导致exifjs使用问题

1,558 阅读1分钟

前言

在我们的 H5 页面中,有人脸上传的功能, 在旧版的 iphone 上, 竖屏拍照之后照片自动旋转 90, 因此前端使用了exif.js来根据照片的 orientation 信息来判断照片是否需要旋转. 但最近出现用户使用 iphoneX 拍照之后相片出现了横屏的情况

探索

一开始以为是 orientation 的问题,但是发现在 iphonex 上 alert 出来的 orientation 还是6, 也就是 orientation 参数是正确的, 注释掉旋转相关的代码, 直接 canvas 绘图发现, iphonex 上竖屏拍照默认没有横屏!

方案

经过一番搜索, 发现是新版的 webkit 改变了image-orientation这个 css 属性值, 在旧版是none, 而在新版之中是'from-image', 也就是默认会忽略 exif 数据, 新版会自动修正, 导致了我们之前使用的exitjs(或者其他基于类似 exif 元数据来处理图片的库)

所以可以通过检测 image-orientaion 来判断是不是新版的 webkit 内核

var styles = getComputedStyle(document.querySelector('#some-image'));
if (styles.getPropertyValue('image-orientation') === 'from-image') {
  // 图片已经被修正
}

参考代码

getOriginOrientationImage (imagePath) {
  return new Promise((resolve, reject) => {
    const image = new Image()
    image.src = imagePath
    uni.showLoading({
      title: '处理中...'
    })
    image.onload = function () {
      EXIF.getData(image, function () {
        const orientation = EXIF.getTag(this, 'Orientation')
        // 旋转图片为1方向
        if (orientation > 1 && orientation <= 8) {
          // https://github.com/mattiasw/ExifReader/issues/99#issuecomment-640217716
          let newWebkitHasFixedProtraitOrientaion = false
          const styles = getComputedStyle(document.querySelector('#face-image'))
          if (styles.getPropertyValue('image-orientation') === 'from-image') {
            newWebkitHasFixedProtraitOrientaion = true
          }
          const canvas = document.createElement('canvas')
          const ctx = canvas.getContext('2d')
          const imageWidth = image.width
          const imageHeight = image.height
          const canvasWidth = (orientation >= 5 && !newWebkitHasFixedProtraitOrientaion) ? imageHeight : imageWidth
          const canvasHeight = (orientation >= 5 && !newWebkitHasFixedProtraitOrientaion) ? imageWidth : imageHeight
          canvas.width = canvasWidth
          canvas.height = canvasHeight
          ctx.clearRect(0, 0, canvasWidth, canvasHeight)
          switch (orientation) {
            case 6:
              ctx.translate(imageHeight / 2, imageHeight / 2)
              if (!newWebkitHasFixedProtraitOrientaion) {
                ctx.rotate(90 * Math.PI / 180)
              }
              ctx.translate(-imageHeight / 2, -imageHeight / 2)
              break
            default: break
          }
          ctx.drawImage(image, 0, 0)
          canvas.toBlob((blob) => {
            uni.hideLoading()
            const url = getObjectURL(blob)
            resolve(url)
          }, 'image/jpeg', 1)
        } else {
          uni.hideLoading()
          resolve(imagePath)
        }
      })
    }
  })
}
},

参考

EXIF Orientation Issue in Safari Mobile

Reports "right-top" for portrait photos