【问题标题】:Flutter - Save BlendMode to ImageFlutter - 将 BlendMode 保存到图像
【发布时间】:2020-09-14 16:54:15
【问题描述】:

我正在尝试实现一个用户界面,用户可以在其中编辑和应用效果到上传的图像,并希望将BlendMode 保存到图像中。可以保存混合图像的结果或使用Canvas 应用它?

有些包应用了一些特定的过滤器,但我希望为最终用户提供更多可定制的东西。

我已经看到了一些关于如何实现 Canvas 来绘制图像的示例,但无法弄清楚如何使用文档中的相关混合来加载图像。谁能举个例子?

更新:

对于有相同问题的人,下面的代码将介绍如何将图像从画布保存到应用了 blendMode 的文件中。 但我仍然没有预期的结果。生成的图像质量与原始图像不同,混合似乎也不是我应用的混合。而且我不能保存为jpg,就像png文件一样。

那么,我怎样才能在不损失质量的情况下加载图像、应用与画布混合并保存为 jpg 文件?

代码:

const kCanvasSize = 200.0;

class CanvasImageToFile {
  CanvasImageToFile._();
  static final instance = CanvasImageToFile._();

  ByteData _readFromFile(File file) {
    // File file = getSomeCorrectFile();
    Uint8List bytes = file.readAsBytesSync();
    return ByteData.view(bytes.buffer);
  }

  Future<File> _writeToFile(ByteData data) async {
    String dir = (await getTemporaryDirectory()).path;
    String filePath = '$dir/tempImage.jpg';
    final buffer = data.buffer;
    return new File(filePath).writeAsBytes(
        buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
  }

  Future<ui.Image> _loadImageSource(File imageSource) async {
    // ByteData data = await rootBundle.load(asset);
    ByteData data = _readFromFile(imageSource);
    ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
    ui.FrameInfo fi = await codec.getNextFrame();
    return fi.image;
  }

  Future<File> generateImage(File imageSource) async {
    File imageResult;
    ui.Image image;
    await _loadImageSource(imageSource).then((value) {
      image = value;
    });
    if (image != null) {
      final recorder = ui.PictureRecorder();
      var rect =
          Rect.fromPoints(Offset(0.0, 0.0), Offset(kCanvasSize, kCanvasSize));
      final canvas = Canvas(recorder, rect);

      Size outputSize = rect.size;
      Paint paint = new Paint();

      //OVERLAY - BlendMode uses the previously drawn content as a mask
      paint.blendMode = BlendMode.colorBurn;
      paint.color = Colors.red;
      // paint.colorFilter = ColorFilter.mode(Colors.blue, BlendMode.colorDodge);
      // paint = Paint()..color = Colors.red;
      // paint = Paint()..blendMode = BlendMode.multiply;

      //Image
      Size inputSize = Size(image.width.toDouble(), image.height.toDouble());
      final FittedSizes fittedSizes =
          applyBoxFit(BoxFit.cover, inputSize, outputSize);
      final Size sourceSize = fittedSizes.source;
      final Rect sourceRect =
          Alignment.center.inscribe(sourceSize, Offset.zero & inputSize);

      canvas.saveLayer(rect, paint);
      canvas.drawImageRect(
          image, sourceRect, rect, paint);
      canvas.restore();

      final picture = recorder.endRecording();
      final img = await picture.toImage(200, 200);
      final byteData = await img.toByteData(format: ImageByteFormat.png);

      await _writeToFile(byteData).then((value) {
        imageResult = value;
      });
      return imageResult;
    }

【问题讨论】:

    标签: image flutter canvas jpeg blend


    【解决方案1】:

    经过一些研究后,我在之前的代码中使用(Bitmap 包)将图像从 png 解码为 rawUnmodified 进行了一些调整,我可以使用原始格式(jpg)保存图像并实现我想要的。如果有人有同样的问题,请按照以下代码使用画布加载图像,应用混合并写入具有相同质量的文件:

    Future<File> generateImage(
          File imageSource, Color color, BlendMode blendMode) async {
        File imageResult;
        ui.Image image;
        await _loadImageSource(imageSource).then((value) {
          image = value;
        });
        if (image != null) {
          final recorder = ui.PictureRecorder();
          var rect = Rect.fromPoints(Offset(0.0, 0.0),
              Offset(image.width.toDouble(), image.height.toDouble()));
          final canvas = Canvas(recorder, rect);
    
          Size outputSize = rect.size;
          Paint paint = new Paint();
    
          //OVERLAY - BlendMode uses the previously drawn content as a mask
          // paint.blendMode = blendMode;
          // paint.color = color;
          paint.colorFilter = ColorFilter.mode(color, blendMode);
    
          //Image
          Size inputSize = Size(image.width.toDouble(), image.height.toDouble());
          final FittedSizes fittedSizes =
              applyBoxFit(BoxFit.contain, inputSize, outputSize);
          final Size sourceSize = fittedSizes.source;
          final Rect sourceRect =
              Alignment.center.inscribe(sourceSize, Offset.zero & inputSize);
    
          canvas.drawImageRect(image, sourceRect, rect, paint);
    
          final picture = recorder.endRecording();
          final img = await picture.toImage(image.width, image.height);
    
          ByteData byteData =
              await img.toByteData(format: ui.ImageByteFormat.rawUnmodified);
          Bitmap bitmap = Bitmap.fromHeadless(
              image.width, image.height, byteData.buffer.asUint8List());
          Uint8List headedIntList = bitmap.buildHeaded();
    
          await _writeToFile(headedIntList.buffer.asByteData()).then((value) {
            imageResult = value;
          });
          return imageResult;
        }
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-18
      • 2021-10-12
      • 2018-10-23
      • 2018-10-03
      • 2021-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多