Skip to content

Commit

Permalink
[web] Dispose a temporary image that may be created by instantiateIma…
Browse files Browse the repository at this point in the history
…geCodecWithSize (flutter#54096)

Fixes flutter/flutter#147066
  • Loading branch information
jason-simmons authored Jul 31, 2024
1 parent 0eb9d95 commit ed95b49
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 4 deletions.
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/engine/canvaskit/image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class CkResizingCodec extends ResizingCodec {
return image;
}

image.dispose();
return CkImage(skImage, imageSource: ImageBitmapImageSource(bitmap));
}
}
Expand Down
33 changes: 29 additions & 4 deletions lib/web_ui/test/canvaskit/image_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ void main() {
void testMain() {
setUpCanvasKitTest();

tearDown(() {
ui.Image.onCreate = null;
ui.Image.onDispose = null;
});

test('toImage succeeds', () async {
final ui.Image image = await _createImage();
expect(image.runtimeType.toString(), equals('CkImage'));
Expand All @@ -44,8 +49,6 @@ void testMain() {

expect(onCreateInvokedCount, 2);
expect(createdImage, image2);

ui.Image.onCreate = null;
});

test('dispose() invokes onDispose once', () async {
Expand All @@ -65,8 +68,6 @@ void testMain() {

expect(onDisposeInvokedCount, 2);
expect(disposedImage, image2);

ui.Image.onDispose = null;
});

test('fetchImage fetches image in chunks', () async {
Expand Down Expand Up @@ -106,6 +107,30 @@ void testMain() {
expect(size?.width, 600);
expect(size?.height, 300);
});

test('instantiateImageCodecWithSize disposes temporary image', () async {
final Set<ui.Image> activeImages = <ui.Image>{};
ui.Image.onCreate = activeImages.add;
ui.Image.onDispose = activeImages.remove;

final ui.Image image = await _createImage();
final ByteData? imageData = await image.toByteData(format: ui.ImageByteFormat.png);
final ui.ImmutableBuffer imageBuffer = await ui.ImmutableBuffer.fromUint8List(imageData!.buffer.asUint8List());
image.dispose();

final ui.Codec codec = await ui.instantiateImageCodecWithSize(
imageBuffer,
getTargetSize: (w, h) => ui.TargetImageSize(width: w ~/ 2, height: h ~/ 2)
);
final ui.FrameInfo frameInfo = await codec.getNextFrame();

expect(activeImages.length, 1);

frameInfo.image.dispose();
codec.dispose();

expect(activeImages.length, 0);
});
}

Future<ui.Image> _createImage() => _createPicture().toImage(10, 10);
Expand Down

0 comments on commit ed95b49

Please sign in to comment.