return reallyHasAlpha;
}
+static inline bool isDirectModel(SkBitmap::Config config) {
+ return config == SkBitmap::kARGB_8888_Config ||
+ config == SkBitmap::kARGB_4444_Config ||
+ config == SkBitmap::kRGB_565_Config;
+}
+
bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
SkBitmap::Config prefConfig, Mode mode) {
// SkAutoTrace apr("SkPNGImageDecoder::onDecode");
// to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
// draw lots faster if we can flag the bitmap has being opaque
bool reallyHasAlpha = false;
-
+ bool upscaleFromPalette = false;
SkColorTable* colorTable = NULL;
if (color_type == PNG_COLOR_TYPE_PALETTE) {
*colorPtr = colorPtr[-1];
}
colorTable->unlockColors(true);
+
+ // see if we need to upscale to a direct-model
+ if (isDirectModel(prefConfig)) {
+ if (!reallyHasAlpha || SkBitmap::kRGB_565_Config != prefConfig) {
+ upscaleFromPalette = true;
+ config = prefConfig;
+ // need to re-call setConfig
+ decodedBitmap->setConfig(config, sampler.scaledWidth(),
+ sampler.scaledHeight(), 0);
+ }
+ }
}
SkAutoUnref aur(colorTable);
- if (!this->allocPixelRef(decodedBitmap, colorTable)) {
+ if (!this->allocPixelRef(decodedBitmap,
+ upscaleFromPalette ? NULL : colorTable)) {
return false;
}
SkScaledBitmapSampler::SrcConfig sc;
int srcBytesPerPixel = 4;
- if (SkBitmap::kIndex8_Config == config) {
+ if (colorTable != NULL) {
sc = SkScaledBitmapSampler::kIndex;
srcBytesPerPixel = 1;
} else if (hasAlpha) {
} else {
sc = SkScaledBitmapSampler::kRGBX;
}
- if (!sampler.begin(decodedBitmap, sc, doDither)) {
+
+ /* We have to pass the colortable explicitly, since we may have one
+ even if our decodedBitmap doesn't, due to the request that we
+ upscale png's palette to a direct model
+ */
+ SkAutoLockColors ctLock(colorTable);
+ if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors())) {
return false;
}
const int height = decodedBitmap->height();
static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int) {
+ int width, int deltaSrc, int, const SkPMColor[]) {
SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
for (int x = 0; x < width; x++) {
dst[x] = SkPackARGB32(0xFF, src[0], src[0], src[0]);
static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int) {
+ int width, int deltaSrc, int, const SkPMColor[]) {
SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
for (int x = 0; x < width; x++) {
dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
static bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int) {
+ int width, int deltaSrc, int, const SkPMColor[]) {
SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
unsigned alphaMask = 0xFF;
for (int x = 0; x < width; x++) {
static bool Sample_Gray_D565(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int) {
+ int width, int deltaSrc, int, const SkPMColor[]) {
uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
for (int x = 0; x < width; x++) {
dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int y) {
+ int width, int deltaSrc, int y, const SkPMColor[]) {
uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
DITHER_565_SCAN(y);
for (int x = 0; x < width; x++) {
static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int) {
+ int width, int deltaSrc, int, const SkPMColor[]) {
uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
for (int x = 0; x < width; x++) {
dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int y) {
+ int width, int deltaSrc, int y, const SkPMColor[]) {
uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
DITHER_565_SCAN(y);
for (int x = 0; x < width; x++) {
static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int) {
+ int width, int deltaSrc, int, const SkPMColor[]) {
SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
for (int x = 0; x < width; x++) {
unsigned gray = src[0] >> 4;
static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int y) {
+ int width, int deltaSrc, int y, const SkPMColor[]) {
SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
DITHER_4444_SCAN(y);
for (int x = 0; x < width; x++) {
static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int) {
+ int width, int deltaSrc, int, const SkPMColor[]) {
SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
for (int x = 0; x < width; x++) {
dst[x] = SkPackARGB4444(0xF, src[0] >> 4, src[1] >> 4, src[2] >> 4);
static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int y) {
+ int width, int deltaSrc, int y, const SkPMColor[]) {
SkPMColor16* dst = (SkPMColor16*)dstRow;
DITHER_4444_SCAN(y);
static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int) {
+ int width, int deltaSrc, int, const SkPMColor[]) {
SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
unsigned alphaMask = 0xFF;
static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int y) {
+ int width, int deltaSrc, int y, const SkPMColor[]) {
SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
unsigned alphaMask = 0xFF;
DITHER_4444_SCAN(y);
// Index
+#define A32_MASK_IN_PLACE (SK_A32_MASK << SK_A32_SHIFT)
+
+static bool Sample_Index_D8888(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor ctable[]) {
+
+ SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
+ SkPMColor cc = A32_MASK_IN_PLACE;
+ for (int x = 0; x < width; x++) {
+ SkPMColor c = ctable[*src];
+ cc &= c;
+ dst[x] = c;
+ src += deltaSrc;
+ }
+ return cc != A32_MASK_IN_PLACE;
+}
+
+static bool Sample_Index_D565(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor ctable[]) {
+
+ uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+ for (int x = 0; x < width; x++) {
+ dst[x] = SkPixel32ToPixel16(ctable[*src]);
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static bool Sample_Index_D565_D(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src, int width,
+ int deltaSrc, int y, const SkPMColor ctable[]) {
+
+ uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+ DITHER_565_SCAN(y);
+
+ for (int x = 0; x < width; x++) {
+ SkPMColor c = ctable[*src];
+ dst[x] = SkDitherRGBTo565(SkGetPackedR32(c), SkGetPackedG32(c),
+ SkGetPackedB32(c), DITHER_VALUE(x));
+ src += deltaSrc;
+ }
+ return false;
+}
+
+static bool Sample_Index_D4444(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src, int width,
+ int deltaSrc, int y, const SkPMColor ctable[]) {
+
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ SkPMColor cc = A32_MASK_IN_PLACE;
+ for (int x = 0; x < width; x++) {
+ SkPMColor c = ctable[*src];
+ cc &= c;
+ dst[x] = SkPixel32ToPixel4444(c);
+ src += deltaSrc;
+ }
+ return cc != A32_MASK_IN_PLACE;
+}
+
+static bool Sample_Index_D4444_D(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src, int width,
+ int deltaSrc, int y, const SkPMColor ctable[]) {
+
+ SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
+ SkPMColor cc = A32_MASK_IN_PLACE;
+ DITHER_4444_SCAN(y);
+
+ for (int x = 0; x < width; x++) {
+ SkPMColor c = ctable[*src];
+ cc &= c;
+ dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
+ src += deltaSrc;
+ }
+ return cc != A32_MASK_IN_PLACE;
+}
+
static bool Sample_Index_DI(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
- int width, int deltaSrc, int) {
+ int width, int deltaSrc, int, const SkPMColor[]) {
if (1 == deltaSrc) {
memcpy(dstRow, src, width);
} else {
SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height);
fRowProc = NULL;
+ fCTable = NULL;
}
-bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither) {
+bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
+ const SkPMColor ctable[]) {
static const RowProc gProcs[] = {
// 8888 (no dither distinction)
Sample_Gray_D8888, Sample_Gray_D8888,
Sample_RGBx_D8888, Sample_RGBx_D8888,
Sample_RGBA_D8888, Sample_RGBA_D8888,
- NULL, NULL,
+ Sample_Index_D8888, Sample_Index_D8888,
// 565 (no alpha distinction)
Sample_Gray_D565, Sample_Gray_D565_D,
Sample_RGBx_D565, Sample_RGBx_D565_D,
Sample_RGBx_D565, Sample_RGBx_D565_D,
- NULL, NULL,
+ Sample_Index_D565, Sample_Index_D565_D,
// 4444
Sample_Gray_D4444, Sample_Gray_D4444_D,
Sample_RGBx_D4444, Sample_RGBx_D4444_D,
Sample_RGBA_D4444, Sample_RGBA_D4444_D,
- NULL, NULL,
+ Sample_Index_D4444, Sample_Index_D4444_D,
// Index8
NULL, NULL,
NULL, NULL,
Sample_Index_DI, Sample_Index_DI,
};
-
+ fCTable = ctable;
+
int index = 0;
if (dither) {
index += 1;
SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight);
bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
- fDX * fSrcPixelSize, fCurrY);
+ fDX * fSrcPixelSize, fCurrY, fCTable);
fDstRow += fDstRowBytes;
fCurrY += 1;
return hadAlpha;