Scanline decoding for bmp
Redesigns SkScanlineDecoder.h to indicate the ordering
in which the scanlines are provided
Refactors SkSwizzler::Fill() to include the zeroInit check
and to actually be correct.
BUG=skia:3257
BUG=skia:4198
Review URL: https://codereview.chromium.org/1287423002
diff --git a/src/codec/SkMaskSwizzler.cpp b/src/codec/SkMaskSwizzler.cpp
index 58be0c6..6ca9b58 100644
--- a/src/codec/SkMaskSwizzler.cpp
+++ b/src/codec/SkMaskSwizzler.cpp
@@ -8,57 +8,64 @@
#include "SkCodecPriv.h"
#include "SkColorPriv.h"
#include "SkMaskSwizzler.h"
+#include "SkScaledCodec.h"
static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_opaque(
- void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
// Use the masks to decode to the destination
- uint16_t* srcPtr = (uint16_t*) srcRow;
+ uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
SkPMColor* dstPtr = (SkPMColor*) dstRow;
for (int i = 0; i < width; i++) {
- uint16_t p = srcPtr[i];
+ uint16_t p = srcPtr[0];
uint8_t red = masks->getRed(p);
uint8_t green = masks->getGreen(p);
uint8_t blue = masks->getBlue(p);
dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
+ srcPtr += sampleX;
}
return SkSwizzler::kOpaque_ResultAlpha;
}
static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_unpremul(
- void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
// Use the masks to decode to the destination
- uint16_t* srcPtr = (uint16_t*) srcRow;
+ uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
SkPMColor* dstPtr = (SkPMColor*) dstRow;
INIT_RESULT_ALPHA;
for (int i = 0; i < width; i++) {
- uint16_t p = srcPtr[i];
+ uint16_t p = srcPtr[0];
uint8_t red = masks->getRed(p);
uint8_t green = masks->getGreen(p);
uint8_t blue = masks->getBlue(p);
uint8_t alpha = masks->getAlpha(p);
UPDATE_RESULT_ALPHA(alpha);
dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
+ srcPtr += sampleX;
}
return COMPUTE_RESULT_ALPHA;
}
static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_premul(
- void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
// Use the masks to decode to the destination
- uint16_t* srcPtr = (uint16_t*) srcRow;
+ uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
SkPMColor* dstPtr = (SkPMColor*) dstRow;
INIT_RESULT_ALPHA;
for (int i = 0; i < width; i++) {
- uint16_t p = srcPtr[i];
+ uint16_t p = srcPtr[0];
uint8_t red = masks->getRed(p);
uint8_t green = masks->getGreen(p);
uint8_t blue = masks->getBlue(p);
uint8_t alpha = masks->getAlpha(p);
UPDATE_RESULT_ALPHA(alpha);
dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
+ srcPtr += sampleX;
}
return COMPUTE_RESULT_ALPHA;
}
@@ -66,152 +73,174 @@
// 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) {
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
// Use the masks to decode to the destination
- uint16_t* srcPtr = (uint16_t*) srcRow;
+ uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
uint16_t* dstPtr = (uint16_t*) dstRow;
for (int i = 0; i < width; i++) {
- uint16_t p = srcPtr[i];
+ uint16_t p = srcPtr[0];
uint8_t red = masks->getRed(p);
uint8_t green = masks->getGreen(p);
uint8_t blue = masks->getBlue(p);
dstPtr[i] = SkPack888ToRGB16(red, green, blue);
+ srcPtr += sampleX;
}
return SkSwizzler::kOpaque_ResultAlpha;
}
static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_opaque(
- void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
// Use the masks to decode to the destination
+ srcRow += 3 * startX;
SkPMColor* dstPtr = (SkPMColor*) dstRow;
- for (int i = 0; i < 3*width; i += 3) {
- uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
+ for (int i = 0; i < width; i++) {
+ uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
uint8_t red = masks->getRed(p);
uint8_t green = masks->getGreen(p);
uint8_t blue = masks->getBlue(p);
- dstPtr[i/3] = SkPackARGB32NoCheck(0xFF, red, green, blue);
+ dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
+ srcRow += 3 * sampleX;
}
return SkSwizzler::kOpaque_ResultAlpha;
}
static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_unpremul(
- void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
// Use the masks to decode to the destination
- SkPMColor* dstPtr = (SkPMColor*) dstRow;
- INIT_RESULT_ALPHA;
- 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);
- uint8_t alpha = masks->getAlpha(p);
- UPDATE_RESULT_ALPHA(alpha);
- dstPtr[i/3] = SkPackARGB32NoCheck(alpha, red, green, blue);
- }
- return COMPUTE_RESULT_ALPHA;
-}
-
-static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul(
- void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
-
- // Use the masks to decode to the destination
- SkPMColor* dstPtr = (SkPMColor*) dstRow;
- INIT_RESULT_ALPHA;
- 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);
- uint8_t alpha = masks->getAlpha(p);
- UPDATE_RESULT_ALPHA(alpha);
- dstPtr[i/3] = SkPreMultiplyARGB(alpha, red, green, blue);
- }
- 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) {
-
- // Use the masks to decode to the destination
- uint32_t* srcPtr = (uint32_t*) srcRow;
- SkPMColor* dstPtr = (SkPMColor*) 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] = SkPackARGB32NoCheck(0xFF, red, green, blue);
- }
- return SkSwizzler::kOpaque_ResultAlpha;
-}
-
-static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_unpremul(
- void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
-
- // Use the masks to decode to the destination
- uint32_t* srcPtr = (uint32_t*) srcRow;
+ srcRow += 3 * startX;
SkPMColor* dstPtr = (SkPMColor*) dstRow;
INIT_RESULT_ALPHA;
for (int i = 0; i < width; i++) {
- uint32_t p = srcPtr[i];
+ uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
uint8_t red = masks->getRed(p);
uint8_t green = masks->getGreen(p);
uint8_t blue = masks->getBlue(p);
uint8_t alpha = masks->getAlpha(p);
UPDATE_RESULT_ALPHA(alpha);
dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
+ srcRow += 3 * sampleX;
}
return COMPUTE_RESULT_ALPHA;
}
-static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_premul(
- void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul(
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
// Use the masks to decode to the destination
- uint32_t* srcPtr = (uint32_t*) srcRow;
+ srcRow += 3 * startX;
SkPMColor* dstPtr = (SkPMColor*) dstRow;
INIT_RESULT_ALPHA;
for (int i = 0; i < width; i++) {
- uint32_t p = srcPtr[i];
+ uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
uint8_t red = masks->getRed(p);
uint8_t green = masks->getGreen(p);
uint8_t blue = masks->getBlue(p);
uint8_t alpha = masks->getAlpha(p);
UPDATE_RESULT_ALPHA(alpha);
dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
+ srcRow += 3 * sampleX;
+ }
+ return COMPUTE_RESULT_ALPHA;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask24_to_565(
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
+
+ // Use the masks to decode to the destination
+ srcRow += 3 * startX;
+ uint16_t* dstPtr = (uint16_t*) dstRow;
+ for (int i = 0; i < width; i++) {
+ uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
+ uint8_t red = masks->getRed(p);
+ uint8_t green = masks->getGreen(p);
+ uint8_t blue = masks->getBlue(p);
+ dstPtr[i] = SkPack888ToRGB16(red, green, blue);
+ srcRow += 3 * sampleX;
+ }
+ return SkSwizzler::kOpaque_ResultAlpha;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_opaque(
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
+
+ // Use the masks to decode to the destination
+ uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
+ SkPMColor* dstPtr = (SkPMColor*) dstRow;
+ for (int i = 0; i < width; i++) {
+ uint32_t p = srcPtr[0];
+ uint8_t red = masks->getRed(p);
+ uint8_t green = masks->getGreen(p);
+ uint8_t blue = masks->getBlue(p);
+ dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
+ srcPtr += sampleX;
+ }
+ return SkSwizzler::kOpaque_ResultAlpha;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_unpremul(
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
+
+ // Use the masks to decode to the destination
+ uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
+ SkPMColor* dstPtr = (SkPMColor*) dstRow;
+ INIT_RESULT_ALPHA;
+ for (int i = 0; i < width; i++) {
+ uint32_t p = srcPtr[0];
+ uint8_t red = masks->getRed(p);
+ uint8_t green = masks->getGreen(p);
+ uint8_t blue = masks->getBlue(p);
+ uint8_t alpha = masks->getAlpha(p);
+ UPDATE_RESULT_ALPHA(alpha);
+ dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
+ srcPtr += sampleX;
+ }
+ return COMPUTE_RESULT_ALPHA;
+}
+
+static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_premul(
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
+
+ // Use the masks to decode to the destination
+ uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
+ SkPMColor* dstPtr = (SkPMColor*) dstRow;
+ INIT_RESULT_ALPHA;
+ for (int i = 0; i < width; i++) {
+ uint32_t p = srcPtr[0];
+ uint8_t red = masks->getRed(p);
+ uint8_t green = masks->getGreen(p);
+ uint8_t blue = masks->getBlue(p);
+ uint8_t alpha = masks->getAlpha(p);
+ UPDATE_RESULT_ALPHA(alpha);
+ dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
+ srcPtr += sampleX;
}
return COMPUTE_RESULT_ALPHA;
}
static SkSwizzler::ResultAlpha swizzle_mask32_to_565(
- void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {
+ void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
+ uint32_t startX, uint32_t sampleX) {
// Use the masks to decode to the destination
- uint32_t* srcPtr = (uint32_t*) srcRow;
+ uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
uint16_t* dstPtr = (uint16_t*) dstRow;
for (int i = 0; i < width; i++) {
- uint32_t p = srcPtr[i];
+ uint32_t p = srcPtr[0];
uint8_t red = masks->getRed(p);
uint8_t green = masks->getGreen(p);
uint8_t blue = masks->getBlue(p);
dstPtr[i] = SkPack888ToRGB16(red, green, blue);
+ srcPtr += sampleX;
}
return SkSwizzler::kOpaque_ResultAlpha;
}
@@ -222,15 +251,16 @@
*
*/
SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(
- const SkImageInfo& info, SkMasks* masks, uint32_t bitsPerPixel) {
+ const SkImageInfo& dstInfo, const SkImageInfo& srcInfo, SkMasks* masks,
+ uint32_t bitsPerPixel) {
// Choose the appropriate row procedure
RowProc proc = nullptr;
switch (bitsPerPixel) {
case 16:
- switch (info.colorType()) {
+ switch (dstInfo.colorType()) {
case kN32_SkColorType:
- switch (info.alphaType()) {
+ switch (dstInfo.alphaType()) {
case kUnpremul_SkAlphaType:
proc = &swizzle_mask16_to_n32_unpremul;
break;
@@ -245,7 +275,7 @@
}
break;
case kRGB_565_SkColorType:
- switch (info.alphaType()) {
+ switch (dstInfo.alphaType()) {
case kOpaque_SkAlphaType:
proc = &swizzle_mask16_to_565;
break;
@@ -258,9 +288,9 @@
}
break;
case 24:
- switch (info.colorType()) {
+ switch (dstInfo.colorType()) {
case kN32_SkColorType:
- switch (info.alphaType()) {
+ switch (dstInfo.alphaType()) {
case kUnpremul_SkAlphaType:
proc = &swizzle_mask24_to_n32_unpremul;
break;
@@ -275,7 +305,7 @@
}
break;
case kRGB_565_SkColorType:
- switch (info.alphaType()) {
+ switch (dstInfo.alphaType()) {
case kOpaque_SkAlphaType:
proc = &swizzle_mask24_to_565;
break;
@@ -288,9 +318,9 @@
}
break;
case 32:
- switch (info.colorType()) {
+ switch (dstInfo.colorType()) {
case kN32_SkColorType:
- switch (info.alphaType()) {
+ switch (dstInfo.alphaType()) {
case kUnpremul_SkAlphaType:
proc = &swizzle_mask32_to_n32_unpremul;
break;
@@ -305,7 +335,7 @@
}
break;
case kRGB_565_SkColorType:
- switch (info.alphaType()) {
+ switch (dstInfo.alphaType()) {
case kOpaque_SkAlphaType:
proc = &swizzle_mask32_to_565;
break;
@@ -321,7 +351,12 @@
SkASSERT(false);
return nullptr;
}
- return new SkMaskSwizzler(info, masks, proc);
+
+ // Get the sample size
+ int sampleX;
+ SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, &sampleX, NULL);
+
+ return new SkMaskSwizzler(dstInfo, masks, proc, sampleX);
}
/*
@@ -330,10 +365,12 @@
*
*/
SkMaskSwizzler::SkMaskSwizzler(const SkImageInfo& dstInfo, SkMasks* masks,
- RowProc proc)
+ RowProc proc, uint32_t sampleX)
: fDstInfo(dstInfo)
, fMasks(masks)
, fRowProc(proc)
+ , fSampleX(sampleX)
+ , fStartX(get_start_coord(sampleX))
{}
/*
@@ -343,5 +380,5 @@
*/
SkSwizzler::ResultAlpha SkMaskSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
SkASSERT(nullptr != dst && nullptr != src);
- return fRowProc(dst, src, fDstInfo.width(), fMasks);
+ return fRowProc(dst, src, fDstInfo.width(), fMasks, fStartX, fSampleX);
}