HarmonyOS鸿蒙Next中应用调用相机拍照后,返回的图片方向(Exif)与实际拍摄方向不一致,如何校正?

HarmonyOS鸿蒙Next中应用调用相机拍照后,返回的图片方向(Exif)与实际拍摄方向不一致,如何校正? 使用 @ohos.multimedia.camera 拍照后,横屏拍摄的照片在 ImageView 中显示为竖屏旋转 90 度,需手动读取 Exif 并旋转,那应该如何矫正呢?

7 回复

【背景知识】

  • 使用相机拍照时,屏幕处于不同的屏幕状态时,原始图像需旋转不同的角度,以确保图像在合适的方向显示。
    • 在预览时,图像旋转角度与屏幕显示旋转角度(Display.rotation)相关。
    • 在拍照、录像时,图像旋转角度与设备重力方向(即设备旋转角度)相关。
  • getPhotoRotation:获取拍照旋转角度。
    • 设备自然方向:设备默认使用方向,手机为竖屏(充电口向下)。
    • 相机镜头角度:值等于相机图像顺时针旋转到设备自然方向的角度,手机后置相机传感器是横屏安装的,所以需要顺时针旋转90度到设备自然方向。
    • 屏幕显示方向:需要屏幕显示的图片左上角为第一个像素点为坐标原点。锁屏时与自然方向一致。

【问题定位】

全局搜索 getPhotoRotation() 关键词,查看应用是否通过该方法获取到拍照旋转角度,并将拍照角度写入 PhotoCaptureSetting.rotation。若缺乏此关键步骤,或者未正确获取拍照旋转角度,会导致应用配置了错误的拍照输出流。

【分析结论】

应用未获取拍照旋转角度,配置了错误的拍照输出流。导致拍摄出来的照片与预览画面的方向不一致。

【修改建议】

正确适配相机旋转角度的开发步骤可以参考:适配相机旋转角度(ArkTS)

示例demo可参考:实现自定义相机功能

更多关于HarmonyOS鸿蒙Next中应用调用相机拍照后,返回的图片方向(Exif)与实际拍摄方向不一致,如何校正?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


还真没碰到过

常见错误规避

  1. 忽略前置摄像头镜像问题:
if (isFrontCamera && rotationDegrees != 0) {
    // 需额外水平翻转
    PixelMap.InitializationOptions flipOpts = new InitializationOptions();
    flipOpts.isVerticallyFlipped = true;
    pixelMap = PixelMap.create(pixelMap, flipOpts);
}
  1. 未处理HEIC格式:
if ("image/heic".equals(mimeType)) {
    opts.formatHint = "image/heic"; // 明确指定格式
}

学到了

在HarmonyOS Next中,应用调用相机拍照后返回的图片方向(Exif)与实际拍摄方向不一致,可通过以下方式校正:

  1. 使用@ohos.multimedia.image模块的ImagePackerImageReceiver处理图像。
  2. 读取图像的Exif信息,使用getImageProperty获取方向属性。
  3. 根据设备传感器方向(通过@ohos.sensor获取)计算实际方向。
  4. 使用ImagemodifyImageProperty方法修正Exif中的方向值,或通过Matrix进行旋转处理。

关键步骤是同步设备方向传感器数据与图像Exif信息,确保方向一致。

在HarmonyOS Next中,相机返回的JPEG图像数据通常包含Exif方向标签(Orientation),但系统默认不会自动应用此旋转。您需要读取Exif信息并校正图像方向。以下是校正步骤:

  1. 获取图像Exif数据:使用@ohos.multimedia.image@ohos.file.fs模块读取图像的Exif信息,提取方向标签(如1、3、6、8等)。

  2. 解析方向值:Exif方向值对应不同旋转角度:

    • 1:正常(无需旋转)
    • 3:旋转180度
    • 6:旋转90度(顺时针)
    • 8:旋转270度(顺时针)
  3. 校正图像方向

    • 使用@ohos.multimedia.imageImagePackerImageReceiver,结合Matrix2D进行旋转处理。
    • 或通过<canvas>绘制图像时应用旋转变换。
  4. 示例代码片段

    // 读取Exif方向(需导入相应模块)
    let orientation = getExifOrientation(imageUri); // 自定义函数获取方向值
    let rotationAngle = 0;
    switch (orientation) {
        case 3:
            rotationAngle = 180;
            break;
        case 6:
            rotationAngle = 90;
            break;
        case 8:
            rotationAngle = 270;
            break;
    }
    // 在ImageView或Canvas中应用旋转
    
  5. 显示校正后图像:将旋转后的图像数据传递给ImageView组件,或保存校正后的图像文件。

注意:如果直接显示,建议在UI层动态旋转;如需持久化,可生成新图像文件。确保处理大图像时性能优化。

回到顶部