| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- import 'dart:io';
- import 'package:sino_med_cloud/core/utils/logger.dart';
- import 'picker_service.dart';
- import 'image_processor.dart';
- import 'media_exception.dart';
- /// 统一媒体服务入口
- ///
- /// 提供快捷的图片选择、拍照和处理功能
- ///
- /// 使用示例:
- /// ```dart
- /// // 从相册选择并自动压缩
- /// final file = await MediaService.pickFromGallery();
- ///
- /// // 使用系统相机拍照并自动压缩
- /// final photo = await MediaService.pickFromCamera();
- ///
- /// // 使用专业相机拍照(需要手动管理生命周期)
- /// final cameraService = CameraService();
- /// await cameraService.init();
- /// final photo = await cameraService.takePicture();
- /// final compressed = await MediaService.compressImage(photo!);
- /// cameraService.dispose();
- /// ```
- class MediaService {
- /// 使用系统相机拍照(快捷方式)
- ///
- /// 自动压缩图片,适合快速拍照场景
- ///
- /// - [imageQuality] 图片质量(1-100),默认 90
- /// - [maxWidth] 压缩后的最大宽度,默认 1080px
- /// - [compressQuality] 压缩质量(1-100),默认 85
- ///
- /// 返回压缩后的照片文件,如果用户取消或失败返回 null
- ///
- /// 抛出 [MediaException] 如果操作失败
- static Future<File?> pickFromCamera({
- int imageQuality = PickerService.defaultImageQuality,
- int maxWidth = ImageProcessor.defaultMaxWidth,
- int compressQuality = ImageProcessor.defaultQuality,
- }) async {
- try {
- AppLogger.d('开始使用系统相机拍照...');
- final file = await PickerService.pickFromCamera(
- imageQuality: imageQuality,
- );
-
- if (file == null) {
- return null;
- }
- AppLogger.d('开始压缩图片...');
- final compressed = await ImageProcessor.compress(
- file,
- maxWidth: maxWidth,
- quality: compressQuality,
- );
- AppLogger.d('拍照并压缩完成: ${compressed.path}');
- return compressed;
- } on MediaException {
- rethrow;
- } catch (e) {
- AppLogger.e('拍照并压缩失败', e);
- throw MediaException(
- '拍照并压缩失败: ${e.toString()}',
- originalError: e,
- );
- }
- }
- /// 从相册选择图片(快捷方式)
- ///
- /// 自动压缩图片,适合快速选择场景
- ///
- /// - [imageQuality] 图片质量(1-100),默认 90
- /// - [maxWidth] 压缩后的最大宽度,默认 1080px
- /// - [compressQuality] 压缩质量(1-100),默认 85
- ///
- /// 返回压缩后的图片文件,如果用户取消或失败返回 null
- ///
- /// 抛出 [MediaException] 如果操作失败
- static Future<File?> pickFromGallery({
- int imageQuality = PickerService.defaultImageQuality,
- int maxWidth = ImageProcessor.defaultMaxWidth,
- int compressQuality = ImageProcessor.defaultQuality,
- }) async {
- try {
- AppLogger.d('开始从相册选择图片...');
- final file = await PickerService.pickFromGallery(
- imageQuality: imageQuality,
- );
-
- if (file == null) {
- return null;
- }
- AppLogger.d('开始压缩图片...');
- final compressed = await ImageProcessor.compress(
- file,
- maxWidth: maxWidth,
- quality: compressQuality,
- );
- AppLogger.d('选择并压缩完成: ${compressed.path}');
- return compressed;
- } on MediaException {
- rethrow;
- } catch (e) {
- AppLogger.e('选择并压缩失败', e);
- throw MediaException(
- '选择并压缩失败: ${e.toString()}',
- originalError: e,
- );
- }
- }
- /// 压缩图片
- ///
- /// - [file] 原始图片文件
- /// - [maxWidth] 最大宽度,默认 1080px
- /// - [quality] 压缩质量(1-100),默认 85
- ///
- /// 返回压缩后的文件(覆盖原文件)
- ///
- /// 抛出 [ImageProcessingException] 如果压缩失败
- static Future<File> compressImage(
- File file, {
- int maxWidth = ImageProcessor.defaultMaxWidth,
- int quality = ImageProcessor.defaultQuality,
- }) async {
- return await ImageProcessor.compress(
- file,
- maxWidth: maxWidth,
- quality: quality,
- );
- }
- /// 获取图片信息
- ///
- /// 返回图片的宽度、高度和文件大小
- ///
- /// 抛出 [ImageProcessingException] 如果获取失败
- static Future<Map<String, dynamic>> getImageInfo(File file) async {
- return await ImageProcessor.getImageInfo(file);
- }
- /// 医疗脱敏处理(去除 EXIF 信息)
- ///
- /// 移除图片中的 EXIF 元数据,保护患者隐私
- ///
- /// 返回脱敏后的文件(覆盖原文件)
- ///
- /// 抛出 [ImageProcessingException] 如果处理失败
- static Future<File> removeExif(File file) async {
- return await ImageProcessor.removeExif(file);
- }
- /// 从相册选择视频
- ///
- /// 返回选择的视频文件,如果用户取消选择返回 null
- ///
- /// 抛出 [MediaException] 如果选择失败
- static Future<File?> pickVideoFromGallery() async {
- return await PickerService.pickVideoFromGallery();
- }
- }
|