image - Canvas drawImage 在 CustomPainter 中缩放高度和宽度

标签 image canvas flutter draw

我正在 Flutter 中开发一个应用程序,我使用 CustomPainter 绘制用户从画廊/相机中选择的图像。除此之外,用户还可以绘制线条以及自行更改笔划值、不透明度颜色和颜色。为此,我创建了 2 个类 DrawEditor 和 DrawingPainter,这两个类的代码可以在下面找到。一旦用户选择图像
图像被传递给调用paint()的DrawingPainter类,然后我绘制线条和图像。问题出在 _paintBackgroundImage() 方法中,我使用 canvas.drawImage(paintedImage, Offset.zero, Paint()); 绘制图像。这不会缩放图像。

早些时候我尝试了一种不同的方法,而不是用 canvas.drawImage(paintedImage, Offset.zero, Paint()) 绘制图像,我使用了 canvas.drawImageRect(paintedImage, inputSubRect, outputSubRect, Paint());如下所示。然而,使用这种方法绘制图片是像素化的,所以我更喜欢 canvas.drawImage(paintedImage, Offset.zero, Paint()) 因为这不会损坏图片。

任何缩放图像的帮助将不胜感激。

  //Example 1 : Code with canvas.drawImageRect but image pixelated
   final UI.Rect rect = UI.Offset.zero & _canvasSize;
       final Size imageSize =Size(paintedImage.width.toDouble(),      paintedImage.height.toDouble());
    FittedSizes sizes = applyBoxFit(BoxFit.contain, imageSize, _canvasSize);
    final Rect inputSubRect =
    Alignment.center.inscribe(sizes.source, Offset.zero & imageSize);
final Rect outputSubRect =
    Alignment.center.inscribe(sizes.destination, rect);

canvas.drawImageRect(paintedImage, inputSubRect, outputSubRect, Paint());

   //Example 2 : Code with canvas.drawImageRect but image pixelated
   canvas.drawRect(Rect.fromPoints(blurStartOffset, blurIndicatorOffset),
      blurPaintSettings)

class DrawingPainter extends CustomPainter {
   static int blurColor = 0xFFB3E5FC;
   UI.Image paintedImage;
   List<DrawingPoints> pointsList;
   List<DrawingPoints> blurPointsList;
   List<Offset> offsetPoints = List();
   Size _canvasSize;
   Offset blurIndicatorOffset;
   Offset blurStartOffset;
   bool isBlur;
   List<BlurIndicatorOffsetWrapper> wrapperList = new List();

   /// To blur an image we need a [MaskFilter]
   Paint blurPaintSettings = new Paint()
      ..style = PaintingStyle.fill
      ..color = Color(blurColor)
      ..maskFilter = MaskFilter.blur(BlurStyle.normal, 3.0);

   DrawingPainter(
      {this.pointsList,
      this.paintedImage,
      this.blurPointsList,
      this.blurIndicatorOffset,
      this.blurStartOffset}) {
      isBlur = blurIndicatorOffset != null;
 }

 @override
 void paint(Canvas canvas, Size size) {
      _canvasSize = size;
      _paintBackgroundImage(canvas);
      _drawPoints(canvas);
      _drawBlurIndicator(canvas);
 }

   /// Paints the image onto the canvas
   void _paintBackgroundImage(Canvas canvas) {
      if (paintedImage == null) {
      return;
     }
     final UI.Rect rect = UI.Offset.zero & _canvasSize;
     final Size imageSize =
    Size(paintedImage.width.toDouble(), paintedImage.height.toDouble());
     FittedSizes sizes = applyBoxFit(BoxFit.contain, imageSize, _canvasSize);
     final Rect inputSubRect =
    Alignment.center.inscribe(sizes.source, Offset.zero & imageSize);
     final Rect outputSubRect =
    Alignment.center.inscribe(sizes.destination, rect);

     canvas.drawImageRect(paintedImage, inputSubRect, outputSubRect, Paint());

    }

