📜  图像抖动中的墨水池不起作用 - Dart (1)

📅  最后修改于: 2023-12-03 14:50:49.028000             🧑  作者: Mango

图像抖动中的墨水池不起作用 - Dart

介绍

本文将介绍一个问题,即在图像抖动时,Dart 中使用的墨水池无法起作用的情况。

问题分析

墨水池是一个方便的工具,可用于在需要时生成指定数量的对象,而不必在每次需要对象时都创建一个新对象。这对于一些开销很大的对象来说非常有用,比如像位图这样的图像对象。

在 Dart 中,墨水池通常与 rootBundle 类一起使用,如下所示:

final bytes = await rootBundle.load('assets/image.png');
final image = await decodeImageFromList(bytes.buffer.asUint8List());
final pool = ImagePool();
final frame = pool.borrowFrame(image.width, image.height);
frame.drawImage(image, 0, 0);

然而,当在图像抖动时,实际上会创建新的帧对象,而不是从墨水池中获取现有的帧对象。这是因为图像抖动会在每个帧之间随机移动像素,并且这种运动会使现有的帧无效。

因此,在图像抖动期间,墨水池不起作用。

解决方案

为了解决这个问题,我们可以手动实现一个帧对象池,以确保帧对象的重用。

class FramePool {
  final List<ImageFrame> _pool = [];

  ImageFrame borrowFrame(int width, int height) {
    if (_pool.isEmpty) {
      return ImageFrame(width, height);
    } else {
      final frame = _pool.removeLast();
      frame.setSize(width, height);
      return frame;
    }
  }

  void returnFrame(ImageFrame frame) {
    _pool.add(frame);
  }
}

然后,我们可以将 FramePool 与使用 dart:ui 库的图像抖动代码一起使用,如下所示:

final bytes = await rootBundle.load('assets/image.png');
final image = await decodeImageFromList(bytes.buffer.asUint8List());
final pool = FramePool();
for (var i = 0; i < 10; ++i) {
  final frame = pool.borrowFrame(image.width, image.height);
  frame.drawImage(image, -i, -i);
  // Draw some other things...
  pool.returnFrame(frame);
}

现在,在图像抖动期间,我们可以通过 FramePool 对象重用帧对象,并避免浪费大量内存。

结论

在 Dart 中,图像抖动会使墨水池无法起作用,我们可以手动实现一个帧对象池以避免浪费大量内存。