Flutter Canvas.drawImage() 绘制像素化图像

时间:2020-12-24 14:51:35

标签: flutter dart

在我的 Flutter 项目中,我使用 CustomPainter 来绘制自定义形状。 在那个 CustomPainter 中,我需要绘制一个 png 图像,该图像在我的资产文件夹中以多种尺寸提供,因此我可以获得适合正确屏幕密度的正确图像:

assets
   \1.5x
      image.png   // 54 x 54 pixels
   \2.0x
      image.png   // 72 x 72 pixels
   \3.0x
      image.png   // 108 x 108 pixels
   \4.0x
      image.png   // 144 x 144 pixels
   image.png      // 36 x 36 pixels

这是我加载图像以获取 Image 文件的方法:

import 'dart:ui' as ui;

Future<ui.Image> getImage() async {
   AssetImage assetImage = AssetImage("assets/image.png");
   ImageStream stream = assetImage.resolve(createLocalImageConfiguration(context));
   Completer<ui.Image> completer = Completer();
   stream.addListener(ImageStreamListener((Imageinfo image, _) {
      return completer.complete(image.image);
   }
   return completer.future;
}

在我的 CustomPainter.paint() 函数中,这是我绘制 Image 后的方式:

@override
void paint(Canvas canvas, Size size) {
   // ...
   canvas.drawImage(
      myImage, // <- the loaded image
      Offset(20, 20),
      Paint()
   );
}

我有两个问题:

  • 图像没有以正确的尺寸绘制(它在 HDPI 屏幕中显示的大小为 54 点,而加载的图像的大小为 54 像素......这是 Flutter 错误吗? )
  • 即使我使用 canvas.drawImageRect() 绘制 36 x 36 点的图像,绘制的图像有时仍然会出现故障,具体取决于图像。是的,我仔细检查了原始图像的大小。

那么我应该怎么做才能在我的 canvas 上为正确的屏幕密度绘制正确的图像,以便正确绘制?

谢谢。

1 个答案:

答案 0 :(得分:1)

这是我最终让它工作的方式(感谢@pskink):

第 1 步:返回整个 ImageInfo 对象,而不仅仅是图像:

Future<ImageInfo> getImageInfo(BuildContext context) async {
   AssetImage assetImage = AssetImage("assets/image.png");
   ImageStream stream = assetImage.resolve(createLocalImageConfiguration(context));
   Completer<ImageInfo> completer = Completer();
   stream.addListener(ImageStreamListener((Imageinfo imageInfo, _) {
      return completer.complete(imageInfo);
   }
   return completer.future;
}

第 2 步:使用 ImageInfo.scale 属性和一些过滤来绘制图像:

@override
void paint(Canvas canvas, Size size) {
   // ...
   paintImage(
      canvas: canvas,
      rect: Rect.fromLTWH(
         20, 20,
         myImageInfo.width / myImageInfo.scale,
         myImageInfo.height / myImageInfo.scale),
      image: myImageInfo.image,                // <- the loaded image
      filterQuality: FilterQuality.low,
   );
}