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

Flutter中如何使用AI生成的二维数组蒙版实现图像指定区域模糊

嘿,我来帮你搞定Flutter里指定区域模糊的问题!你遇到的MaskFilter.blur只能用单个sigma参数的问题确实挺头疼的,不过有两种靠谱的方案能实现你要的效果,咱们一步步说~

方案一:自定义Painter结合ImageFilter.blur(适合实时渲染)

这个方法直接在Widget的绘制流程里处理,不需要提前修改图像文件,适合需要实时交互的场景。

实现步骤

  1. 准备基础资源:你需要加载好原始图像,以及后端返回的二维蒙版数组。
  2. 生成蒙版路径:把二维数组转换成Canvas能识别的Path——遍历数组,把值为0(需要模糊的深粉色区域)的位置转换成对应的矩形,添加到Path中:
    Path generateMaskPathFromArray(List<List<int>> maskArray, Size imageSize) {
      final path = Path();
      final tileWidth = imageSize.width / maskArray[0].length;
      final tileHeight = imageSize.height / maskArray.length;
    
      for (int y = 0; y < maskArray.length; y++) {
        for (int x = 0; x < maskArray[y].length; x++) {
          if (maskArray[y][x] == 0) { // 0对应需要模糊的区域
            final rect = Rect.fromLTWH(
              x * tileWidth,
              y * tileHeight,
              tileWidth,
              tileHeight,
            );
            path.addRect(rect);
          }
        }
      }
      return path;
    }
    
  3. 自定义Painter绘制模糊区域:利用Canvas.saveLayer配合ImageFilter.blur(这个支持单独设置sigmaX和sigmaY!),只在蒙版区域应用模糊效果:
    class MaskedBlurPainter extends CustomPainter {
      final Image originalImage;
      final List<List<int>> maskArray;
    
      MaskedBlurPainter({required this.originalImage, required this.maskArray});
    
      @override
      void paint(Canvas canvas, Size size) {
        // 先绘制原始图像,保留非模糊区域
        canvas.drawImage(originalImage, Offset.zero, Paint());
    
        final maskPath = generateMaskPathFromArray(maskArray, size);
    
        // 保存当前图层,给后续内容应用模糊滤镜
        canvas.saveLayer(
          Offset.zero & size,
          Paint()..imageFilter = ImageFilter.blur(sigmaX: 15, sigmaY: 10),
        );
    
        // 用clear模式绘制蒙版路径,相当于把模糊效果"裁剪"到蒙版区域
        canvas.drawPath(
          maskPath,
          Paint()..blendMode = BlendMode.clear,
        );
    
        // 恢复图层,完成绘制
        canvas.restore();
      }
    
      @override
      bool shouldRepaint(covariant MaskedBlurPainter oldDelegate) {
        return originalImage != oldDelegate.originalImage || maskArray != oldDelegate.maskArray;
      }
    }
    
  4. 在Widget中使用:把这个Painter放到CustomPaint里就能显示了:
    CustomPaint(
      size: Size(originalImage.width.toDouble(), originalImage.height.toDouble()),
      painter: MaskedBlurPainter(originalImage: originalImage, maskArray: maskArray),
    )
    

方案二:用image库提前处理图像(适合保存或复用)

如果需要把处理后的图像保存到本地,或者多次复用,推荐用pub上的image库直接操作像素,精度更高。

实现步骤

  1. 添加依赖:在pubspec.yaml里加上:
    dependencies:
      image: ^4.0.17 # 版本号以最新为准
    
  2. 编写处理函数:把原始图像转成image库的对象,遍历蒙版数组对指定区域应用模糊,再转成Flutter的Image:
    import 'package:image/image.dart' as img;
    import 'dart:typed_data';
    import 'dart:ui' as ui;
    
    Future<ui.Image> applyMaskedBlur(ui.Image originalImage, List<List<int>> maskArray) async {
      // 把Flutter Image转成image库的Image对象
      final byteData = await originalImage.toByteData(format: ui.ImageByteFormat.png);
      final img.Image inputImage = img.decodeImage(byteData!.buffer.asUint8List())!;
    
      final width = inputImage.width;
      final height = inputImage.height;
      final tileWidth = width ~/ maskArray[0].length;
      final tileHeight = height ~/ maskArray.length;
    
      // 遍历蒙版,模糊指定区域
      for (int y = 0; y < maskArray.length; y++) {
        for (int x = 0; x < maskArray[y].length; x++) {
          if (maskArray[y][x] == 0) {
            final startX = x * tileWidth;
            final startY = y * tileHeight;
            final endX = (x + 1) * tileWidth;
            final endY = (y + 1) * tileHeight;
    
            // 这里可以分别设置sigmaX和sigmaY,精准控制模糊方向和程度
            img.blur(
              inputImage,
              sigmaX: 15,
              sigmaY: 10,
              x: startX,
              y: startY,
              width: endX - startX,
              height: endY - startY,
            );
          }
        }
      }
    
      // 转成Flutter可用的Image
      final Uint8List outputBytes = img.encodePng(inputImage);
      final codec = await ui.instantiateImageCodec(outputBytes);
      final frame = await codec.getNextFrame();
      return frame.image;
    }
    
  3. 调用并显示:在FutureBuilder里处理异步操作,显示处理后的图像:
    FutureBuilder<ui.Image>(
      future: applyMaskedBlur(originalImage, maskArray),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          final byteData = await snapshot.data!.toByteData(format: ui.ImageByteFormat.png);
          return Image(image: MemoryImage(byteData!.buffer.asUint8List()));
        }
        return const CircularProgressIndicator();
      },
    )
    

小提示

  • 如果蒙版的精度很高(比如每个元素对应单个像素),方案二的像素操作性能会更好;如果是大块区域模糊,方案一更轻便。
  • ImageFilter.blur在不同平台的渲染效果可能略有差异,记得在目标平台上测试调整sigma值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 10:32:30