respect preferred config when png is index-based

git-svn-id: http://skia.googlecode.com/svn/trunk@261 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2009-07-08 20:09:23 +00:00
Родитель 40443b2371
Коммит 1134426f6b
5 изменённых файлов: 215 добавлений и 35 удалений

Просмотреть файл

@ -613,19 +613,22 @@ public:
*/
const SkPMColor* colors() const { return fColors; }
/** If a previous bitmap has been locked by this object, unlock its colors
first. If the specified bitmap has a colortable, lock its colors and
return them.
*/
const SkPMColor* lockColors(const SkBitmap& bm) {
/** Locks the table and returns is colors (assuming ctable is not null) and
unlocks the previous table if one was present
*/
const SkPMColor* lockColors(SkColorTable* ctable) {
if (fCTable) {
fCTable->unlockColors(false);
}
fCTable = bm.getColorTable();
fColors = fCTable ? fCTable->lockColors() : NULL;
fCTable = ctable;
fColors = ctable ? ctable->lockColors() : NULL;
return fColors;
}
const SkPMColor* lockColors(const SkBitmap& bm) {
return this->lockColors(bm.getColorTable());
}
private:
SkColorTable* fCTable;
const SkPMColor* fColors;

Просмотреть файл

@ -0,0 +1,67 @@
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkImageDecoder.h"
#include "SkStream.h"
static const struct {
SkBitmap::Config fPrefConfig;
bool fDither;
} gRec[] = {
{ SkBitmap::kIndex8_Config, false },
{ SkBitmap::kARGB_8888_Config, false },
{ SkBitmap::kARGB_4444_Config, false },
{ SkBitmap::kARGB_4444_Config, true },
{ SkBitmap::kRGB_565_Config, false },
{ SkBitmap::kRGB_565_Config, true },
};
class DecodeView : public SkView {
public:
SkBitmap fBitmap[SK_ARRAY_COUNT(gRec)];
DecodeView() {
SkFILEStream stream("/skimages/index.png");
SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
stream.rewind();
codec->setDitherImage(gRec[i].fDither);
codec->decode(&stream, &fBitmap[i], gRec[i].fPrefConfig,
SkImageDecoder::kDecodePixels_Mode);
}
}
protected:
// overrides from SkEventSink
virtual bool onQuery(SkEvent* evt) {
if (SampleCode::TitleQ(*evt)) {
SampleCode::TitleR(evt, "ImageDecoder");
return true;
}
return this->INHERITED::onQuery(evt);
}
void drawBG(SkCanvas* canvas) {
canvas->drawColor(0xFFDDDDDD);
// canvas->drawColor(SK_ColorWHITE);
}
virtual void onDraw(SkCanvas* canvas) {
this->drawBG(canvas);
canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
for (size_t i = 0; i < SK_ARRAY_COUNT(fBitmap); i++) {
canvas->drawBitmap(fBitmap[i], 0, 0);
canvas->translate(SkIntToScalar(fBitmap[i].width()), 0);
}
}
private:
typedef SkView INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
static SkView* MyFactory() { return new DecodeView; }
static SkViewRegister reg(MyFactory);

Просмотреть файл

@ -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();

Просмотреть файл

@ -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;

Просмотреть файл

@ -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