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();
}