CustomPainter中的canvas drawImage比例高度和宽度

时间:2019-06-23 08:29:37

标签: image canvas flutter draw

我正在Flutter中开发一个应用程序,在这里我将使用CustomPainter绘制用户从画廊/相机中选取的图像。除此之外,用户还可以绘制线条以及更改笔划值,不透明度颜色和单独的颜色。为此,我创建了2个类DrawEditor和DrawingPainter,可以在下面找到这两个类的代码。一旦用户选择了图像 图像被传递到DrawingPainter类,在其中调用paint(),然后绘制线条和图像。问题出在此方法中的_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 }

1 个答案:

答案 0 :(得分:3)

我有一个非常相似的需求,关于使用 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());