我正在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 }
答案 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());