    /// Paints the lines onto the canvas
    void _drawPoints(Canvas canvas) {
      for (int i = 0; i < pointsList.length - 1; i++) {
      if (pointsList[i] != null && pointsList[i + 1] != null) {
      canvas.drawLine(pointsList[i].points, pointsList[i + 1].points,
        pointsList[i].paint);
    }
   }
  }

    /// Paints the blur indicator onto the canvas
    void _drawBlurIndicator(Canvas canvas) {
       if (blurStartOffset != null && blurIndicatorOffset != null) {
        canvas.drawRect(Rect.fromPoints(blurStartOffset,  blurIndicatorOffset),
      blurPaintSettings);
    }
  }

  void setBlurIndicator(Offset localOffset) {
      blurIndicatorOffset = localOffset;
   }

  @override
  bool shouldRepaint(DrawingPainter oldDelegate) {
     return true;
  }

  Future<Uint8List> save() async {
     //Create canvas
     // Set PictureRecorder on the canvas and start recording
     UI.PictureRecorder recorder = UI.PictureRecorder();
     Canvas canvas = Canvas(recorder);

     //Draw image on new canvas
     if (paintedImage != null) {
     final Size imageSize = Size(paintedImage.width.toDouble(), paintedImage.height.toDouble());

      //Here image is the problem
      canvas.drawImage(paintedImage, Offset.zero, Paint());
   }

   //Draw points on new canvas
      for (int i = 0; i < pointsList.length - 1; i++) {
      if (pointsList[i] != null && pointsList[i + 1] != null) {
      canvas.drawLine(
             pointsList[i].points,
             pointsList[i + 1].points,
             pointsList[i].paint,
      );
     }
   }

//End recording
final resultImage = await recorder.endRecording().toImage(
      _canvasSize.width.floor(),
      _canvasSize.height.floor(),
    );

final imageBytes =
    await resultImage.toByteData(format: UI.ImageByteFormat.png);

return imageBytes.buffer.asUint8List();
 }


 }

class DrawingPoints {
     Paint paint;
     Offset points;

     DrawingPoints({this.points, this.paint});
}

enum SelectedMode { StrokeWidth, Opacity, Color, Blur }

最佳答案

我有一个非常相似的要求,关于使用 paintImage 的评论正是我想要的,所以我想我会分享我的最终结果。
我需要缩小图像并在该图像上绘制叠加层。图像是我的原始(未缩放)Image 对象。

var recorder = ui.PictureRecorder();
var imageCanvas = new Canvas(recorder);
var painter = _MarkupPainter(_overlays);

//Paint the image into a rectangle that matches the requested width/height.
//This will handle rescaling the image into the rectangle so that it will not be clipped.
paintImage(
  canvas: imageCanvas, 
  rect: Rect.fromLTWH(0, 0, scaledWidth, scaledHeight),
  image: image,
  fit: BoxFit.scaleDown,
  repeat: ImageRepeat.noRepeat,
  scale: 1.0,
  alignment: Alignment.center,
  flipHorizontally: false,
  filterQuality: FilterQuality.high
  );

//Add the markup overlays.
painter.paint(imageCanvas, Size(scaledWidth, scaledHeight));

var picture = recorder.endRecording();

return picture.toImage(scaledWidth.toInt(), scaledHeight.toInt());

关于image - Canvas drawImage 在 CustomPainter 中缩放高度和宽度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56722240/

相关文章:

javascript - HTML Canvas 和 Javascript - 通过选择(从多个位置)触发音频

javascript - HTML5 Canvas 相机/视口(viewport) - 如何实际操作?

Flutter 3.0 显示错误 : WidgetsBinding. instance!.addPostFrameCallback((_) => widget.onReady.call());

python - 如何将不同的图片正确插入到单个文件中

python - 在Python中按 block 加载图像以进行GDAL处理

javascript - 如何调整 html2canvas 的大小并缩放到原始的 100% 分辨率?

flutter - 当我将 better_player flutter 包添加到 pubspec.yaml 中的依赖项时,应用程序无法运行

dart - 在 Flutter 中保持 ScrollView 偏移的同时添加 ListView 项

android - 在 flutter 中仅显示图像的顶部部分

python - 如何用python将方形图像像素化为256个大像素?