diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/html_image_codec.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/html_image_codec.dart index 276bcdc54df..c52c9e4b781 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/html_image_codec.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/html_image_codec.dart @@ -172,24 +172,25 @@ class HtmlImage implements ui.Image { @override Future toByteData({ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba}) { - if (format == ui.ImageByteFormat.rawRgba) { - final html.CanvasElement canvas = html.CanvasElement() - ..width = width - ..height = height; - final html.CanvasRenderingContext2D ctx = canvas.context2D; - ctx.drawImage(imgElement, 0, 0); - final html.ImageData imageData = ctx.getImageData(0, 0, width, height); - return Future.value(imageData.data.buffer.asByteData()); - } else if (format == ui.ImageByteFormat.rawStraightRgba) { - // TODO(ColdPaleLight): https://github.com/flutter/flutter/issues/89094 - throw UnsupportedError( - 'Image.toByteData(format: ui.ImageByteFormat.rawStraightRgba) not yet implemented for HTML'); - } - if (imgElement.src?.startsWith('data:') == true) { - final UriData data = UriData.fromUri(Uri.parse(imgElement.src!)); - return Future.value(data.contentAsBytes().buffer.asByteData()); - } else { - return Future.value(null); + switch (format) { + // TODO(ColdPaleLight): https://github.com/flutter/flutter/issues/89128 + // The format rawRgba always returns straight rather than premul currently. + case ui.ImageByteFormat.rawRgba: + case ui.ImageByteFormat.rawStraightRgba: + final html.CanvasElement canvas = html.CanvasElement() + ..width = width + ..height = height; + final html.CanvasRenderingContext2D ctx = canvas.context2D; + ctx.drawImage(imgElement, 0, 0); + final html.ImageData imageData = ctx.getImageData(0, 0, width, height); + return Future.value(imageData.data.buffer.asByteData()); + default: + if (imgElement.src?.startsWith('data:') == true) { + final UriData data = UriData.fromUri(Uri.parse(imgElement.src!)); + return Future.value(data.contentAsBytes().buffer.asByteData()); + } else { + return Future.value(null); + } } } diff --git a/engine/src/flutter/lib/web_ui/test/engine/image_to_byte_data_test.dart b/engine/src/flutter/lib/web_ui/test/engine/image_to_byte_data_test.dart index a6d7bea6ffa..60eed86e226 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/image_to_byte_data_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/image_to_byte_data_test.dart @@ -20,13 +20,19 @@ Future testMain() async { await webOnlyFontCollection.ensureFontsLoaded(); }); - test('Picture.toImage().toByteData()', () async { + Future createTestImageByColor(Color color) async { final EnginePictureRecorder recorder = EnginePictureRecorder(); final RecordingCanvas canvas = recorder.beginRecording(const Rect.fromLTRB(0, 0, 2, 2)); - canvas.drawColor(const Color(0xFFCCDD00), BlendMode.srcOver); + canvas.drawColor(color, BlendMode.srcOver); final Picture testPicture = recorder.endRecording(); final Image testImage = await testPicture.toImage(2, 2); + return testImage; + } + + test('Picture.toImage().toByteData()', () async { + final Image testImage = await createTestImageByColor(const Color(0xFFCCDD00)); + final ByteData bytes = (await testImage.toByteData(format: ImageByteFormat.rawRgba))!; expect( @@ -45,4 +51,15 @@ Future testMain() async { pngHeader, ); }); + + test('Image.toByteData(format: ImageByteFormat.rawStraightRgba)', () async { + final Image testImage = await createTestImageByColor(const Color(0xAAFFFF00)); + + final ByteData bytes = + (await testImage.toByteData(format: ImageByteFormat.rawStraightRgba))!; + expect( + bytes.buffer.asUint32List(), + [0xAA00FFFF, 0xAA00FFFF, 0xAA00FFFF, 0xAA00FFFF], + ); + }); }