Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit ed95b49

Browse files
[web] Dispose a temporary image that may be created by instantiateImageCodecWithSize (#54096)
Fixes flutter/flutter#147066
1 parent 0eb9d95 commit ed95b49

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

lib/web_ui/lib/src/engine/canvaskit/image.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class CkResizingCodec extends ResizingCodec {
130130
return image;
131131
}
132132

133+
image.dispose();
133134
return CkImage(skImage, imageSource: ImageBitmapImageSource(bitmap));
134135
}
135136
}

lib/web_ui/test/canvaskit/image_test.dart

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ void main() {
2121
void testMain() {
2222
setUpCanvasKitTest();
2323

24+
tearDown(() {
25+
ui.Image.onCreate = null;
26+
ui.Image.onDispose = null;
27+
});
28+
2429
test('toImage succeeds', () async {
2530
final ui.Image image = await _createImage();
2631
expect(image.runtimeType.toString(), equals('CkImage'));
@@ -44,8 +49,6 @@ void testMain() {
4449

4550
expect(onCreateInvokedCount, 2);
4651
expect(createdImage, image2);
47-
48-
ui.Image.onCreate = null;
4952
});
5053

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

6669
expect(onDisposeInvokedCount, 2);
6770
expect(disposedImage, image2);
68-
69-
ui.Image.onDispose = null;
7071
});
7172

7273
test('fetchImage fetches image in chunks', () async {
@@ -106,6 +107,30 @@ void testMain() {
106107
expect(size?.width, 600);
107108
expect(size?.height, 300);
108109
});
110+
111+
test('instantiateImageCodecWithSize disposes temporary image', () async {
112+
final Set<ui.Image> activeImages = <ui.Image>{};
113+
ui.Image.onCreate = activeImages.add;
114+
ui.Image.onDispose = activeImages.remove;
115+
116+
final ui.Image image = await _createImage();
117+
final ByteData? imageData = await image.toByteData(format: ui.ImageByteFormat.png);
118+
final ui.ImmutableBuffer imageBuffer = await ui.ImmutableBuffer.fromUint8List(imageData!.buffer.asUint8List());
119+
image.dispose();
120+
121+
final ui.Codec codec = await ui.instantiateImageCodecWithSize(
122+
imageBuffer,
123+
getTargetSize: (w, h) => ui.TargetImageSize(width: w ~/ 2, height: h ~/ 2)
124+
);
125+
final ui.FrameInfo frameInfo = await codec.getNextFrame();
126+
127+
expect(activeImages.length, 1);
128+
129+
frameInfo.image.dispose();
130+
codec.dispose();
131+
132+
expect(activeImages.length, 0);
133+
});
109134
}
110135

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

0 commit comments

Comments
 (0)