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>
diff --git a/src/codec/SkWuffsCodec.cpp b/src/codec/SkWuffsCodec.cpp
index 7c966c3..2f0495c 100644
--- a/src/codec/SkWuffsCodec.cpp
+++ b/src/codec/SkWuffsCodec.cpp
@@ -461,9 +461,6 @@
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 @@
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;
diff --git a/tests/GifTest.cpp b/tests/GifTest.cpp
index a3541af..12d8108 100644
--- a/tests/GifTest.cpp
+++ b/tests/GifTest.cpp
@@ -535,32 +535,68 @@
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);
+ }
}
}
}