前言
在我们的 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)
}
})
}
})
}
},