Have SkWuffsCodec speak kRGB_565_SkColorType

This takes the "one pass" code path more often, using less memory, as it
does not have to allocate an intermediate width*height pixel buffer.

Wuffs v0.2 did not support RGB 565 color but Wuffs v0.3 does.

The Codec_AnimatedTransparentGif test passes with skia_use_wuffs true or
false.

Change-Id: Id569fc0bf62e614fa881cb235a9a6a1ca340dcb0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/329916
Commit-Queue: Leon Scroggins <scroggo@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
This commit is contained in:
Nigel Tao 2020-10-29 09:42:11 +11:00 committed by Skia Commit-Bot
parent 5c53ae5a72
commit f933e4fb56
2 changed files with 63 additions and 26 deletions

View File

@ -461,9 +461,6 @@ SkCodec::Result SkWuffsCodec::onStartIncrementalDecode(const SkImageInfo& d
if (options.fSubset) {
return SkCodec::kUnimplemented;
}
if (options.fFrameIndex > 0 && SkColorTypeIsAlwaysOpaque(dstInfo.colorType())) {
return SkCodec::kInvalidConversion;
}
SkCodec::Result result = this->seekFrame(WhichDecoder::kIncrDecode, options.fFrameIndex);
if (result != SkCodec::kSuccess) {
return result;
@ -481,6 +478,10 @@ SkCodec::Result SkWuffsCodec::onStartIncrementalDecode(const SkImageInfo& d
size_t bytesPerPixel = 0;
switch (dstInfo.colorType()) {
case kRGB_565_SkColorType:
pixelFormat = WUFFS_BASE__PIXEL_FORMAT__BGR_565;
bytesPerPixel = 2;
break;
case kBGRA_8888_SkColorType:
pixelFormat = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL;
bytesPerPixel = 4;

View File

@ -535,32 +535,68 @@ DEF_TEST(Codec_AnimatedTransparentGif, r) {
ERRORF(r, "Unexpected image info");
return;
}
SkBitmap bm;
bm.allocPixels(info);
for (int i = 0; i < 2; i++) {
SkColor expectedPixels[2][4] = {
{ 0xFF800000, 0xFF900000, 0xFFA00000, 0xFFB00000 },
{ 0xFFC00000, 0xFFD00000, 0xFFE00000, 0xFFF00000 },
};
if (i > 0) {
expectedPixels[1][1] = 0xFF0000FF;
expectedPixels[1][3] = 0xFF000055;
}
for (bool use565 : { false, true }) {
SkBitmap bm;
bm.allocPixels(use565 ? info.makeColorType(kRGB_565_SkColorType) : info);
SkCodec::Options options;
options.fFrameIndex = i;
options.fPriorFrame = (i > 0) ? (i - 1) : SkCodec::kNoFrame;
auto result = codec->getPixels(bm.pixmap(), &options);
REPORTER_ASSERT(r, result == SkCodec::kSuccess, "Failed to decode frame %i", i);
for (int i = 0; i < 2; i++) {
SkCodec::Options options;
options.fFrameIndex = i;
options.fPriorFrame = (i > 0) ? (i - 1) : SkCodec::kNoFrame;
auto result = codec->getPixels(bm.pixmap(), &options);
#ifdef SK_HAS_WUFFS_LIBRARY
// No-op. Wuffs' GIF decoder supports animated 565.
#else
if (use565 && i > 0) {
// Unsupported. Quoting libgifcodec/SkLibGifCodec.cpp:
//
// In theory, we might be able to support this, but it's not
// clear that it is necessary (Chromium does not decode to 565,
// and Android does not decode frames beyond the first).
REPORTER_ASSERT(r, result != SkCodec::kSuccess,
"Unexpected success to decode frame %i", i);
continue;
}
#endif
REPORTER_ASSERT(r, result == SkCodec::kSuccess, "Failed to decode frame %i", i);
for (int y = 0; y < 2; y++) {
for (int x = 0; x < 4; x++) {
auto expected = expectedPixels[y][x];
auto actual = bm.getColor(x, y);
REPORTER_ASSERT(r, actual == expected,
"frame %i, pixel (%i,%i) mismatch! expected: %x actual: %x",
i, x, y, expected, actual);
// Per above: the first frame is full of various red pixels.
SkColor expectedPixels[2][4] = {
{ 0xFF800000, 0xFF900000, 0xFFA00000, 0xFFB00000 },
{ 0xFFC00000, 0xFFD00000, 0xFFE00000, 0xFFF00000 },
};
if (use565) {
// For kRGB_565_SkColorType, copy the red channel's high 3 bits
// to its low 3 bits.
expectedPixels[0][0] = 0xFF840000;
expectedPixels[0][1] = 0xFF940000;
expectedPixels[0][2] = 0xFFA50000;
expectedPixels[0][3] = 0xFFB50000;
expectedPixels[1][0] = 0xFFC60000;
expectedPixels[1][1] = 0xFFD60000;
expectedPixels[1][2] = 0xFFE70000;
expectedPixels[1][3] = 0xFFF70000;
}
if (i > 0) {
// Per above: the second frame overlays a 3x1 rectangle at (1,
// 1): light blue, transparent, dark blue.
//
// Again, for kRGB_565_SkColorType, copy the blue channel's
// high 3 bits to its low 3 bits.
expectedPixels[1][1] = use565 ? 0xFF0000FF : 0xFF0000FF;
expectedPixels[1][3] = use565 ? 0xFF000052 : 0xFF000055;
}
for (int y = 0; y < 2; y++) {
for (int x = 0; x < 4; x++) {
auto expected = expectedPixels[y][x];
auto actual = bm.getColor(x, y);
REPORTER_ASSERT(r, actual == expected,
"use565 %i, frame %i, pixel (%i,%i) "
"mismatch! expected: %x actual: %x",
(int)use565, i, x, y, expected, actual);
}
}
}
}