diff options
author | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2009-07-08 20:09:23 +0000 |
---|---|---|
committer | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2009-07-08 20:09:23 +0000 |
commit | 1134426f6b1c4130e8dbe4c38a4aa976fbb18b4b (patch) | |
tree | df7c4a1592d7c9627571211e4c7be5265467b9c7 /src/images | |
parent | 40443b2371ecc61e04ad496f69919dc1e30036f5 (diff) |
respect preferred config when png is index-based
git-svn-id: http://skia.googlecode.com/svn/trunk@261 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/images')
-rw-r--r-- | src/images/SkImageDecoder_libpng.cpp | 32 | ||||
-rw-r--r-- | src/images/SkScaledBitmapSampler.cpp | 120 | ||||
-rw-r--r-- | src/images/SkScaledBitmapSampler.h | 14 |
3 files changed, 138 insertions, 28 deletions
diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp index 81e73ef854..8f2652a4eb 100644 --- a/src/images/SkImageDecoder_libpng.cpp +++ b/src/images/SkImageDecoder_libpng.cpp @@ -110,6 +110,12 @@ static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) { 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"); @@ -292,7 +298,7 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, // 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) { @@ -346,11 +352,23 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, *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; } @@ -392,7 +410,7 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, SkScaledBitmapSampler::SrcConfig sc; int srcBytesPerPixel = 4; - if (SkBitmap::kIndex8_Config == config) { + if (colorTable != NULL) { sc = SkScaledBitmapSampler::kIndex; srcBytesPerPixel = 1; } else if (hasAlpha) { @@ -400,7 +418,13 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, } 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(); diff --git a/src/images/SkScaledBitmapSampler.cpp b/src/images/SkScaledBitmapSampler.cpp index 15f44327a7..b51b4e7529 100644 --- a/src/images/SkScaledBitmapSampler.cpp +++ b/src/images/SkScaledBitmapSampler.cpp @@ -23,7 +23,7 @@ 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]); @@ -34,7 +34,7 @@ static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow, 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]); @@ -45,7 +45,7 @@ static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow, 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++) { @@ -61,7 +61,7 @@ static bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow, 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]); @@ -72,7 +72,7 @@ static bool Sample_Gray_D565(void* SK_RESTRICT dstRow, 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++) { @@ -84,7 +84,7 @@ static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow, 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]); @@ -95,7 +95,7 @@ static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow, 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++) { @@ -109,7 +109,7 @@ static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow, 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; @@ -121,7 +121,7 @@ static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow, 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++) { @@ -134,7 +134,7 @@ static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow, 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); @@ -145,7 +145,7 @@ static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow, 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); @@ -159,7 +159,7 @@ static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow, 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; @@ -175,7 +175,7 @@ static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow, 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); @@ -192,9 +192,86 @@ static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow, // 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 { @@ -247,25 +324,27 @@ SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height, 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, @@ -273,7 +352,8 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither) { Sample_Index_DI, Sample_Index_DI, }; - + fCTable = ctable; + int index = 0; if (dither) { index += 1; @@ -331,7 +411,7 @@ bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) { 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; diff --git a/src/images/SkScaledBitmapSampler.h b/src/images/SkScaledBitmapSampler.h index 0bb99242a7..84a75ba544 100644 --- a/src/images/SkScaledBitmapSampler.h +++ b/src/images/SkScaledBitmapSampler.h @@ -2,6 +2,7 @@ #define SkScaledBitmapSampler_DEFINED #include "SkTypes.h" +#include "SkColor.h" class SkBitmap; @@ -26,7 +27,8 @@ public: // Given a dst bitmap (with pixels already allocated) and a src-config, // prepares iterator to process the src colors and write them into dst. // Returns false if the request cannot be fulfulled. - bool begin(SkBitmap* dst, SrcConfig sc, bool doDither); + bool begin(SkBitmap* dst, SrcConfig sc, bool doDither, + const SkPMColor* = NULL); // call with row of src pixels, for y = 0...scaledHeight-1. // returns true if the row had non-opaque alpha in it bool next(const uint8_t* SK_RESTRICT src); @@ -39,17 +41,21 @@ private: int fY0; // first Y coord (scanline) to sample int fDX; // step between X samples int fDY; // step between Y samples - + typedef bool (*RowProc)(void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, - int width, int deltaSrc, int y); - + int width, int deltaSrc, int y, + const SkPMColor[]); + // setup state char* fDstRow; // points into bitmap's pixels int fDstRowBytes; int fCurrY; // used for dithering int fSrcPixelSize; // 1, 3, 4 RowProc fRowProc; + + // optional reference to the src colors if the src is a palette model + const SkPMColor* fCTable; }; #endif |