[web] Support raw straight RGBA format in Image.toByteData() in Html (flutter/engine#28357)

This commit is contained in:
ColdPaleLight 2021-09-23 17:13:02 +08:00 committed by GitHub
parent 5e5a056363
commit 0987697edf
2 changed files with 38 additions and 20 deletions

View File

@ -172,24 +172,25 @@ class HtmlImage implements ui.Image {
@override
Future<ByteData?> 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<ByteData?>.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<ByteData?>.value(data.contentAsBytes().buffer.asByteData());
} else {
return Future<ByteData?>.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<ByteData?>.value(imageData.data.buffer.asByteData());
default:
if (imgElement.src?.startsWith('data:') == true) {
final UriData data = UriData.fromUri(Uri.parse(imgElement.src!));
return Future<ByteData?>.value(data.contentAsBytes().buffer.asByteData());
} else {
return Future<ByteData?>.value(null);
}
}
}

View File

@ -20,13 +20,19 @@ Future<void> testMain() async {
await webOnlyFontCollection.ensureFontsLoaded();
});
test('Picture.toImage().toByteData()', () async {
Future<Image> 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<void> 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(),
<int>[0xAA00FFFF, 0xAA00FFFF, 0xAA00FFFF, 0xAA00FFFF],
);
});
}