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

Commit cc846da

Browse files
authored
Added float32 support to decodeImageFromPixels (#40068)
Added float32 support to decodeImageFromPixels
1 parent 5177251 commit cc846da

File tree

6 files changed

+99
-6
lines changed

6 files changed

+99
-6
lines changed

lib/ui/painting.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,13 +1663,19 @@ enum ImageByteFormat {
16631663
enum PixelFormat {
16641664
/// Each pixel is 32 bits, with the highest 8 bits encoding red, the next 8
16651665
/// bits encoding green, the next 8 bits encoding blue, and the lowest 8 bits
1666-
/// encoding alpha.
1666+
/// encoding alpha. Premultiplied alpha is used.
16671667
rgba8888,
16681668

16691669
/// Each pixel is 32 bits, with the highest 8 bits encoding blue, the next 8
16701670
/// bits encoding green, the next 8 bits encoding red, and the lowest 8 bits
1671-
/// encoding alpha.
1671+
/// encoding alpha. Premultiplied alpha is used.
16721672
bgra8888,
1673+
1674+
/// Each pixel is 128 bits, where each color component is a 32 bit float that
1675+
/// is normalized across the sRGB gamut. The first float is the red
1676+
/// component, followed by: green, blue and alpha. Premultiplied alpha isn't
1677+
/// used, matching [ImageByteFormat.rawExtendedRgba128].
1678+
rgbaFloat32,
16731679
}
16741680

16751681
/// Signature for [Image] lifecycle events.

lib/ui/painting/image_decoder_impeller.cc

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,12 @@ ImageDecoderImpeller::ImageDecoderImpeller(
8686
ImageDecoderImpeller::~ImageDecoderImpeller() = default;
8787

8888
static SkColorType ChooseCompatibleColorType(SkColorType type) {
89-
return kRGBA_8888_SkColorType;
89+
switch (type) {
90+
case kRGBA_F32_SkColorType:
91+
return kRGBA_F16_SkColorType;
92+
default:
93+
return kRGBA_8888_SkColorType;
94+
}
9095
}
9196

9297
static SkAlphaType ChooseCompatibleAlphaType(SkAlphaType type) {
@@ -176,12 +181,26 @@ std::shared_ptr<SkBitmap> ImageDecoderImpeller::DecompressTexture(
176181
FML_DLOG(ERROR) << "Could not decompress image.";
177182
return nullptr;
178183
}
179-
} else {
184+
} else if (image_info.colorType() == base_image_info.colorType()) {
180185
bitmap->setInfo(image_info);
181186
auto pixel_ref = SkMallocPixelRef::MakeWithData(
182187
image_info, descriptor->row_bytes(), descriptor->data());
183188
bitmap->setPixelRef(pixel_ref, 0, 0);
184189
bitmap->setImmutable();
190+
} else {
191+
auto temp_bitmap = std::make_shared<SkBitmap>();
192+
temp_bitmap->setInfo(base_image_info);
193+
auto pixel_ref = SkMallocPixelRef::MakeWithData(
194+
base_image_info, descriptor->row_bytes(), descriptor->data());
195+
temp_bitmap->setPixelRef(pixel_ref, 0, 0);
196+
197+
if (!bitmap->tryAllocPixels(image_info)) {
198+
FML_DLOG(ERROR)
199+
<< "Could not allocate intermediate for pixel conversion.";
200+
return nullptr;
201+
}
202+
temp_bitmap->readPixels(bitmap->pixmap());
203+
bitmap->setImmutable();
185204
}
186205

187206
if (bitmap->dimensions() == target_size) {

lib/ui/painting/image_decoder_unittests.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,31 @@ TEST_F(ImageDecoderFixtureTest, ImpellerWideGamutDisplayP3) {
359359
#endif // IMPELLER_SUPPORTS_RENDERING
360360
}
361361

362+
TEST_F(ImageDecoderFixtureTest, ImpellerPixelConversion32F) {
363+
auto info = SkImageInfo::Make(10, 10, SkColorType::kRGBA_F32_SkColorType,
364+
SkAlphaType::kUnpremul_SkAlphaType);
365+
SkBitmap bitmap;
366+
bitmap.allocPixels(info, 10 * 16);
367+
auto data = SkData::MakeWithoutCopy(bitmap.getPixels(), 10 * 10 * 16);
368+
auto image = SkImage::MakeFromBitmap(bitmap);
369+
ASSERT_TRUE(image != nullptr);
370+
ASSERT_EQ(SkISize::Make(10, 10), image->dimensions());
371+
ASSERT_EQ(nullptr, image->colorSpace());
372+
373+
auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
374+
std::move(data), image->imageInfo(), 10 * 16);
375+
376+
#if IMPELLER_SUPPORTS_RENDERING
377+
std::shared_ptr<SkBitmap> decompressed =
378+
ImageDecoderImpeller::DecompressTexture(
379+
descriptor.get(), SkISize::Make(100, 100), {100, 100},
380+
/*supports_wide_gamut=*/true);
381+
ASSERT_TRUE(decompressed);
382+
ASSERT_EQ(decompressed->colorType(), kRGBA_F16_SkColorType);
383+
ASSERT_EQ(decompressed->colorSpace(), nullptr);
384+
#endif // IMPELLER_SUPPORTS_RENDERING
385+
}
386+
362387
namespace {
363388
float DecodeBGR10(uint32_t x) {
364389
const float max = 1.25098f;

lib/ui/painting/image_descriptor.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,22 @@ void ImageDescriptor::initRaw(Dart_Handle descriptor_handle,
8585
int row_bytes,
8686
PixelFormat pixel_format) {
8787
SkColorType color_type = kUnknown_SkColorType;
88+
SkAlphaType alpha_type = kPremul_SkAlphaType;
8889
switch (pixel_format) {
8990
case PixelFormat::kRGBA8888:
9091
color_type = kRGBA_8888_SkColorType;
9192
break;
9293
case PixelFormat::kBGRA8888:
9394
color_type = kBGRA_8888_SkColorType;
9495
break;
96+
case PixelFormat::kRGBAFloat32:
97+
// `PixelFormat.rgbaFloat32` is documented to not use premultiplied alpha.
98+
color_type = kRGBA_F32_SkColorType;
99+
alpha_type = kUnpremul_SkAlphaType;
100+
break;
95101
}
96102
FML_DCHECK(color_type != kUnknown_SkColorType);
97-
auto image_info =
98-
SkImageInfo::Make(width, height, color_type, kPremul_SkAlphaType);
103+
auto image_info = SkImageInfo::Make(width, height, color_type, alpha_type);
99104
auto descriptor = fml::MakeRefCounted<ImageDescriptor>(
100105
data->data(), std::move(image_info),
101106
row_bytes == -1 ? std::nullopt : std::optional<size_t>(row_bytes));

lib/ui/painting/image_descriptor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class ImageDescriptor : public RefCountedDartWrappable<ImageDescriptor> {
3737
enum PixelFormat {
3838
kRGBA8888,
3939
kBGRA8888,
40+
kRGBAFloat32,
4041
};
4142

4243
/// @brief Asynchronously initializes an ImageDescriptor for an encoded

testing/dart/encoding_test.dart

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,43 @@ const Color _kBlack = Color.fromRGBO(0, 0, 0, 1.0);
1717
const Color _kGreen = Color.fromRGBO(0, 255, 0, 1.0);
1818

1919
void main() {
20+
test('decodeImageFromPixels float32', () async {
21+
const int width = 2;
22+
const int height = 2;
23+
final Float32List pixels = Float32List(width * height * 4);
24+
final List<List<double>> pixels2d = <List<double>>[
25+
<double>[1, 0, 0, 1],
26+
<double>[0, 1, 0, 1],
27+
<double>[0, 0, 1, 1],
28+
<double>[1, 1, 1, 0],
29+
];
30+
int offset = 0;
31+
for (final List<double> color in pixels2d) {
32+
pixels[offset + 0] = color[0];
33+
pixels[offset + 1] = color[1];
34+
pixels[offset + 2] = color[2];
35+
pixels[offset + 3] = color[3];
36+
offset += 4;
37+
}
38+
39+
final Completer<Image> completer = Completer<Image>();
40+
decodeImageFromPixels(
41+
Uint8List.view(pixels.buffer), width, height, PixelFormat.rgbaFloat32,
42+
(Image result) {
43+
completer.complete(result);
44+
});
45+
46+
final Image image = await completer.future;
47+
final ByteData data =
48+
(await image.toByteData(format: ImageByteFormat.rawStraightRgba))!;
49+
final Uint32List readPixels = Uint32List.view(data.buffer);
50+
expect(width * height, readPixels.length);
51+
expect(readPixels[0], 0xff0000ff);
52+
expect(readPixels[1], 0xff00ff00);
53+
expect(readPixels[2], 0xffff0000);
54+
expect(readPixels[3], 0x00ffffff);
55+
});
56+
2057
test('Image.toByteData RGBA format works with simple image', () async {
2158
final Image image = await Square4x4Image.image;
2259
final ByteData data = (await image.toByteData())!;

0 commit comments

Comments
 (0)