imageProcessor处理ios 竖直图片时,导致图片变形的问题
pengkai0113 opened this issue · comments
pk_test commented
先上源码
/* istanbul ignore next */
function getImageSize(img, orientation, maxWidth, maxHeight) {
const ret = {
width: img.width,
height: img.height,
}
if ('5678'.indexOf(orientation) > -1) {
ret.width = img.height
ret.height = img.width
}
// 如果原图小于设定,采用原图
if (ret.width < maxWidth || ret.height < maxHeight) {
return ret
}
const scale = ret.width / ret.height
if (maxWidth && maxHeight) {
if (scale >= maxWidth / maxHeight) {
if (ret.width > maxWidth) {
ret.width = maxWidth
ret.height = Math.ceil(maxWidth / scale)
}
} else {
if (ret.height > maxHeight) {
ret.height = maxHeight
ret.width = Math.ceil(maxHeight * scale)
}
}
} else if (maxWidth) {
if (maxWidth < ret.width) {
ret.width = maxWidth
ret.height = Math.ceil(maxWidth / scale)
}
} else if (maxHeight < ret.height) {
ret.width = Math.ceil(maxHeight * scale)
ret.height = maxHeight
}
// 超过这个值base64无法生成,在IOS上
if (ret.width >= 3264 || ret.height >= 2448) {
ret.width *= 0.8
ret.height *= 0.8
}
return ret
}
/* istanbul ignore next */
function makeCanvas(img, orientation, maxWidth, maxHeight, quality) {
const {width, height} = getImageSize(img, orientation, maxWidth, maxHeight)
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = width
canvas.height = height
ctx.drawImage(img, 0, 0, width, height)
let base64 = null
if (CSS && CSS.supports && !CSS.supports('image-orientation:none')) {
switch (orientation) {
case 3:
ctx.rotate(180 * Math.PI / 180)
ctx.drawImage(img, -width, -height, width, height)
break
case 6:
ctx.rotate(90 * Math.PI / 180)
ctx.drawImage(img, 0, -width, height, width)
break
case 8:
ctx.rotate(270 * Math.PI / 180)
ctx.drawImage(img, -height, 0, height, width)
break
case 2:
ctx.translate(width, 0)
ctx.scale(-1, 1)
ctx.drawImage(img, 0, 0, width, height)
break
case 4:
ctx.translate(width, 0)
ctx.scale(-1, 1)
ctx.rotate(180 * Math.PI / 180)
ctx.drawImage(img, -width, -height, width, height)
break
case 5:
ctx.translate(width, 0)
ctx.scale(-1, 1)
ctx.rotate(90 * Math.PI / 180)
ctx.drawImage(img, 0, -width, height, width)
break
case 7:
ctx.translate(width, 0)
ctx.scale(-1, 1)
ctx.rotate(270 * Math.PI / 180)
ctx.drawImage(img, -height, 0, height, width)
break
default:
ctx.drawImage(img, 0, 0, width, height)
}
} else {
ctx.drawImage(img, 0, 0, width, height)
}
if ((UA.oldIOS || UA.oldAndroid || UA.mQQBrowser || !navigator.userAgent) && window.JPEGEncoder) {
/* global JPEGEncoder */
const encoder = new JPEGEncoder()
const newImg = ctx.getImageData(0, 0, canvas.width, canvas.height)
base64 = encoder.encode(newImg, quality * 100)
} else {
base64 = canvas.toDataURL('image/jpeg', quality)
}
return base64
}
getImageSize函数会处理图片的宽高,makeCanvas会根据这个宽高在canvas中绘制图片。
场景:ios 处理竖直图片
竖直图片在getImageSize 中 ('5678'.indexOf(orientation) > -1为true,所以会被宽高互换
CSS && CSS.supports && !CSS.supports('image-orientation:none')判断为fasle,所以makeCanvas会按错误的宽高直接绘制图片。
这个地方应该判断判断一下
if (CSS && CSS.supports && !CSS.supports('image-orientation:none')) {
switch (orientation) {
case 3:
ctx.rotate(180 * Math.PI / 180)
ctx.drawImage(img, -width, -height, width, height)
break
case 6:
ctx.rotate(90 * Math.PI / 180)
ctx.drawImage(img, 0, -width, height, width)
break
case 8:
ctx.rotate(270 * Math.PI / 180)
ctx.drawImage(img, -height, 0, height, width)
break
case 2:
ctx.translate(width, 0)
ctx.scale(-1, 1)
ctx.drawImage(img, 0, 0, width, height)
break
case 4:
ctx.translate(width, 0)
ctx.scale(-1, 1)
ctx.rotate(180 * Math.PI / 180)
ctx.drawImage(img, -width, -height, width, height)
break
case 5:
ctx.translate(width, 0)
ctx.scale(-1, 1)
ctx.rotate(90 * Math.PI / 180)
ctx.drawImage(img, 0, -width, height, width)
break
case 7:
ctx.translate(width, 0)
ctx.scale(-1, 1)
ctx.rotate(270 * Math.PI / 180)
ctx.drawImage(img, -height, 0, height, width)
break
default:
ctx.drawImage(img, 0, 0, width, height)
}
} else {
//交换过宽高的图片要按交换过的大小绘制图片
if('5678'.indexOf(orientation) > -1){
ctx.drawImage(img, 0, 0, height, width)
}else{
ctx.drawImage(img, 0, 0, width, height)
}
}
兼容方案
对ios的竖直图片进行旋转处理,转成水平的图片,再经过imageProcessor压缩就可以了