add optional pref-config table to codecs

git-svn-id: http://skia.googlecode.com/svn/trunk@519 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2010-03-03 21:04:12 +00:00
Родитель 8de2e6de5b
Коммит 3f1f06a26b
11 изменённых файлов: 131 добавлений и 58 удалений

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

@ -89,6 +89,33 @@ public:
Chooser* getChooser() const { return fChooser; }
Chooser* setChooser(Chooser*);
/** This optional table describes the caller's preferred config based on
information about the src data. For this table, the src attributes are
described in terms of depth (index (8), 16, 32/24) and if there is
per-pixel alpha. These inputs combine to create an index into the
pref[] table, which contains the caller's preferred config for that
input, or kNo_Config if there is no preference.
To specify no preferrence, call setPrefConfigTable(NULL), which is
the default.
Note, it is still at the discretion of the codec as to what output
config is actually returned, as it may not be able to support the
caller's preference.
Here is how the index into the table is computed from the src:
depth [8, 16, 32/24] -> 0, 2, 4
alpha [no, yes] -> 0, 1
The two index values are OR'd together.
src: 8-index, no-alpha -> 0
src: 8-index, yes-alpha -> 1
src: 16bit, no-alpha -> 2 // e.g. 565
src: 16bit, yes-alpha -> 3 // e.g. 1555
src: 32/24, no-alpha -> 4
src: 32/24, yes-alpha -> 5
*/
void setPrefConfigTable(const SkBitmap::Config pref[6]);
SkBitmap::Allocator* getAllocator() const { return fAllocator; }
SkBitmap::Allocator* setAllocator(SkBitmap::Allocator*);
@ -145,6 +172,9 @@ public:
note: document use of Allocator, Peeker and Chooser
*/
bool decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode);
bool decode(SkStream* stream, SkBitmap* bitmap, Mode mode) {
return this->decode(stream, bitmap, SkBitmap::kNo_Config, mode);
}
/** Given a stream, this will try to find an appropriate decoder object.
If none is found, the method returns NULL.
@ -232,8 +262,7 @@ public:
protected:
// must be overridden in subclasses. This guy is called by decode(...)
virtual bool onDecode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref,
Mode) = 0;
virtual bool onDecode(SkStream*, SkBitmap* bitmap, Mode) = 0;
/** Can be queried from within onDecode, to see if the user (possibly in
a different thread) has requested the decode to cancel. If this returns
@ -260,12 +289,30 @@ protected:
*/
bool allocPixelRef(SkBitmap*, SkColorTable*) const;
enum SrcDepth {
kIndex_SrcDepth,
k16Bit_SrcDepth,
k32Bit_SrcDepth
};
/** The subclass, inside onDecode(), calls this to determine the config of
the returned bitmap. SrcDepth and hasAlpha reflect the raw data of the
src image. This routine returns the caller's preference given
srcDepth and hasAlpha, or kNo_Config if there is no preference.
Note: this also takes into account GetDeviceConfig(), so the subclass
need not call that.
*/
SkBitmap::Config getPrefConfig(SrcDepth, bool hasAlpha) const;
private:
Peeker* fPeeker;
Chooser* fChooser;
SkBitmap::Allocator* fAllocator;
int fSampleSize;
SkBitmap::Config fDefaultPref; // use if fUsePrefTable is false
SkBitmap::Config fPrefTable[6]; // use if fUsePrefTable is true
bool fDitherImage;
bool fUsePrefTable;
mutable bool fShouldCancelDecode;
// illegal

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

