From 0987697edfacdb52b8bb5880fed81aa27eede1c8 Mon Sep 17 00:00:00 2001 From: ColdPaleLight <31977171+ColdPaleLight@users.noreply.github.com> Date: Thu, 23 Sep 2021 17:13:02 +0800 Subject: [PATCH] [web] Support raw straight RGBA format in Image.toByteData() in Html (flutter/engine#28357) --- .../lib/src/engine/html_image_codec.dart | 37 ++++++++++--------- .../test/engine/image_to_byte_data_test.dart | 21 ++++++++++- 2 files changed, 38 insertions(+), 20 deletions(-) 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], + ); + }); }