如何在Flutter中使用camera包调整实时相机的色调与饱和度
解决方案
一、实时预览的色调/饱和度调整
camera 包的 CameraPreview 本身不自带滤镜API,但可以用Flutter原生的 ColorFiltered 组件包裹预览,通过颜色矩阵实现实时色调与饱和度调整,性能开销低且易实现。
核心代码实现
import 'dart:math' as math; // 生成饱和度调整矩阵(1为原始值,<1降低饱和度,>1增强饱和度) Matrix4 saturationMatrix(double saturation) { final double r = 0.299 * (1 - saturation); final double g = 0.587 * (1 - saturation); final double b = 0.114 * (1 - saturation); return Matrix4.fromList([ r + saturation, g, b, 0, 0, r, g + saturation, b, 0, 0, r, g, b + saturation, 0, 0, 0, 0, 0, 1, 0, ]); } // 生成色调旋转矩阵(angle为弧度,如math.pi/3对应60度) Matrix4 hueRotateMatrix(double angle) { final double cosA = math.cos(angle); final double sinA = math.sin(angle); final double lumR = 0.299; final double lumG = 0.587; final double lumB = 0.114; return Matrix4.fromList([ lumR + cosA * (1 - lumR) + sinA * (-lumR), lumG + cosA * (-lumG) + sinA * (-lumG), lumB + cosA * (-lumB) + sinA * (1 - lumB), 0, 0, lumR + cosA * (-lumR) + sinA * (0.143), lumG + cosA * (1 - lumG) + sinA * (0.140), lumB + cosA * (-lumB) + sinA * (-0.283), 0, 0, lumR + cosA * (-lumR) + sinA * (-(1 - lumR)), lumG + cosA * (-lumG) + sinA * (lumG), lumB + cosA * (1 - lumB) + sinA * (lumB), 0, 0, 0, 0, 0, 1, 0, ]); } // 组合色调与饱和度矩阵 Matrix4 combineFilters(double hueAngle, double saturation) { return saturationMatrix(saturation) * hueRotateMatrix(hueAngle); } // 应用到CameraPreview ColorFiltered( colorFilter: ColorFilter.matrix(combineFilters(math.pi/3, 1.5).storage), child: CameraPreview(controller), )
二、拍摄照片的滤镜应用
拍摄得到的 XFile 需要通过 image 库处理像素,调整后再保存。
步骤与代码
- 添加依赖:在
pubspec.yaml中加入image: ^4.0.17(版本以最新为准) - 处理照片:
import 'package:image/image.dart' as img; import 'package:path_provider/path_provider.dart'; import 'dart:io'; Future<XFile> applyFilterToPhoto(XFile rawPhoto, double hueAngle, double saturation) async { // 读取原始照片 bytes final bytes = await rawPhoto.readAsBytes(); img.Image image = img.decodeImage(bytes)!; // 调整饱和度与色调(image库的hue参数为0-360的角度值) img.adjustColor(image, saturation: saturation); img.adjustColor(image, hue: hueAngle * 180 / math.pi); // 保存处理后的照片到临时目录 final tempDir = await getTemporaryDirectory(); final tempPath = '${tempDir.path}/filtered_photo.jpg'; final file = File(tempPath); await file.writeAsBytes(img.encodeJpg(image, quality: 90)); return XFile(tempPath); } // 使用示例 final XFile rawPhoto = await controller.takePicture(); final XFile filteredPhoto = await applyFilterToPhoto(rawPhoto, math.pi/3, 1.5); // 后续可将filteredPhoto保存到相册
三、录制视频的滤镜应用
camera 包的原生录制不支持实时滤镜,需先录制原始视频,再通过 flutter_ffmpeg 工具处理添加滤镜。
步骤与代码
- 添加依赖:在
pubspec.yaml中加入flutter_ffmpeg: ^0.4.0-lts(选择全功能LTS版本避免功能缺失) - 处理视频:
import 'package:flutter_ffmpeg/flutter_ffmpeg.dart'; import 'package:path_provider/path_provider.dart'; final FlutterFFmpeg _ffmpeg = FlutterFFmpeg(); Future<String> applyFilterToVideo(String rawVideoPath, double hueAngle, double saturation) async { final tempDir = await getTemporaryDirectory(); final outputPath = '${tempDir.path}/filtered_video.mp4'; // FFmpeg命令:用hue滤镜调整色调与饱和度,复用原音频编码 final command = '-i $rawVideoPath -vf "hue=${hueAngle*180/math.pi}:s=$saturation" -c:v libx264 -c:a copy $outputPath'; final int resultCode = await _ffmpeg.execute(command); if (resultCode == 0) { return outputPath; } else { throw Exception('视频滤镜处理失败,FFmpeg返回码:$resultCode'); } } // 使用示例 await controller.startVideoRecording(); // 录制结束后 final XFile rawVideo = await controller.stopVideoRecording(); final String filteredVideoPath = await applyFilterToVideo(rawVideo.path, math.pi/3, 1.5); // 后续可将filteredVideoPath对应的文件保存到相册
补充提示
- 如果需要更复杂的GPU加速滤镜,可使用
flutter_image_filters库,它支持将滤镜直接绑定到CameraPreview的Texture上,实时性能更优。 - 若追求录制时的实时滤镜预览+录制,可替换为第三方相机库(如
camera_camera),这类库内置了滤镜录制支持。
内容的提问来源于stack exchange,提问作者tushar nariya
相关产品推荐
相关产品推荐