@ -37,7 +37,8 @@ void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config)
SkImageDecoder::SkImageDecoder()
: fPeeker(NULL), fChooser(NULL), fAllocator(NULL), fSampleSize(1),
fDitherImage(true) {
fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true),
fUsePrefTable(false) {
}
SkImageDecoder::~SkImageDecoder() {
@ -91,6 +92,46 @@ bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap,
///////////////////////////////////////////////////////////////////////////////
void SkImageDecoder::setPrefConfigTable(const SkBitmap::Config pref[6]) {
if (NULL == pref) {
fUsePrefTable = false;
} else {
fUsePrefTable = true;
memcpy(fPrefTable, pref, sizeof(fPrefTable));
}
}
SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth,
bool srcHasAlpha) const {
SkBitmap::Config config;
if (fUsePrefTable) {
int index = 0;
switch (srcDepth) {
case kIndex_SrcDepth:
index = 0;
break;
case k16Bit_SrcDepth:
index = 2;
break;
case k32Bit_SrcDepth:
index = 4;
break;
}
if (srcHasAlpha) {
index += 1;
}
config = fPrefTable[index];
} else {
config = fDefaultPref;
}
if (SkBitmap::kNo_Config == config) {
config = SkImageDecoder::GetDeviceConfig();
}
return config;
}
bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config pref, Mode mode) {
// pass a temporary bitmap, so that if we return false, we are assured of
@ -99,8 +140,10 @@ bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm,
// we reset this to false before calling onDecode
fShouldCancelDecode = false;
// assign this, for use by getPrefConfig(), in case fUsePrefTable is false
fDefaultPref = pref;
if (!this->onDecode(stream, &tmp, pref, mode)) {
if (!this->onDecode(stream, &tmp, mode)) {
return false;
}
bm->swap(tmp);

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

@ -31,8 +31,7 @@ public:
}
protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config pref, Mode mode);
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode);
};
static SkImageDecoder* Factory(SkStream* stream) {
@ -81,8 +80,7 @@ private:
bool fJustBounds;
};
bool SkBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config prefConfig, Mode mode) {
bool SkBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
size_t length = stream->getLength();
SkAutoMalloc storage(length);
@ -110,12 +108,12 @@ bool SkBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* bm,
int width = callback.width();
int height = callback.height();
SkBitmap::Config config = SkBitmap::kARGB_8888_Config;
SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
// only accept prefConfig if it makes sense for us
if (SkBitmap::kARGB_4444_Config == prefConfig ||
SkBitmap::kRGB_565_Config == config) {
config = prefConfig;
if (SkBitmap::kARGB_4444_Config != config &&
SkBitmap::kRGB_565_Config != config) {
config = SkBitmap::kARGB_8888_Config;
}
SkScaledBitmapSampler sampler(width, height, getSampleSize());

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

@ -31,8 +31,7 @@ public:
}
protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config pref, Mode mode);
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode);
};
static const uint8_t gStartingIterlaceYValue[] = {
@ -154,8 +153,7 @@ static bool error_return(GifFileType* gif, const SkBitmap& bm,
return false;
}
bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm,
SkBitmap::Config prefConfig, Mode mode) {
bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc);
if (NULL == gif) {
return error_return(gif, *bm, "DGifOpen");

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

@ -29,8 +29,7 @@ public:
}
protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config pref, Mode);
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
};
/////////////////////////////////////////////////////////////////////////////////////////
@ -79,8 +78,7 @@ static int calculateRowBytesFor8888(int w, int bitCount)
return 0;
}
bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config pref, Mode mode)
bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode)
{
size_t length = stream->read(NULL, 0);
SkAutoMalloc autoMal(length);

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

@ -55,8 +55,7 @@ public:
}
protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config pref, Mode);
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
};
//////////////////////////////////////////////////////////////////////////
@ -157,8 +156,7 @@ static bool return_false(const jpeg_decompress_struct& cinfo,
return false; // must always return false
}
bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config prefConfig, Mode mode) {
bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
#ifdef TIME_DECODE
AutoTimeMillis atm("JPEG Decode");
#endif
@ -215,11 +213,7 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm,
/* default format is RGB */
cinfo.out_color_space = JCS_RGB;
SkBitmap::Config config = prefConfig;
// if no user preference, see what the device recommends
if (config == SkBitmap::kNo_Config)
config = SkImageDecoder::GetDeviceConfig();
SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
// only these make sense for jpegs
if (config != SkBitmap::kARGB_8888_Config &&
config != SkBitmap::kARGB_4444_Config &&

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

@ -37,8 +37,7 @@ public:
}
protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config pref, Mode);
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
};
#ifndef png_jmpbuf
@ -110,9 +109,9 @@ static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) {
return reallyHasAlpha;
}
static bool canUpscalePaletteToConfig(SkBitmap::Config prefConfig,
static bool canUpscalePaletteToConfig(SkBitmap::Config dstConfig,
bool srcHasAlpha) {
switch (prefConfig) {
switch (dstConfig) {
case SkBitmap::kARGB_8888_Config:
case SkBitmap::kARGB_4444_Config:
return true;
@ -137,7 +136,7 @@ static bool hasTransparencyInPalette(png_structp png_ptr, png_infop info_ptr) {
}
bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
SkBitmap::Config prefConfig, Mode mode) {
Mode mode) {
// SkAutoTrace apr("SkPNGImageDecoder::onDecode");
/* Create and initialize the png_struct with the desired error handler
@ -233,11 +232,11 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
}
if (color_type == PNG_COLOR_TYPE_PALETTE) {
config = SkBitmap::kIndex8_Config;
// now see if we can upscale to their requested config
bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr);
if (canUpscalePaletteToConfig(prefConfig, paletteHasAlpha)) {
config = prefConfig;
config = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha);
// now see if we can upscale to their requested config
if (!canUpscalePaletteToConfig(config, paletteHasAlpha)) {
config = SkBitmap::kIndex8_Config;
}
} else {
png_color_16p transpColor = NULL;
@ -278,12 +277,14 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
PNG_COLOR_TYPE_RGB_ALPHA == color_type ||
PNG_COLOR_TYPE_GRAY_ALPHA == color_type) {
hasAlpha = true;
config = SkBitmap::kARGB_8888_Config;
} else { // we get to choose the config
config = prefConfig;
if (config == SkBitmap::kNo_Config) {
config = SkImageDecoder::GetDeviceConfig();
}
config = this->getPrefConfig(k32Bit_SrcDepth, hasAlpha);
// now match the request against our capabilities
if (hasAlpha) {
if (config != SkBitmap::kARGB_4444_Config) {
config = SkBitmap::kARGB_8888_Config;
}
} else {
if (config != SkBitmap::kRGB_565_Config &&
config != SkBitmap::kARGB_4444_Config) {
config = SkBitmap::kARGB_8888_Config;
@ -311,9 +312,6 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
const int sampleSize = this->getSampleSize();
SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
// we must always return the same config, independent of mode, so if we were
// going to respect prefConfig, it must have happened by now
decodedBitmap->setConfig(config, sampler.scaledWidth(),
sampler.scaledHeight(), 0);
if (SkImageDecoder::kDecodeBounds_Mode == mode) {

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

@ -29,8 +29,7 @@ public:
}
protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config pref, Mode);
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
};
static bool read_byte(SkStream* stream, uint8_t* data)
@ -107,7 +106,7 @@ static void expand_bits_to_bytes(uint8_t dst[], const uint8_t src[], int bits)
#define SkAlign8(x) (((x) + 7) & ~7)
bool SkWBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
SkBitmap::Config prefConfig, Mode mode)
Mode mode)
{
wbmp_head head;

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

@ -43,7 +43,7 @@ static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
if (num_bytes > src->bytes_in_buffer) {
if (num_bytes > (long)src->bytes_in_buffer) {
long bytesToSkip = num_bytes - src->bytes_in_buffer;
while (bytesToSkip > 0) {
long bytes = (long)src->fStream->skip(bytesToSkip);

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

@ -42,14 +42,12 @@ static CGImageSourceRef SkStreamToCGImageSource(SkStream* stream) {
class SkImageDecoder_CG : public SkImageDecoder {
protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config pref, Mode);
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
};
#define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast)
bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm,
SkBitmap::Config pref, Mode mode) {
bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);
if (NULL == imageSrc) {