diff options
-rw-r--r-- | include/core/SkFontHost.h | 4 | ||||
-rw-r--r-- | include/images/SkImageDecoder.h | 51 | ||||
-rw-r--r-- | src/images/SkImageDecoder.cpp | 47 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libbmp.cpp | 16 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libgif.cpp | 6 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libico.cpp | 6 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libjpeg.cpp | 12 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libpng.cpp | 34 | ||||
-rw-r--r-- | src/images/SkImageDecoder_wbmp.cpp | 5 | ||||
-rw-r--r-- | src/images/SkJpegUtility.cpp | 2 | ||||
-rw-r--r-- | src/ports/SkImageDecoder_CG.cpp | 6 |
11 files changed, 131 insertions, 58 deletions
diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h index d706e4e802..ec345839ad 100644 --- a/include/core/SkFontHost.h +++ b/include/core/SkFontHost.h @@ -254,7 +254,7 @@ public: 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 @@ public: 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 de63345922..f8a941fdf6 100644 --- a/include/images/SkImageDecoder.h +++ b/include/images/SkImageDecoder.h @@ -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 diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp index 4711f89d7f..768d671d6a 100644 --- a/src/images/SkImageDecoder.cpp +++ b/src/images/SkImageDecoder.cpp @@ -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); diff --git a/src/images/SkImageDecoder_libbmp.cpp b/src/images/SkImageDecoder_libbmp.cpp index a4dcbf6174..30bfbdb7ca 100644 --- a/src/images/SkImageDecoder_libbmp.cpp +++ b/src/images/SkImageDecoder_libbmp.cpp @@ -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()); diff --git a/src/images/SkImageDecoder_libgif.cpp b/src/images/SkImageDecoder_libgif.cpp index 258a8a017d..d2470ccf1d 100644 --- a/src/images/SkImageDecoder_libgif.cpp +++ b/src/images/SkImageDecoder_libgif.cpp @@ -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"); diff --git a/src/images/SkImageDecoder_libico.cpp b/src/images/SkImageDecoder_libico.cpp index 9f21e13256..ef5b7ac976 100644 --- a/src/images/SkImageDecoder_libico.cpp +++ b/src/images/SkImageDecoder_libico.cpp @@ -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); diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp index 476cfa13a1..a64efbc4ac 100644 --- a/src/images/SkImageDecoder_libjpeg.cpp +++ b/src/images/SkImageDecoder_libjpeg.cpp @@ -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 && diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp index 6df56b4b8f..3548fc8393 100644 --- a/src/images/SkImageDecoder_libpng.cpp +++ b/src/images/SkImageDecoder_libpng.cpp @@ -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,14 +277,16 @@ 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_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) { diff --git a/src/images/SkImageDecoder_wbmp.cpp b/src/images/SkImageDecoder_wbmp.cpp index ac242ea22f..6d63ca93eb 100644 --- a/src/images/SkImageDecoder_wbmp.cpp +++ b/src/images/SkImageDecoder_wbmp.cpp @@ -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; diff --git a/src/images/SkJpegUtility.cpp b/src/images/SkJpegUtility.cpp index fc4f358bc3..e207592974 100644 --- a/src/images/SkJpegUtility.cpp +++ b/src/images/SkJpegUtility.cpp @@ -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); diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp index ea865c80bc..e7a5528c94 100644 --- a/src/ports/SkImageDecoder_CG.cpp +++ b/src/ports/SkImageDecoder_CG.cpp @@ -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) { |