Flutter中如何给图片文件直接应用ColorFilter矩阵并保存到本地
Flutter 应用ColorFilter矩阵到图片并保存本地实现方案
前置依赖
首先添加第三方图像像素处理库image到pubspec.yaml,无需依赖Widget渲染即可直接操作图像数据:
dependencies: flutter: sdk: flutter image: ^4.0.17 # 可替换为最新稳定版
核心实现
首先导入必要的包:
import 'dart:io'; import 'package:image/image.dart' as img; import 'package:flutter/painting.dart';
通过扩展方法实现你需要的调用形式,矩阵计算逻辑和Flutter官方ColorFilter渲染规则完全一致,效果和ColorFiltered组件展示效果无差异:
extension ColorFilterFile on File { Future<File> addColorFilter(ColorFilter filter) async { // 提取ColorFilter的20位矩阵参数 final matrix = (filter as ColorFilterMatrix).matrix; // 读取并解码原图片文件 final originBytes = await readAsBytes(); final originImage = img.decodeImage(originBytes); if (originImage == null) return this; final filteredImage = img.Image.from(originImage); // 遍历所有像素应用滤镜变换 for (int y = 0; y < filteredImage.height; y++) { for (int x = 0; x < filteredImage.width; x++) { final pixel = filteredImage.getPixel(x, y); final r = pixel.r.toDouble(); final g = pixel.g.toDouble(); final b = pixel.b.toDouble(); final a = pixel.a.toDouble(); // 按矩阵规则计算新的RGBA值 double newR = matrix[0]*r + matrix[1]*g + matrix[2]*b + matrix[3]*a + matrix[4]; double newG = matrix[5]*r + matrix[6]*g + matrix[7]*b + matrix[8]*a + matrix[9]; double newB = matrix[10]*r + matrix[11]*g + matrix[12]*b + matrix[13]*a + matrix[14]; double newA = matrix[15]*r + matrix[16]*g + matrix[17]*b + matrix[18]*a + matrix[19]; // 数值范围限制在有效区间0-255 newR = newR.clamp(0, 255); newG = newG.clamp(0, 255); newB = newB.clamp(0, 255); newA = newA.clamp(0, 255); // 替换为滤镜后的像素 filteredImage.setPixelRgba(x, y, newR.toInt(), newG.toInt(), newB.toInt(), newA.toInt()); } } // 编码为图片文件,需要保留透明通道可替换为encodePng final filteredBytes = img.encodeJpg(filteredImage); // 自定义存储路径,此处默认存在原文件同级目录 final newFile = File('${parent.path}/filtered_${uri.pathSegments.last}'); await newFile.writeAsBytes(filteredBytes); return newFile; } }
如果需要直接得到Image组件的扩展,可额外添加以下实现:
extension ColorFilterImage on Image { Future<Image> addColorFilter(ColorFilter filter) async { final file = (this.image as FileImage).file; final filteredFile = await file.addColorFilter(filter); return Image.file(filteredFile); } }
调用示例
完全符合你预期的调用形式:
// 直接对文件应用滤镜得到新文件 File colorFilterFile = await _sampleFile.addColorFilter(ColorFilter.matrix(filter[2])); // 对Image组件应用滤镜得到新的Image组件 Image image = Image.file(_sampleFile); Image colorFilterImage = await image.addColorFilter(ColorFilter.matrix(filter[2]));
注意事项
- 处理高分辨率大图片时建议放到Isolate中执行,避免阻塞主线程造成卡顿
- 存储格式可根据需求调整,需要透明通道时将编码方法替换为
img.encodePng即可
内容的提问来源于stack exchange,提问作者Vora Ravi
相关产品推荐
相关产品推荐

