uni-app compressImage getImageInfo 存在方向错误和旋转异常压缩无效的问题

uni-app compressImage getImageInfo 存在方向错误和旋转异常压缩无效的问题

测试过的手机:

  • iPhone 8 16
  • iPhone 15 18.6
  • nova12 鸿蒙next
  • oppo

示例代码:

<template>  
    <view style="padding-top: 200rpx;" >  
        <button @click="test">选择图片</button>  
        <view>  
            <text>{{imageInfo}}</text>  
        </view>  
        <image v-if="imageUrl" :src="imageUrl" mode="aspectFill" />  
    </view>  
</template>  

<script setup>  
import {ref} from 'vue'  
/**  
 * 照片有个叫 exif 的部分 的 orientation 存储了图片的方向.  
 * 如果拍的是 字母 F 那么 orientation 就表示数据的实际存储, 查看时需要旋转一下.  
 *   1        2       3      4         5            6           7          8  
 *  
 * 888888  888888      88  88      8888888888  88                  88  8888888888  
 * 88          88      88  88      88  88      88  88          88  88      88  88  
 * 8888      8888    8888  8888    88          8888888888  8888888888          88  
 * 88          88      88  88  
 * 88          88  888888  888888  
 *  
 * iPhone 的照片我们程序都能拿到方向.  
 * 安卓大部分手机无论是那个方向拍照的, 我们程序拿到的都是默认方向 1, 并且图片已经旋  
 * 转正确了, 也可能有和iphone一样能拿到方向的情况.  
 *  
 * 压缩 会将 orientation 设置为 1, 所以压缩时需要根据方向设置 rotate 把图片转正.  
 *  
 * 测试  
 * iPhone 8 的照片 和 iPhone 15 / 16 / 17 的照片 orientation 都为 6.  
 * 压缩时 rotate 传了 90 (顺时针旋转 90 度)  
 * iPhone 15 / 16 / 17 的照片压缩后方向正确.  
 * iPhone 8 的照片压缩后旋转了 180 度.  
 *  
 * 不使用压缩, 直接上传.  
 * iPhone 15 / 16 / 17 的照片太大, 无法上传.  
 * iPhone 8 的照片在商品详情上传, 会被删除 exif 数据, 在单据附件处上传, 正常.  
 *   
 * 说明 uni 和 plus 的 compressImage 可能存在问题.  
 *  
 */  

const imageUrl = ref('');  
const imageInfo = ref('');  

/**  
 * 测试 compressImage 是否存在问题.  
 */  
function test() {  
    uni.chooseImage({  
        count: 1,  
        sizeType: ['original', 'compressed'],  
        sourceType: ['album', 'camera'],  
        success: (chooseImageRes) => {  
            uni.getImageInfo({  
                src: chooseImageRes.tempFilePaths[0],  
                success: (getImageInfoRes) => {  
                    imageInfo.value = `原图:${getImageInfoRes.width}x${getImageInfoRes.height} 方向:${getImageInfoRes.orientation}`  

                    let rotate = 0;  
                    switch (getImageInfoRes.orientation) {  
                        case 'up':  
                        case 'up-mirrored':  
                            rotate = 0;  
                            break;  
                        case 'down':   
                        case 'down-mirrored':   
                            rotate = 180;  
                            break;  
                        case 'left':  
                        case 'left-mirrored':   
                            rotate = 270;  
                            break;  
                        case 'right':  
                        case 'right-mirrored':  
                            rotate = 90;  
                            break;  
                    }  
                    uni.compressImage({  
                        src: chooseImageRes.tempFilePaths[0],  
                        rotate,  
                        success: (compressImageRes) => {  
                            imageUrl.value = compressImageRes.tempFilePath;  
                            uni.getImageInfo({  
                                src: compressImageRes.tempFilePath,  
                                success: (getImageInfoRes) => {  
                                    imageInfo.value += `, 压缩后图:${getImageInfoRes.width}x${getImageInfoRes.height} 方向:${getImageInfoRes.orientation}`  
                                }  
                            })  
                        }  
                    })  
                },  
            })  
        }  
    })  
}  
</script>

操作步骤:

  • 选择图片即可见效果

预期结果:

  • 方向正确, 压缩正确

实际结果:

  • 方向异常, 压缩异常

bug描述:

两种图: iphone 8 (16系统) 拍照的图 8.jpg, iPhone 15(系统 18) 拍照的图 15 plus.jpg, 均通过 uni.chooseImage 原图获取后上传到pc 拿到的图片; [EXIF] 的 Orientation 均为 Rotate 90 CW; 也就是 right.

安卓和ios压缩时 如果指定旋转90度, 则8.jpg 方向错误, 如果不旋转, 则 15 plus.jpg 方向错误;

安卓和ios 的 plus 的 compressImage 也存在该问题.

鸿蒙: getImageInfo 返回的 orientation 全部为 up; compressImage后任然返回原图 无压缩效果, 并且选择图片时无论是否勾选原图均返回原图.

附件为两张图片

uploads.zip


更多关于uni-app compressImage getImageInfo 存在方向错误和旋转异常压缩无效的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于uni-app compressImage getImageInfo 存在方向错误和旋转异常压缩无效的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html


这是一个已知的uni-app图像处理兼容性问题。问题核心在于不同设备和系统对EXIF方向标识的处理不一致。

问题分析:

  1. iOS设备差异:iPhone 8和iPhone 15虽然EXIF方向值相同(均为6,对应rotate 90),但压缩后表现不同,说明底层图像处理库存在版本差异
  2. 鸿蒙系统:getImageInfo始终返回’up’,compressImage压缩无效,这是鸿蒙Next系统的兼容性问题
  3. Android设备:多数设备已自动旋转图片,返回orientation为1,但仍有部分设备需要手动处理

临时解决方案:

// 统一处理方向转换
function getRotateAngle(orientation) {
  const orientationMap = {
    'up': 0,
    'up-mirrored': 0, 
    'down': 180,
    'down-mirrored': 180,
    'left': 270,
    'left-mirrored': 270,
    'right': 90,
    'right-mirrored': 90
  };
  return orientationMap[orientation] || 0;
}

// 针对鸿蒙系统的特殊处理
function compressWithFallback(src, rotate) {
  return new Promise((resolve, reject) => {
    uni.compressImage({
      src,
      rotate,
      success: resolve,
      fail: () => {
        // 压缩失败时返回原图
        resolve({tempFilePath: src});
      }
    });
  });
}
回到顶部