Support more swizzles to 565 in SkCodec
Add more swizzling functions for swizzling to 565. Much of this
code was revived from crrev.com/1055743003 (for BMP). Also added
swizzling functions for WBMP.
Consolidate the static function conversion_possible.
In SkCodec::getPixels, check that the alphatype corresponds to the
colorType. This prevents requesting 565 + non-opaque.
In SkIcoCodec, report that the image is unpremul (instead of
whatever the largest embedded codec thinks), but modify the
requested info to have the alpha type expected/required by the
embedded codec.
Add tests for decoding to 565.
BUG=skia:3257
BUG=skia:3683
Review URL: https://codereview.chromium.org/1277213002
diff --git a/src/codec/SkMaskSwizzler.cpp b/src/codec/SkMaskSwizzler.cpp
index d0bb646..31fd2cf 100644
--- a/src/codec/SkMaskSwizzler.cpp
+++ b/src/codec/SkMaskSwizzler.cpp
@@ -63,6 +63,24 @@
return COMPUTE_RESULT_ALPHA;
}
+// TODO (msarett): We have promoted a two byte per pixel image to 8888, only to
+// convert it back to 565. Instead, we should swizzle to 565 directly.
+static SkSwizzler::ResultAlpha swizzle_mask16_to_565(
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+
+ // Use the masks to decode to the destination
+ uint16_t* srcPtr = (uint16_t*) srcRow;
+ uint16_t* dstPtr = (uint16_t*) dstRow;
+ for (int i = 0; i < width; i++) {
+ uint16_t p = srcPtr[i];
+ uint8_t red = masks->getRed(p);
+ uint8_t green = masks->getGreen(p);
+ uint8_t blue = masks->getBlue(p);
+ dstPtr[i] = SkPack888ToRGB16(red, green, blue);
+ }
+ return SkSwizzler::kOpaque_ResultAlpha;
+}
+
static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_opaque(
void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
@@ -114,6 +132,21 @@
return COMPUTE_RESULT_ALPHA;
}
+static SkSwizzler::ResultAlpha swizzle_mask24_to_565(
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+
+ // Use the masks to decode to the destination
+ uint16_t* dstPtr = (uint16_t*) dstRow;
+ for (int i = 0; i < 3*width; i += 3) {
+ uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
+ uint8_t red = masks->getRed(p);
+ uint8_t green = masks->getGreen(p);
+ uint8_t blue = masks->getBlue(p);
+ dstPtr[i/3] = SkPack888ToRGB16(red, green, blue);
+ }
+ return SkSwizzler::kOpaque_ResultAlpha;
+}
+
static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_opaque(
void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
@@ -168,6 +201,21 @@
return COMPUTE_RESULT_ALPHA;
}
+static SkSwizzler::ResultAlpha swizzle_mask32_to_565(
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+ // Use the masks to decode to the destination
+ uint32_t* srcPtr = (uint32_t*) srcRow;
+ uint16_t* dstPtr = (uint16_t*) dstRow;
+ for (int i = 0; i < width; i++) {
+ uint32_t p = srcPtr[i];
+ uint8_t red = masks->getRed(p);
+ uint8_t green = masks->getGreen(p);
+ uint8_t blue = masks->getBlue(p);
+ dstPtr[i] = SkPack888ToRGB16(red, green, blue);
+ }
+ return SkSwizzler::kOpaque_ResultAlpha;
+}
+
/*
*
* Create a new mask swizzler
@@ -196,6 +244,15 @@
break;
}
break;
+ case kRGB_565_SkColorType:
+ switch (info.alphaType()) {
+ case kOpaque_SkAlphaType:
+ proc = &swizzle_mask16_to_565;
+ break;
+ default:
+ break;
+ }
+ break;
default:
break;
}
@@ -217,6 +274,15 @@
break;
}
break;
+ case kRGB_565_SkColorType:
+ switch (info.alphaType()) {
+ case kOpaque_SkAlphaType:
+ proc = &swizzle_mask24_to_565;
+ break;
+ default:
+ break;
+ }
+ break;
default:
break;
}
@@ -238,6 +304,15 @@
break;
}
break;
+ case kRGB_565_SkColorType:
+ switch (info.alphaType()) {
+ case kOpaque_SkAlphaType:
+ proc = &swizzle_mask32_to_565;
+ break;
+ default:
+ break;
+ }
+ break;
default:
break;
}