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
相关产品推荐
相关产品推荐

