add optional pref-config table to codecs
git-svn-id: http://skia.googlecode.com/svn/trunk@519 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h
index d706e4e..ec34583 100644
--- a/include/core/SkFontHost.h
+++ b/include/core/SkFontHost.h
@@ -254,7 +254,7 @@
Note, if you change this after startup, you'll need to flush the glyph
cache because it'll have the wrong type of masks cached.
-
+
kNONE_LCDOrder means that the subpixel elements are not spatially
separated in any usable fashion.
*/
@@ -263,7 +263,7 @@
kBGR_LCDOrder = 1,
kNONE_LCDOrder = 2,
};
-
+
static void SetSubpixelOrder(LCDOrder order);
static LCDOrder GetSubpixelOrder();
};
diff --git a/include/images/SkImageDecoder.h b/include/images/SkImageDecoder.h
index de63345..f8a941f 100644
--- a/include/images/SkImageDecoder.h
+++ b/include/images/SkImageDecoder.h
@@ -89,6 +89,33 @@
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 @@
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 @@
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 @@
*/
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
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp
index 4711f89..768d671 100644
--- a/src/images/SkImageDecoder.cpp
+++ b/src/images/SkImageDecoder.cpp
@@ -37,7 +37,8 @@
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 @@
///////////////////////////////////////////////////////////////////////////////
+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 @@
// 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);
diff --git a/src/images/SkImageDecoder_libbmp.cpp b/src/images/SkImageDecoder_libbmp.cpp
index a4dcbf6..30bfbdb 100644
--- a/src/images/SkImageDecoder_libbmp.cpp
+++ b/src/images/SkImageDecoder_libbmp.cpp
@@ -31,8 +31,7 @@
}
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 @@
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 @@
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());
diff --git a/src/images/SkImageDecoder_libgif.cpp b/src/images/SkImageDecoder_libgif.cpp
index 258a8a0..d2470cc 100644
--- a/src/images/SkImageDecoder_libgif.cpp
+++ b/src/images/SkImageDecoder_libgif.cpp
@@ -31,8 +31,7 @@
}
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 @@
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");
diff --git a/src/images/SkImageDecoder_libico.cpp b/src/images/SkImageDecoder_libico.cpp
index 9f21e13..ef5b7ac 100644
--- a/src/images/SkImageDecoder_libico.cpp
+++ b/src/images/SkImageDecoder_libico.cpp
@@ -29,8 +29,7 @@
}
protected:
- virtual bool onDecode(SkStream* stream, SkBitmap* bm,
- SkBitmap::Config pref, Mode);
+ virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
};
/////////////////////////////////////////////////////////////////////////////////////////
@@ -79,8 +78,7 @@
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);
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index 476cfa1..a64efbc 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -55,8 +55,7 @@
}
protected:
- virtual bool onDecode(SkStream* stream, SkBitmap* bm,
- SkBitmap::Config pref, Mode);
+ virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
};
//////////////////////////////////////////////////////////////////////////
@@ -157,8 +156,7 @@
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 @@
/* 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 &&
diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp
index 6df56b4..3548fc8 100644
--- a/src/images/SkImageDecoder_libpng.cpp
+++ b/src/images/SkImageDecoder_libpng.cpp
@@ -37,8 +37,7 @@
}
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 @@
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 @@
}
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 @@
}
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,14 +277,16 @@
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_4444_Config) {
config = SkBitmap::kARGB_8888_Config;
}
}
@@ -311,9 +312,6 @@
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) {
diff --git a/src/images/SkImageDecoder_wbmp.cpp b/src/images/SkImageDecoder_wbmp.cpp
index ac242ea..6d63ca9 100644
--- a/src/images/SkImageDecoder_wbmp.cpp
+++ b/src/images/SkImageDecoder_wbmp.cpp
@@ -29,8 +29,7 @@
}
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 @@
#define SkAlign8(x) (((x) + 7) & ~7)
bool SkWBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
- SkBitmap::Config prefConfig, Mode mode)
+ Mode mode)
{
wbmp_head head;
diff --git a/src/images/SkJpegUtility.cpp b/src/images/SkJpegUtility.cpp
index fc4f358..e207592 100644
--- a/src/images/SkJpegUtility.cpp
+++ b/src/images/SkJpegUtility.cpp
@@ -43,7 +43,7 @@
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);
diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp
index ea865c8..e7a5528 100644
--- a/src/ports/SkImageDecoder_CG.cpp
+++ b/src/ports/SkImageDecoder_CG.cpp
@@ -42,14 +42,12 @@
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) {