mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Support raw straight RGBA format in Image.toByteData() (flutter/engine#28293)
This commit is contained in:
parent
391934cf47
commit
d90a23b4ae
@ -1577,9 +1577,14 @@ class Paint {
|
||||
enum ImageByteFormat {
|
||||
/// Raw RGBA format.
|
||||
///
|
||||
/// Unencoded bytes, in RGBA row-primary form, 8 bits per channel.
|
||||
/// Unencoded bytes, in RGBA row-primary form with premultiplied alpha, 8 bits per channel.
|
||||
rawRgba,
|
||||
|
||||
/// Raw straight RGBA format.
|
||||
///
|
||||
/// Unencoded bytes, in RGBA row-primary form with straight alpha, 8 bits per channel.
|
||||
rawStraightRgba,
|
||||
|
||||
/// Raw unmodified format.
|
||||
///
|
||||
/// Unencoded bytes, in the image's existing format. For example, a grayscale
|
||||
|
||||
@ -31,6 +31,7 @@ namespace {
|
||||
// This must be kept in sync with the enum in painting.dart
|
||||
enum ImageByteFormat {
|
||||
kRawRGBA,
|
||||
kRawStraightRGBA,
|
||||
kRawUnmodified,
|
||||
kPNG,
|
||||
};
|
||||
@ -151,7 +152,8 @@ void ConvertImageToRaster(sk_sp<SkImage> image,
|
||||
}
|
||||
|
||||
sk_sp<SkData> CopyImageByteData(sk_sp<SkImage> raster_image,
|
||||
SkColorType color_type) {
|
||||
SkColorType color_type,
|
||||
SkAlphaType alpha_type) {
|
||||
FML_DCHECK(raster_image);
|
||||
|
||||
SkPixmap pixmap;
|
||||
@ -162,14 +164,14 @@ sk_sp<SkData> CopyImageByteData(sk_sp<SkImage> raster_image,
|
||||
}
|
||||
|
||||
// The color types already match. No need to swizzle. Return early.
|
||||
if (pixmap.colorType() == color_type) {
|
||||
if (pixmap.colorType() == color_type && pixmap.alphaType() == alpha_type) {
|
||||
return SkData::MakeWithCopy(pixmap.addr(), pixmap.computeByteSize());
|
||||
}
|
||||
|
||||
// Perform swizzle if the type doesnt match the specification.
|
||||
auto surface = SkSurface::MakeRaster(
|
||||
SkImageInfo::Make(raster_image->width(), raster_image->height(),
|
||||
color_type, kPremul_SkAlphaType, nullptr));
|
||||
color_type, alpha_type, nullptr));
|
||||
|
||||
if (!surface) {
|
||||
FML_LOG(ERROR) << "Could not set up the surface for swizzle.";
|
||||
@ -205,10 +207,16 @@ sk_sp<SkData> EncodeImage(sk_sp<SkImage> raster_image, ImageByteFormat format) {
|
||||
return png_image;
|
||||
} break;
|
||||
case kRawRGBA: {
|
||||
return CopyImageByteData(raster_image, kRGBA_8888_SkColorType);
|
||||
return CopyImageByteData(raster_image, kRGBA_8888_SkColorType,
|
||||
kPremul_SkAlphaType);
|
||||
} break;
|
||||
case kRawStraightRGBA: {
|
||||
return CopyImageByteData(raster_image, kRGBA_8888_SkColorType,
|
||||
kUnpremul_SkAlphaType);
|
||||
} break;
|
||||
case kRawUnmodified: {
|
||||
return CopyImageByteData(raster_image, raster_image->colorType());
|
||||
return CopyImageByteData(raster_image, raster_image->colorType(),
|
||||
raster_image->alphaType());
|
||||
} break;
|
||||
}
|
||||
|
||||
|
||||
@ -425,6 +425,7 @@ class ImageFilter {
|
||||
|
||||
enum ImageByteFormat {
|
||||
rawRgba,
|
||||
rawStraightRgba,
|
||||
rawUnmodified,
|
||||
png,
|
||||
}
|
||||
|
||||
@ -31,6 +31,22 @@ void main() {
|
||||
expect(bytes, GrayscaleImage.bytesAsRgba);
|
||||
});
|
||||
|
||||
test('Image.toByteData RGBA format works with transparent image', () async {
|
||||
final Image image = await TransparentImage.load();
|
||||
final ByteData data = (await image.toByteData())!;
|
||||
final Uint8List bytes = data.buffer.asUint8List();
|
||||
expect(bytes, hasLength(64));
|
||||
expect(bytes, TransparentImage.bytesAsPremultipliedRgba);
|
||||
});
|
||||
|
||||
test('Image.toByteData Straight RGBA format works with transparent image', () async {
|
||||
final Image image = await TransparentImage.load();
|
||||
final ByteData data = (await image.toByteData(format: ImageByteFormat.rawStraightRgba))!;
|
||||
final Uint8List bytes = data.buffer.asUint8List();
|
||||
expect(bytes, hasLength(64));
|
||||
expect(bytes, TransparentImage.bytesAsStraightRgba);
|
||||
});
|
||||
|
||||
test('Image.toByteData Unmodified format works with simple image', () async {
|
||||
final Image image = await Square4x4Image.image;
|
||||
final ByteData data = (await image.toByteData(format: ImageByteFormat.rawUnmodified))!;
|
||||
@ -124,6 +140,73 @@ class GrayscaleImage {
|
||||
static List<int> get bytesUnmodified => <int>[255, 127, 127, 0];
|
||||
}
|
||||
|
||||
class TransparentImage {
|
||||
TransparentImage._();
|
||||
|
||||
static Future<Image> load() async {
|
||||
final Uint8List bytes = await readFile('transparent_image.png');
|
||||
final Completer<Image> completer = Completer<Image>();
|
||||
decodeImageFromList(bytes, (Image image) => completer.complete(image));
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
static List<int> get bytesAsPremultipliedRgba {
|
||||
return <int>[
|
||||
//First raw, solid colors
|
||||
255, 0, 0, 255, // red
|
||||
0, 255, 0, 255, // green
|
||||
0, 0, 255, 255, // blue
|
||||
136, 136, 136, 255, // grey
|
||||
|
||||
//Second raw, 50% transparent
|
||||
127, 0, 0, 127, // red
|
||||
0, 127, 0, 127, // green
|
||||
0, 0, 127, 127, // blue
|
||||
67, 67, 67, 127, // grey
|
||||
|
||||
//Third raw, 25% transparent
|
||||
63, 0, 0, 63, // red
|
||||
0, 63, 0, 63, // green
|
||||
0, 0, 63, 63, // blue
|
||||
33, 33, 33, 63, // grey
|
||||
|
||||
//Fourth raw, transparent
|
||||
0, 0, 0, 0, // red
|
||||
0, 0, 0, 0, // green
|
||||
0, 0, 0, 0, // blue
|
||||
0, 0, 0, 0, // grey
|
||||
];
|
||||
}
|
||||
|
||||
static List<int> get bytesAsStraightRgba {
|
||||
return <int>[
|
||||
//First raw, solid colors
|
||||
255, 0, 0, 255, // red
|
||||
0, 255, 0, 255, // green
|
||||
0, 0, 255, 255, // blue
|
||||
136, 136, 136, 255, // grey
|
||||
|
||||
//Second raw, 50% transparent
|
||||
255, 0, 0, 127, // red
|
||||
0, 255, 0, 127, // green
|
||||
0, 0, 255, 127, // blue
|
||||
135, 135, 135, 127, // grey
|
||||
|
||||
//Third raw, 25% transparent
|
||||
255, 0, 0, 63, // red
|
||||
0, 255, 0, 63, // green
|
||||
0, 0, 255, 63, // blue
|
||||
134, 134, 134, 63, // grey
|
||||
|
||||
//Fourth raw, transparent
|
||||
0, 0, 0, 0, // red
|
||||
0, 0, 0, 0, // green
|
||||
0, 0, 0, 0, // blue
|
||||
0, 0, 0, 0, // grey
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List> readFile(String fileName) async {
|
||||
final File file = File(path.join('flutter', 'testing', 'resources', fileName));
|
||||
return file.readAsBytes();
|
||||
|
||||
BIN
engine/src/flutter/testing/resources/transparent_image.png
Normal file
BIN
engine/src/flutter/testing/resources/transparent_image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 133 B |
Loading…
x
Reference in New Issue
Block a user