使用dart:ui绘制图片

535 阅读1分钟

1前言

在使用Flutter进行开发时,如果想显示图片,我们一般采用Image组件进行相应的展示。Image会自动完成图片的加载,解码,绘制,缓存。我不禁好奇Image组件底层是怎么实现的,Flutter引擎为我们做了什么,于是我开始阅读Image组件的源码。

2如何绘制

跟踪Image组件的代码可以发现,Flutter引擎最终通过Canvas绘制图片。Canvas通过接收的Image对象,进行绘制操作。需要注意的是这个Image是dart:ui提供的对图片进行不透明操作的类,不是Material里面提供的Image Widget。要注意两者之间的区别。绘制图片代码如下,把图片绘制在屏幕正中间

void _drawImage(Duration timeStamp) async {
  PictureRecorder recorder = new PictureRecorder();

  Canvas canvas = new Canvas(recorder);
  Image image = await _loadImage();

  canvas.drawImage(image,-Offset(image.width/2,image.height/2), Paint());

  final picture = recorder.endRecording();

  var centerX = window.physicalSize.width / 2.0;
  var centerY = window.physicalSize.height / 2.0;

  final SceneBuilder sceneBuilder = SceneBuilder()
    ..pushOffset(centerX, centerY)
    ..addPicture(Offset.zero, picture)
    ..pop();

  window.render(sceneBuilder.build());
}

3加载、解码图片

简单起见我们直接从磁盘获取图片,使用decodeImageFromList函数完成对图片的解码。可以看到还是很方便的,不写C语言的代码就能完成图片的解码工作。代码如下:

Future<Image> _loadImage()  {
  final Completer<Image> completer = Completer<Image>();

  final imgFile = File('/storage/emulated/0/test.jpg');
  print(imgFile.readAsBytesSync());

  decodeImageFromList(imgFile.readAsBytesSync(), (img) =>
    completer.complete(img),
  );

  return completer.future;
}

4运行

import 'dart:async';
import 'dart:ui';
import 'dart:io';

void main() {
  window.onBeginFrame = _drawImage;
  window.scheduleFrame();
}

5效果

微信图片_20220513152010.jpg