Flutter - Сохранить режим BlendMode в изображение - PullRequest
0 голосов
/ 27 мая 2020

Я пытаюсь реализовать пользовательский интерфейс, в котором пользователь может редактировать и применять эффекты к загруженному изображению, и хочу сохранить BlendMode , объединенный с изображением. Можно сохранить результат смешанного изображения или применить его с помощью Canvas ?

Есть некоторые пакеты, которые применяют некоторые специальные c фильтры, но мне нужно что-то более настраиваемое для конечного пользователя.

Я уже видел несколько примеров того, как реализовать 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;
    }

1 Ответ

0 голосов
/ 30 мая 2020

После некоторых исследований и некоторых корректировок при декодировании изображения из png в rawUnmodified в моем предыдущем коде с использованием ( Bitmap package) я смог сохранить изображение в исходном формате (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;
    }
  }
...