diff options
Diffstat (limited to 'src/images')
-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 | 10 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libico.cpp | 6 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libjpeg.cpp | 238 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libpng.cpp | 34 | ||||
-rw-r--r-- | src/images/SkImageDecoder_wbmp.cpp | 5 | ||||
-rw-r--r-- | src/images/SkImageRef.cpp | 3 | ||||
-rw-r--r-- | src/images/SkJpegUtility.cpp | 189 |
9 files changed, 283 insertions, 265 deletions
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 @@ 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 a4dcbf6..30bfbdb 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 4c22cbf..75a9ee0 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[] = { @@ -124,8 +123,8 @@ static const ColorMapObject* find_colormap(const GifFileType* gif) { return NULL; } // some sanity checks - if ((unsigned)cmap->ColorCount > 256 || - cmap->ColorCount != (1 << cmap->BitsPerPixel)) { + if (cmap && ((unsigned)cmap->ColorCount > 256 || + cmap->ColorCount != (1 << cmap->BitsPerPixel))) { cmap = NULL; } return cmap; @@ -159,8 +158,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 9f21e13..ef5b7ac 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 12fe76a..ed523bb 100644 --- a/src/images/SkImageDecoder_libjpeg.cpp +++ b/src/images/SkImageDecoder_libjpeg.cpp @@ -16,6 +16,7 @@ #include "SkImageDecoder.h" #include "SkImageEncoder.h" +#include "SkJpegUtility.h" #include "SkColorPriv.h" #include "SkDither.h" #include "SkScaledBitmapSampler.h" @@ -54,8 +55,7 @@ public: } protected: - virtual bool onDecode(SkStream* stream, SkBitmap* bm, - SkBitmap::Config pref, Mode); + virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode); }; ////////////////////////////////////////////////////////////////////////// @@ -78,21 +78,6 @@ private: SkMSec fNow; }; -/* our source struct for directing jpeg to our stream object -*/ -struct sk_source_mgr : jpeg_source_mgr { - sk_source_mgr(SkStream* stream, SkImageDecoder* decoder); - - SkStream* fStream; - const void* fMemoryBase; - size_t fMemoryBaseSize; - SkImageDecoder* fDecoder; - enum { - kBufferSize = 1024 - }; - char fBuffer[kBufferSize]; -}; - /* Automatically clean up after throwing an exception */ class JPEGAutoClean { public: @@ -109,154 +94,19 @@ private: jpeg_decompress_struct* cinfo_ptr; }; -static void sk_init_source(j_decompress_ptr cinfo) { - sk_source_mgr* src = (sk_source_mgr*)cinfo->src; - src->next_input_byte = (const JOCTET*)src->fBuffer; - src->bytes_in_buffer = 0; -} - -static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) { - sk_source_mgr* src = (sk_source_mgr*)cinfo->src; - if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) { - return FALSE; - } - size_t bytes = src->fStream->read(src->fBuffer, sk_source_mgr::kBufferSize); - // note that JPEG is happy with less than the full read, - // as long as the result is non-zero - if (bytes == 0) { - return FALSE; - } - - src->next_input_byte = (const JOCTET*)src->fBuffer; - src->bytes_in_buffer = bytes; - return TRUE; -} - -static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { - SkASSERT(num_bytes > 0); - - sk_source_mgr* src = (sk_source_mgr*)cinfo->src; - - long bytesToSkip = num_bytes - src->bytes_in_buffer; - - // check if the skip amount exceeds the current buffer - if (bytesToSkip > 0) { - size_t bytes = src->fStream->skip(bytesToSkip); - if (bytes != (size_t)bytesToSkip) { -// SkDebugf("xxxxxxxxxxxxxx failure to skip request %d actual %d\n", bytesToSkip, bytes); - cinfo->err->error_exit((j_common_ptr)cinfo); - } - src->next_input_byte = (const JOCTET*)src->fBuffer; - src->bytes_in_buffer = 0; - } else { - src->next_input_byte += num_bytes; - src->bytes_in_buffer -= num_bytes; - } -} - -static boolean sk_resync_to_restart(j_decompress_ptr cinfo, int desired) { - sk_source_mgr* src = (sk_source_mgr*)cinfo->src; - - // what is the desired param for??? - - if (!src->fStream->rewind()) { - SkDebugf("xxxxxxxxxxxxxx failure to rewind\n"); - cinfo->err->error_exit((j_common_ptr)cinfo); - return FALSE; - } - src->next_input_byte = (const JOCTET*)src->fBuffer; - src->bytes_in_buffer = 0; - return TRUE; -} - -static void sk_term_source(j_decompress_ptr /*cinfo*/) {} - -/////////////////////////////////////////////////////////////////////////////// - -static void skmem_init_source(j_decompress_ptr cinfo) { - sk_source_mgr* src = (sk_source_mgr*)cinfo->src; - src->next_input_byte = (const JOCTET*)src->fMemoryBase; - src->bytes_in_buffer = src->fMemoryBaseSize; -} - -static boolean skmem_fill_input_buffer(j_decompress_ptr cinfo) { - SkDebugf("xxxxxxxxxxxxxx skmem_fill_input_buffer called\n"); - return FALSE; -} - -static void skmem_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { - sk_source_mgr* src = (sk_source_mgr*)cinfo->src; -// SkDebugf("xxxxxxxxxxxxxx skmem_skip_input_data called %d\n", num_bytes); - src->next_input_byte = (const JOCTET*)((const char*)src->next_input_byte + num_bytes); - src->bytes_in_buffer -= num_bytes; -} - -static boolean skmem_resync_to_restart(j_decompress_ptr cinfo, int desired) { - SkDebugf("xxxxxxxxxxxxxx skmem_resync_to_restart called\n"); - return TRUE; -} - -static void skmem_term_source(j_decompress_ptr /*cinfo*/) {} - #ifdef ANDROID /* Check if the memory cap property is set. If so, use the memory size for jpeg decode. */ static void overwrite_mem_buffer_size(j_decompress_ptr cinfo) { - int len = 0; - char value[PROPERTY_VALUE_MAX]; - int memCap; - - len = property_get(KEY_MEM_CAP, value, ""); - if (len > 0 && sscanf(value, "%d", &memCap) == 1) { - cinfo->mem->max_memory_to_use = memCap; - } -} +#ifdef ANDROID_LARGE_MEMORY_DEVICE + cinfo->mem->max_memory_to_use = 30 * 1024 * 1024; +#else + cinfo->mem->max_memory_to_use = 5 * 1024 * 1024; #endif - -/////////////////////////////////////////////////////////////////////////////// - -sk_source_mgr::sk_source_mgr(SkStream* stream, SkImageDecoder* decoder) : fStream(stream) { - fDecoder = decoder; - const void* baseAddr = stream->getMemoryBase(); - if (baseAddr && false) { - fMemoryBase = baseAddr; - fMemoryBaseSize = stream->getLength(); - - init_source = skmem_init_source; - fill_input_buffer = skmem_fill_input_buffer; - skip_input_data = skmem_skip_input_data; - resync_to_restart = skmem_resync_to_restart; - term_source = skmem_term_source; - } else { - fMemoryBase = NULL; - fMemoryBaseSize = 0; - - init_source = sk_init_source; - fill_input_buffer = sk_fill_input_buffer; - skip_input_data = sk_skip_input_data; - resync_to_restart = sk_resync_to_restart; - term_source = sk_term_source; - } -// SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize); } +#endif -#include <setjmp.h> - -struct sk_error_mgr : jpeg_error_mgr { - jmp_buf fJmpBuf; -}; - -static void sk_error_exit(j_common_ptr cinfo) { - sk_error_mgr* error = (sk_error_mgr*)cinfo->err; - - (*error->output_message) (cinfo); - - /* Let the memory manager delete any temp files before we die */ - jpeg_destroy(cinfo); - - longjmp(error->fJmpBuf, -1); -} /////////////////////////////////////////////////////////////////////////////// @@ -303,8 +153,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 @@ -313,11 +162,11 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, JPEGAutoClean autoClean; jpeg_decompress_struct cinfo; - sk_error_mgr sk_err; - sk_source_mgr sk_stream(stream, this); + skjpeg_error_mgr sk_err; + skjpeg_source_mgr sk_stream(stream, this); cinfo.err = jpeg_std_error(&sk_err); - sk_err.error_exit = sk_error_exit; + sk_err.error_exit = skjpeg_error_exit; // All objects need to be instantiated before this setjmp call so that // they will be cleaned up properly if an error occurs. @@ -361,11 +210,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 && @@ -709,58 +554,6 @@ static WriteScanline ChooseWriter(const SkBitmap& bm) { } } -struct sk_destination_mgr : jpeg_destination_mgr { - sk_destination_mgr(SkWStream* stream); - - SkWStream* fStream; - - enum { - kBufferSize = 1024 - }; - uint8_t fBuffer[kBufferSize]; -}; - -static void sk_init_destination(j_compress_ptr cinfo) { - sk_destination_mgr* dest = (sk_destination_mgr*)cinfo->dest; - - dest->next_output_byte = dest->fBuffer; - dest->free_in_buffer = sk_destination_mgr::kBufferSize; -} - -static boolean sk_empty_output_buffer(j_compress_ptr cinfo) { - sk_destination_mgr* dest = (sk_destination_mgr*)cinfo->dest; - -// if (!dest->fStream->write(dest->fBuffer, sk_destination_mgr::kBufferSize - dest->free_in_buffer)) - if (!dest->fStream->write(dest->fBuffer, sk_destination_mgr::kBufferSize)) { - ERREXIT(cinfo, JERR_FILE_WRITE); - return false; - } - - dest->next_output_byte = dest->fBuffer; - dest->free_in_buffer = sk_destination_mgr::kBufferSize; - return TRUE; -} - -static void sk_term_destination (j_compress_ptr cinfo) { - sk_destination_mgr* dest = (sk_destination_mgr*)cinfo->dest; - - size_t size = sk_destination_mgr::kBufferSize - dest->free_in_buffer; - if (size > 0) { - if (!dest->fStream->write(dest->fBuffer, size)) { - ERREXIT(cinfo, JERR_FILE_WRITE); - return; - } - } - dest->fStream->flush(); -} - -sk_destination_mgr::sk_destination_mgr(SkWStream* stream) - : fStream(stream) { - this->init_destination = sk_init_destination; - this->empty_output_buffer = sk_empty_output_buffer; - this->term_destination = sk_term_destination; -} - class SkJPEGImageEncoder : public SkImageEncoder { protected: virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { @@ -779,15 +572,15 @@ protected: } jpeg_compress_struct cinfo; - sk_error_mgr sk_err; - sk_destination_mgr sk_wstream(stream); + skjpeg_error_mgr sk_err; + skjpeg_destination_mgr sk_wstream(stream); // allocate these before set call setjmp SkAutoMalloc oneRow; SkAutoLockColors ctLocker; cinfo.err = jpeg_std_error(&sk_err); - sk_err.error_exit = sk_error_exit; + sk_err.error_exit = skjpeg_error_exit; if (setjmp(sk_err.fJmpBuf)) { return false; } @@ -858,4 +651,3 @@ static SkImageEncoder* EFactory(SkImageEncoder::Type t) { static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory); static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(EFactory); - 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 @@ 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 ac242ea..6d63ca9 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/SkImageRef.cpp b/src/images/SkImageRef.cpp index 3756d4e..60e01c6 100644 --- a/src/images/SkImageRef.cpp +++ b/src/images/SkImageRef.cpp @@ -6,6 +6,8 @@ #include "SkTemplates.h" #include "SkThread.h" +//#define DUMP_IMAGEREF_LIFECYCLE + // can't be static, as SkImageRef_Pool needs to see it SkMutex gImageRefMutex; @@ -161,6 +163,7 @@ SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer) fConfig = (SkBitmap::Config)buffer.readU8(); fSampleSize = buffer.readU8(); fDoDither = buffer.readBool(); + size_t length = buffer.readU32(); fStream = SkNEW_ARGS(SkMemoryStream, (length)); buffer.read((void*)fStream->getMemoryBase(), length); diff --git a/src/images/SkJpegUtility.cpp b/src/images/SkJpegUtility.cpp new file mode 100644 index 0000000..e207592 --- /dev/null +++ b/src/images/SkJpegUtility.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SkJpegUtility.h" + +///////////////////////////////////////////////////////////////////// +static void sk_init_source(j_decompress_ptr cinfo) { + skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; + src->next_input_byte = (const JOCTET*)src->fBuffer; + src->bytes_in_buffer = 0; +} + +static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) { + skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; + if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) { + return FALSE; + } + size_t bytes = src->fStream->read(src->fBuffer, skjpeg_source_mgr::kBufferSize); + // note that JPEG is happy with less than the full read, + // as long as the result is non-zero + if (bytes == 0) { + return FALSE; + } + + src->next_input_byte = (const JOCTET*)src->fBuffer; + src->bytes_in_buffer = bytes; + return TRUE; +} + +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 > (long)src->bytes_in_buffer) { + long bytesToSkip = num_bytes - src->bytes_in_buffer; + while (bytesToSkip > 0) { + long bytes = (long)src->fStream->skip(bytesToSkip); + if (bytes <= 0 || bytes > bytesToSkip) { +// SkDebugf("xxxxxxxxxxxxxx failure to skip request %d returned %d\n", bytesToSkip, bytes); + cinfo->err->error_exit((j_common_ptr)cinfo); + return; + } + bytesToSkip -= bytes; + } + src->next_input_byte = (const JOCTET*)src->fBuffer; + src->bytes_in_buffer = 0; + } else { + src->next_input_byte += num_bytes; + src->bytes_in_buffer -= num_bytes; + } +} + +static boolean sk_resync_to_restart(j_decompress_ptr cinfo, int desired) { + skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; + + // what is the desired param for??? + + if (!src->fStream->rewind()) { + SkDebugf("xxxxxxxxxxxxxx failure to rewind\n"); + cinfo->err->error_exit((j_common_ptr)cinfo); + return FALSE; + } + src->next_input_byte = (const JOCTET*)src->fBuffer; + src->bytes_in_buffer = 0; + return TRUE; +} + +static void sk_term_source(j_decompress_ptr /*cinfo*/) {} + + +static void skmem_init_source(j_decompress_ptr cinfo) { + skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; + src->next_input_byte = (const JOCTET*)src->fMemoryBase; + src->bytes_in_buffer = src->fMemoryBaseSize; +} + +static boolean skmem_fill_input_buffer(j_decompress_ptr cinfo) { + SkDebugf("xxxxxxxxxxxxxx skmem_fill_input_buffer called\n"); + return FALSE; +} + +static void skmem_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { + skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src; +// SkDebugf("xxxxxxxxxxxxxx skmem_skip_input_data called %d\n", num_bytes); + src->next_input_byte = (const JOCTET*)((const char*)src->next_input_byte + num_bytes); + src->bytes_in_buffer -= num_bytes; +} + +static boolean skmem_resync_to_restart(j_decompress_ptr cinfo, int desired) { + SkDebugf("xxxxxxxxxxxxxx skmem_resync_to_restart called\n"); + return TRUE; +} + +static void skmem_term_source(j_decompress_ptr /*cinfo*/) {} + + +/////////////////////////////////////////////////////////////////////////////// + +skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder) : fStream(stream) { + fDecoder = decoder; + const void* baseAddr = stream->getMemoryBase(); + if (baseAddr && false) { + fMemoryBase = baseAddr; + fMemoryBaseSize = stream->getLength(); + + init_source = skmem_init_source; + fill_input_buffer = skmem_fill_input_buffer; + skip_input_data = skmem_skip_input_data; + resync_to_restart = skmem_resync_to_restart; + term_source = skmem_term_source; + } else { + fMemoryBase = NULL; + fMemoryBaseSize = 0; + + init_source = sk_init_source; + fill_input_buffer = sk_fill_input_buffer; + skip_input_data = sk_skip_input_data; + resync_to_restart = sk_resync_to_restart; + term_source = sk_term_source; + } +// SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize); +} + +/////////////////////////////////////////////////////////////////////////////// + +static void sk_init_destination(j_compress_ptr cinfo) { + skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; + + dest->next_output_byte = dest->fBuffer; + dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize; +} + +static boolean sk_empty_output_buffer(j_compress_ptr cinfo) { + skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; + +// if (!dest->fStream->write(dest->fBuffer, skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer)) + if (!dest->fStream->write(dest->fBuffer, + skjpeg_destination_mgr::kBufferSize)) { + ERREXIT(cinfo, JERR_FILE_WRITE); + return false; + } + + dest->next_output_byte = dest->fBuffer; + dest->free_in_buffer = skjpeg_destination_mgr::kBufferSize; + return TRUE; +} + +static void sk_term_destination (j_compress_ptr cinfo) { + skjpeg_destination_mgr* dest = (skjpeg_destination_mgr*)cinfo->dest; + + size_t size = skjpeg_destination_mgr::kBufferSize - dest->free_in_buffer; + if (size > 0) { + if (!dest->fStream->write(dest->fBuffer, size)) { + ERREXIT(cinfo, JERR_FILE_WRITE); + return; + } + } + dest->fStream->flush(); +} + +skjpeg_destination_mgr::skjpeg_destination_mgr(SkWStream* stream) + : fStream(stream) { + this->init_destination = sk_init_destination; + this->empty_output_buffer = sk_empty_output_buffer; + this->term_destination = sk_term_destination; +} + +void skjpeg_error_exit(j_common_ptr cinfo) { + skjpeg_error_mgr* error = (skjpeg_error_mgr*)cinfo->err; + + (*error->output_message) (cinfo); + + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); + + longjmp(error->fJmpBuf, -1); +} |