aboutsummaryrefslogtreecommitdiffstats
path: root/src/images
diff options
context:
space:
mode:
Diffstat (limited to 'src/images')
-rw-r--r--src/images/SkImageDecoder.cpp47
-rw-r--r--src/images/SkImageDecoder_libbmp.cpp16
-rw-r--r--src/images/SkImageDecoder_libgif.cpp10
-rw-r--r--src/images/SkImageDecoder_libico.cpp6
-rw-r--r--src/images/SkImageDecoder_libjpeg.cpp238
-rw-r--r--src/images/SkImageDecoder_libpng.cpp34
-rw-r--r--src/images/SkImageDecoder_wbmp.cpp5
-rw-r--r--src/images/SkImageRef.cpp3
-rw-r--r--src/images/SkJpegUtility.cpp189
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);
+}