You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Camera插件拍摄照片Exif Orientation始终为0的问题求助

相机拍摄方向与Exif数据异常问题

我用Flutter的Camera插件开发拍照功能时遇到两个设备兼容性问题:

  • 三星S53手机竖屏拍摄的照片会自动旋转90°
  • Oppo A73无论拍摄时设备是横屏还是竖屏,照片的Exif Orientation始终返回0(竖屏标识),甚至照片宽高也完全一致,无法判断拍摄时的真实方向

这是Camera插件的Bug还是Android系统层面的问题?

核心代码

import 'package:fatamtam/presentation/utils/scaffold_messenger_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:go_router/go_router.dart';
import 'package:permission_handler/permission_handler.dart';

class TakePicturePage extends StatefulWidget {
  const TakePicturePage({
    super.key,
  });

  static String routePath = '/take-picture';

  @override
  TakePictureScreenState createState() => TakePictureScreenState();
}

class TakePictureScreenState extends State<TakePicturePage> {
  CameraController? _controller;
  Future<void>? _initializeControllerFuture;

  @override
  void initState() {
    super.initState();
    initializeCamera();
  }

  void initializeCamera() async {
    var permissionResult = await Permission.camera.request();
    if(permissionResult.isDenied || permissionResult.isPermanentlyDenied) {
      if(mounted) {
        showScaffoldMessenger(context,
            permissionResult.isPermanentlyDenied ? "Il permesso è stato permanentemente negato. Abilitalo dalle impostazioni del tuo telefono." : "È necessario fornire i permessi per accedere alla fotocamera.");
        context.pop(null);
      }
      return;
    }

    final cameras = await availableCameras();

    _controller = CameraController(cameras.first, ResolutionPreset.high,
        enableAudio: false);
    print(_controller);
    _initializeControllerFuture = _controller?.initialize();
    setState(() {});
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Scatta immagine')),
      body: FutureBuilder<void>(
        future: _initializeControllerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done &&
              _controller != null) {
            final scale = 1 /
                (_controller!.value.aspectRatio *
                    MediaQuery.of(context).size.aspectRatio);
            return Transform.scale(
              scale: scale,
              alignment: Alignment.topCenter,
              child: CameraPreview(_controller!),
            );
          } else {
            return const Center(child: CircularProgressIndicator());
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          try {
            await _initializeControllerFuture;
            final image = await _controller?.takePicture();

            if (!context.mounted) return;

            fixImageRotation(image?.path);
            context.pop(image?.path);
          } catch (e) {
            print(e);
          }
        },
        child: const Icon(Icons.camera_alt),
      ),
    );
  }

  void fixImageRotation(String? path) async {

  }
}

尝试读取Exif的代码(无效)

final bytes = await File(imagePath).readAsBytes();
final data = await readExifFromBytes(bytes);
print(await getApplicationDocumentsDirectory());
print(await getApplicationCacheDirectory());
if (data.isEmpty || !data.containsKey('Image Orientation')) {
  return imagePath;
}

img.Image? image = img.decodeImage(bytes);
if (image == null) return imagePath;

解决建议

  • 调整CameraController配置:初始化时指定imageFormatGroup: ImageFormatGroup.jpeg,部分Android厂商对不同图像格式的Exif写入逻辑存在差异;同时升级camera插件到最新稳定版,修复已知的厂商适配Bug。
  • 直接记录拍摄方向:拍摄瞬间通过MediaQuery.of(context).orientation获取设备方向,或使用专门的方向插件获取更精确的角度,将方向信息与照片路径绑定保存,后续根据记录手动旋转图片,无需依赖不可靠的Exif数据。
  • Oppo设备特殊适配:对比预览画面比例与拍摄后照片比例,竖屏预览比例为9:16、横屏为16:9,若照片比例与预览比例不符,说明系统自动调整了方向,需手动修正。
  • 手动旋转图片实现:使用image库根据记录的方向旋转图片,示例代码:
    img.Image rotatedImage = img.copyRotate(image, 90); // 按需选择90/180/270度
    final rotatedBytes = img.encodeJpg(rotatedImage);
    await File(newPath).writeAsBytes(rotatedBytes);
    

内容的提问来源于stack exchange,提问作者Nicola

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 16:58:15