expo-image-manipulator 弄乱了图像的纵横比
expo-image-manipulator messes up aspect ratio of images
我们已经使用 Expo Image Manipulator 实现了图像压缩。我们面临的问题是,一些来自压缩功能的照片被弄乱了。示例:
https://i.stack.imgur.com/JezvB.png
图像在 iOS 设备上永远不会弄乱,它在 Android(12、11)上随机发生,主要是在三星手机上。
技术栈:
EXPO SDK 43(托管工作流)
反应本机 0.64.3
我们用来处理压缩的代码:
cameraParsing = async (result) => {
if (result.cancelled) {
return
}
const { uri, width, height } = result
const percentage = this.getResizePercentage(width, height)
const croppedImage = await manipulateAsync(
uri,
[
{
resize: {
width: width - width * percentage,
height: height - height * percentage,
},
},
],
{
compress: 0.4,
},
)
const fileName = uri.split('/')[uri.split('/').length - 1]
this.setState({
selectedFile: fileName,
selectedUri: croppedImage.uri,
})
this.props.setFieldValue(this.props.field.key, {
uri: croppedImage.uri,
type: mime.lookup(fileName),
name: fileName,
})
}
getResizePercentage = (width, height) => {
let percentage = 0
let newWidth = width
let newHeight = height
while (newWidth > 1200 || newHeight > 1150) {
percentage += 0.01
newWidth = width - width * percentage
newHeight = height - height * percentage
}
return percentage
}
也许有人遇到了这个问题并可以帮助解决这个问题?
当您强制图像的高度 + 宽度时会发生这种情况,如果图像是例如,如果您有横向图像但想要方形图像(100 宽 100 高),它会拉伸图像,然后它将以这种方式裁剪它。我建议只定义宽度,这样它就会有自动高度。
所以我已经设法解决了这个问题。
这个问题实际上与设备如何管理图像的纵横比有关。例如,iPhone 相机使用纵横比 4:3、16:9 等(其中 4 是高度,3 是宽度)。但是,某些 Android 设备使用不同的纵横比:3:4、9:16,其中 4 是高度,3 是宽度。这里的问题是 expo 相机总是处理 4:3 的图像,所以最后,图像尺寸数据是错误的。
假设我正在上传一张尺寸为 3024x4032 的照片。
iPhone returns:
{
"cancelled": false,
"height": 4032,
"type": "image",
"uri": "...",
"width": 3024
}
Android returns:
{
"cancelled": false,
"height": 3024,
"type": "image",
"uri": "...",
"width": 4032
}
如果你看得足够仔细,你会看到 Android 案例 returns 混合尺寸(高度作为宽度,宽度作为高度)。这会使压缩弄乱图像。
为了解决这个问题,我发现 React Native 的内置方法 Image.getSize 总是 returns 正确的尺寸,所以最终代码如下所示:
getResizePercentage = (width, height) => {
let percentage = 0
let newWidth = width
let newHeight = height
while (newWidth > 1200 || newHeight > 1150) {
percentage += 0.01
newWidth = width - width * percentage
newHeight = height - height * percentage
}
return percentage
}
cameraParsing = async (result) => {
if (result.cancelled) {
return
}
this.setState({ compressionInProgress: true })
const { uri } = result
Image.getSize(result.uri, async (width, height) => {
const percentage = this.getResizePercentage(width, height)
const croppedImage = await manipulateAsync(
uri,
[
{
resize: {
width: width - width * percentage,
height: height - height * percentage,
},
},
],
{
compress: 0.5,
},
)
this.setState({ compressionInProgress: false })
const fileName = uri.split('/')[uri.split('/').length - 1]
this.setState({
selectedFile: fileName,
selectedUri: croppedImage.uri,
})
this.props.setFieldValue(this.props.field.key, {
uri: croppedImage.uri,
type: mime.lookup(fileName),
name: fileName,
})
})
}
另外,请问各位大神,我确实查了世博相机返回的EXIF数据,也是错误的。
我希望这对其他人有帮助。
我们已经使用 Expo Image Manipulator 实现了图像压缩。我们面临的问题是,一些来自压缩功能的照片被弄乱了。示例:
https://i.stack.imgur.com/JezvB.png
图像在 iOS 设备上永远不会弄乱,它在 Android(12、11)上随机发生,主要是在三星手机上。
技术栈: EXPO SDK 43(托管工作流) 反应本机 0.64.3
我们用来处理压缩的代码:
cameraParsing = async (result) => {
if (result.cancelled) {
return
}
const { uri, width, height } = result
const percentage = this.getResizePercentage(width, height)
const croppedImage = await manipulateAsync(
uri,
[
{
resize: {
width: width - width * percentage,
height: height - height * percentage,
},
},
],
{
compress: 0.4,
},
)
const fileName = uri.split('/')[uri.split('/').length - 1]
this.setState({
selectedFile: fileName,
selectedUri: croppedImage.uri,
})
this.props.setFieldValue(this.props.field.key, {
uri: croppedImage.uri,
type: mime.lookup(fileName),
name: fileName,
})
}
getResizePercentage = (width, height) => {
let percentage = 0
let newWidth = width
let newHeight = height
while (newWidth > 1200 || newHeight > 1150) {
percentage += 0.01
newWidth = width - width * percentage
newHeight = height - height * percentage
}
return percentage
}
也许有人遇到了这个问题并可以帮助解决这个问题?
当您强制图像的高度 + 宽度时会发生这种情况,如果图像是例如,如果您有横向图像但想要方形图像(100 宽 100 高),它会拉伸图像,然后它将以这种方式裁剪它。我建议只定义宽度,这样它就会有自动高度。
所以我已经设法解决了这个问题。
这个问题实际上与设备如何管理图像的纵横比有关。例如,iPhone 相机使用纵横比 4:3、16:9 等(其中 4 是高度,3 是宽度)。但是,某些 Android 设备使用不同的纵横比:3:4、9:16,其中 4 是高度,3 是宽度。这里的问题是 expo 相机总是处理 4:3 的图像,所以最后,图像尺寸数据是错误的。
假设我正在上传一张尺寸为 3024x4032 的照片。
iPhone returns:
{
"cancelled": false,
"height": 4032,
"type": "image",
"uri": "...",
"width": 3024
}
Android returns:
{
"cancelled": false,
"height": 3024,
"type": "image",
"uri": "...",
"width": 4032
}
如果你看得足够仔细,你会看到 Android 案例 returns 混合尺寸(高度作为宽度,宽度作为高度)。这会使压缩弄乱图像。
为了解决这个问题,我发现 React Native 的内置方法 Image.getSize 总是 returns 正确的尺寸,所以最终代码如下所示:
getResizePercentage = (width, height) => {
let percentage = 0
let newWidth = width
let newHeight = height
while (newWidth > 1200 || newHeight > 1150) {
percentage += 0.01
newWidth = width - width * percentage
newHeight = height - height * percentage
}
return percentage
}
cameraParsing = async (result) => {
if (result.cancelled) {
return
}
this.setState({ compressionInProgress: true })
const { uri } = result
Image.getSize(result.uri, async (width, height) => {
const percentage = this.getResizePercentage(width, height)
const croppedImage = await manipulateAsync(
uri,
[
{
resize: {
width: width - width * percentage,
height: height - height * percentage,
},
},
],
{
compress: 0.5,
},
)
this.setState({ compressionInProgress: false })
const fileName = uri.split('/')[uri.split('/').length - 1]
this.setState({
selectedFile: fileName,
selectedUri: croppedImage.uri,
})
this.props.setFieldValue(this.props.field.key, {
uri: croppedImage.uri,
type: mime.lookup(fileName),
name: fileName,
})
})
}
另外,请问各位大神,我确实查了世博相机返回的EXIF数据,也是错误的。
我希望这对其他人有帮助。