Upstream changes from Android for decoding jpeg images.
Review URL: https://codereview.chromium.org/12438025 git-svn-id: http://skia.googlecode.com/svn/trunk@8267 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
4d9853288b
commit
113994051b
217
gyp/libjpeg.gyp
217
gyp/libjpeg.gyp
@ -13,110 +13,127 @@
|
||||
'use_system_libjpeg%': 0,
|
||||
},
|
||||
'conditions': [
|
||||
['use_system_libjpeg==0', {
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'libjpeg',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'../third_party/externals/libjpeg/jcapimin.c',
|
||||
'../third_party/externals/libjpeg/jcapistd.c',
|
||||
'../third_party/externals/libjpeg/jccoefct.c',
|
||||
'../third_party/externals/libjpeg/jccolor.c',
|
||||
'../third_party/externals/libjpeg/jcdctmgr.c',
|
||||
'../third_party/externals/libjpeg/jchuff.c',
|
||||
'../third_party/externals/libjpeg/jchuff.h',
|
||||
'../third_party/externals/libjpeg/jcinit.c',
|
||||
'../third_party/externals/libjpeg/jcmainct.c',
|
||||
'../third_party/externals/libjpeg/jcmarker.c',
|
||||
'../third_party/externals/libjpeg/jcmaster.c',
|
||||
'../third_party/externals/libjpeg/jcomapi.c',
|
||||
'../third_party/externals/libjpeg/jconfig.h',
|
||||
'../third_party/externals/libjpeg/jcparam.c',
|
||||
'../third_party/externals/libjpeg/jcphuff.c',
|
||||
'../third_party/externals/libjpeg/jcprepct.c',
|
||||
'../third_party/externals/libjpeg/jcsample.c',
|
||||
'../third_party/externals/libjpeg/jdapimin.c',
|
||||
'../third_party/externals/libjpeg/jdapistd.c',
|
||||
'../third_party/externals/libjpeg/jdatadst.c',
|
||||
'../third_party/externals/libjpeg/jdatasrc.c',
|
||||
'../third_party/externals/libjpeg/jdcoefct.c',
|
||||
'../third_party/externals/libjpeg/jdcolor.c',
|
||||
'../third_party/externals/libjpeg/jdct.h',
|
||||
'../third_party/externals/libjpeg/jddctmgr.c',
|
||||
'../third_party/externals/libjpeg/jdhuff.c',
|
||||
'../third_party/externals/libjpeg/jdhuff.h',
|
||||
'../third_party/externals/libjpeg/jdinput.c',
|
||||
'../third_party/externals/libjpeg/jdmainct.c',
|
||||
'../third_party/externals/libjpeg/jdmarker.c',
|
||||
'../third_party/externals/libjpeg/jdmaster.c',
|
||||
'../third_party/externals/libjpeg/jdmerge.c',
|
||||
'../third_party/externals/libjpeg/jdphuff.c',
|
||||
'../third_party/externals/libjpeg/jdpostct.c',
|
||||
'../third_party/externals/libjpeg/jdsample.c',
|
||||
'../third_party/externals/libjpeg/jerror.c',
|
||||
'../third_party/externals/libjpeg/jerror.h',
|
||||
'../third_party/externals/libjpeg/jfdctflt.c',
|
||||
'../third_party/externals/libjpeg/jfdctfst.c',
|
||||
'../third_party/externals/libjpeg/jfdctint.c',
|
||||
'../third_party/externals/libjpeg/jidctflt.c',
|
||||
'../third_party/externals/libjpeg/jidctfst.c',
|
||||
'../third_party/externals/libjpeg/jidctint.c',
|
||||
'../third_party/externals/libjpeg/jinclude.h',
|
||||
'../third_party/externals/libjpeg/jmemmgr.c',
|
||||
'../third_party/externals/libjpeg/jmemnobs.c',
|
||||
'../third_party/externals/libjpeg/jmemsys.h',
|
||||
'../third_party/externals/libjpeg/jmorecfg.h',
|
||||
'../third_party/externals/libjpeg/jpegint.h',
|
||||
'../third_party/externals/libjpeg/jpeglib.h',
|
||||
'../third_party/externals/libjpeg/jquant1.c',
|
||||
'../third_party/externals/libjpeg/jquant2.c',
|
||||
'../third_party/externals/libjpeg/jutils.c',
|
||||
'../third_party/externals/libjpeg/jversion.h',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'../third_party/externals/libjpeg',
|
||||
],
|
||||
},
|
||||
'conditions': [
|
||||
['OS!="win"', {
|
||||
'product_name': 'jpeg',
|
||||
'cflags': [
|
||||
'-Wno-main', # supresses warnings about naming things "main"
|
||||
],
|
||||
}],
|
||||
['OS=="android"', {
|
||||
'cflags!': [
|
||||
'-fno-rtti', # supresses warnings about invalid option of non-C++ code
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
],
|
||||
}],
|
||||
['OS in ["linux", "freebsd", "openbsd", "solaris", "nacl"]', {
|
||||
'cflags!': [
|
||||
'-Werror',
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
],
|
||||
}, {
|
||||
['skia_os == "android"', {
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'libjpeg',
|
||||
'type': 'none',
|
||||
'direct_dependent_settings': {
|
||||
'defines': [
|
||||
'USE_SYSTEM_LIBJPEG',
|
||||
],
|
||||
},
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'-ljpeg',
|
||||
],
|
||||
},
|
||||
}
|
||||
'dependencies': [
|
||||
'android_deps.gyp:jpeg',
|
||||
],
|
||||
'export_dependent_settings': [
|
||||
'android_deps.gyp:jpeg',
|
||||
],
|
||||
},
|
||||
],
|
||||
}, { # skia_os != android
|
||||
'conditions': [
|
||||
['use_system_libjpeg==0', {
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'libjpeg',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'../third_party/externals/libjpeg/jcapimin.c',
|
||||
'../third_party/externals/libjpeg/jcapistd.c',
|
||||
'../third_party/externals/libjpeg/jccoefct.c',
|
||||
'../third_party/externals/libjpeg/jccolor.c',
|
||||
'../third_party/externals/libjpeg/jcdctmgr.c',
|
||||
'../third_party/externals/libjpeg/jchuff.c',
|
||||
'../third_party/externals/libjpeg/jchuff.h',
|
||||
'../third_party/externals/libjpeg/jcinit.c',
|
||||
'../third_party/externals/libjpeg/jcmainct.c',
|
||||
'../third_party/externals/libjpeg/jcmarker.c',
|
||||
'../third_party/externals/libjpeg/jcmaster.c',
|
||||
'../third_party/externals/libjpeg/jcomapi.c',
|
||||
'../third_party/externals/libjpeg/jconfig.h',
|
||||
'../third_party/externals/libjpeg/jcparam.c',
|
||||
'../third_party/externals/libjpeg/jcphuff.c',
|
||||
'../third_party/externals/libjpeg/jcprepct.c',
|
||||
'../third_party/externals/libjpeg/jcsample.c',
|
||||
'../third_party/externals/libjpeg/jdapimin.c',
|
||||
'../third_party/externals/libjpeg/jdapistd.c',
|
||||
'../third_party/externals/libjpeg/jdatadst.c',
|
||||
'../third_party/externals/libjpeg/jdatasrc.c',
|
||||
'../third_party/externals/libjpeg/jdcoefct.c',
|
||||
'../third_party/externals/libjpeg/jdcolor.c',
|
||||
'../third_party/externals/libjpeg/jdct.h',
|
||||
'../third_party/externals/libjpeg/jddctmgr.c',
|
||||
'../third_party/externals/libjpeg/jdhuff.c',
|
||||
'../third_party/externals/libjpeg/jdhuff.h',
|
||||
'../third_party/externals/libjpeg/jdinput.c',
|
||||
'../third_party/externals/libjpeg/jdmainct.c',
|
||||
'../third_party/externals/libjpeg/jdmarker.c',
|
||||
'../third_party/externals/libjpeg/jdmaster.c',
|
||||
'../third_party/externals/libjpeg/jdmerge.c',
|
||||
'../third_party/externals/libjpeg/jdphuff.c',
|
||||
'../third_party/externals/libjpeg/jdpostct.c',
|
||||
'../third_party/externals/libjpeg/jdsample.c',
|
||||
'../third_party/externals/libjpeg/jerror.c',
|
||||
'../third_party/externals/libjpeg/jerror.h',
|
||||
'../third_party/externals/libjpeg/jfdctflt.c',
|
||||
'../third_party/externals/libjpeg/jfdctfst.c',
|
||||
'../third_party/externals/libjpeg/jfdctint.c',
|
||||
'../third_party/externals/libjpeg/jidctflt.c',
|
||||
'../third_party/externals/libjpeg/jidctfst.c',
|
||||
'../third_party/externals/libjpeg/jidctint.c',
|
||||
'../third_party/externals/libjpeg/jinclude.h',
|
||||
'../third_party/externals/libjpeg/jmemmgr.c',
|
||||
'../third_party/externals/libjpeg/jmemnobs.c',
|
||||
'../third_party/externals/libjpeg/jmemsys.h',
|
||||
'../third_party/externals/libjpeg/jmorecfg.h',
|
||||
'../third_party/externals/libjpeg/jpegint.h',
|
||||
'../third_party/externals/libjpeg/jpeglib.h',
|
||||
'../third_party/externals/libjpeg/jquant1.c',
|
||||
'../third_party/externals/libjpeg/jquant2.c',
|
||||
'../third_party/externals/libjpeg/jutils.c',
|
||||
'../third_party/externals/libjpeg/jversion.h',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'../third_party/externals/libjpeg',
|
||||
],
|
||||
},
|
||||
'conditions': [
|
||||
['OS!="win"', {
|
||||
'product_name': 'jpeg',
|
||||
'cflags': [
|
||||
'-Wno-main', # supresses warnings about naming things "main"
|
||||
],
|
||||
}],
|
||||
['OS=="android"', {
|
||||
'cflags!': [
|
||||
'-fno-rtti', # supresses warnings about invalid option of non-C++ code
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
],
|
||||
}],
|
||||
['OS in ["linux", "freebsd", "openbsd", "solaris", "nacl"]', {
|
||||
'cflags!': [
|
||||
'-Werror',
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
],
|
||||
}, {
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'libjpeg',
|
||||
'type': 'none',
|
||||
'direct_dependent_settings': {
|
||||
'defines': [
|
||||
'USE_SYSTEM_LIBJPEG',
|
||||
],
|
||||
},
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'-ljpeg',
|
||||
],
|
||||
},
|
||||
}
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
@ -15,7 +15,10 @@
|
||||
#include "SkScaledBitmapSampler.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkTemplates.h"
|
||||
#include "SkTime.h"
|
||||
#include "SkUtils.h"
|
||||
#include "SkRect.h"
|
||||
#include "SkCanvas.h"
|
||||
|
||||
#include <stdio.h>
|
||||
extern "C" {
|
||||
@ -23,7 +26,13 @@ extern "C" {
|
||||
#include "jerror.h"
|
||||
}
|
||||
|
||||
// this enables timing code to report milliseconds for an encode
|
||||
// Uncomment to enable the code path used by the Android framework with their
|
||||
// custom image decoders.
|
||||
//#if defined(SK_BUILD_FOR_ANDROID) && defined(SK_DEBUG)
|
||||
// #define SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
//#endif
|
||||
|
||||
// These enable timing code that report milliseconds for an encoding/decoding
|
||||
//#define TIME_ENCODE
|
||||
//#define TIME_DECODE
|
||||
|
||||
@ -31,39 +40,98 @@ extern "C" {
|
||||
// disable for the moment, as we have some glitches when width != multiple of 4
|
||||
#define WE_CONVERT_TO_YUV
|
||||
|
||||
// If ANDROID_RGB is defined by in the jpeg headers it indicates that jpeg offers
|
||||
// support for two additional formats (1) JCS_RGBA_8888 and (2) JCS_RGB_565.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void overwrite_mem_buffer_size(j_decompress_ptr cinfo) {
|
||||
#ifdef SK_BUILD_FOR_ANDROID
|
||||
/* Check if the device indicates that it has a large amount of system memory
|
||||
* if so, increase the memory allocation to 30MB instead of the default 5MB.
|
||||
*/
|
||||
#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
|
||||
#endif // SK_BUILD_FOR_ANDROID
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SkJPEGImageIndex {
|
||||
public:
|
||||
SkJPEGImageIndex(SkStream* stream, SkImageDecoder* decoder)
|
||||
: fSrcMgr(stream, decoder, true) {}
|
||||
|
||||
~SkJPEGImageIndex() {
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
jpeg_destroy_huffman_index(&fHuffmanIndex);
|
||||
#endif
|
||||
jpeg_finish_decompress(&fCInfo);
|
||||
jpeg_destroy_decompress(&fCInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the cinfo struct using libjpeg and apply any necessary
|
||||
* customizations.
|
||||
*/
|
||||
void initializeInfo() {
|
||||
jpeg_create_decompress(&fCInfo);
|
||||
overwrite_mem_buffer_size(&fCInfo);
|
||||
fCInfo.src = &fSrcMgr;
|
||||
}
|
||||
|
||||
jpeg_decompress_struct* cinfo() { return &fCInfo; }
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
huffman_index* huffmanIndex() { return &fHuffmanIndex; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
skjpeg_source_mgr fSrcMgr;
|
||||
jpeg_decompress_struct fCInfo;
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
huffman_index fHuffmanIndex;
|
||||
#endif
|
||||
};
|
||||
|
||||
class SkJPEGImageDecoder : public SkImageDecoder {
|
||||
public:
|
||||
SkJPEGImageDecoder() {
|
||||
fImageIndex = NULL;
|
||||
fImageWidth = 0;
|
||||
fImageHeight = 0;
|
||||
}
|
||||
|
||||
virtual ~SkJPEGImageDecoder() {
|
||||
SkDELETE(fImageIndex);
|
||||
}
|
||||
|
||||
virtual Format getFormat() const {
|
||||
return kJPEG_Format;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_OVERRIDE;
|
||||
virtual bool onDecodeRegion(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE;
|
||||
#endif
|
||||
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
SkJPEGImageIndex* fImageIndex;
|
||||
int fImageWidth;
|
||||
int fImageHeight;
|
||||
|
||||
typedef SkImageDecoder INHERITED;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SkTime.h"
|
||||
|
||||
class AutoTimeMillis {
|
||||
public:
|
||||
AutoTimeMillis(const char label[]) : fLabel(label) {
|
||||
if (!fLabel) {
|
||||
fLabel = "";
|
||||
}
|
||||
fNow = SkTime::GetMSecs();
|
||||
}
|
||||
~AutoTimeMillis() {
|
||||
SkDebugf("---- Time (ms): %s %d\n", fLabel, SkTime::GetMSecs() - fNow);
|
||||
}
|
||||
private:
|
||||
const char* fLabel;
|
||||
SkMSec fNow;
|
||||
};
|
||||
|
||||
/* Automatically clean up after throwing an exception */
|
||||
class JPEGAutoClean {
|
||||
public:
|
||||
@ -80,24 +148,6 @@ private:
|
||||
jpeg_decompress_struct* cinfo_ptr;
|
||||
};
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID
|
||||
|
||||
/* For non-ndk builds we could look at the system's jpeg memory cap and use it
|
||||
* if it is set. However, for now we will use the NDK compliant hardcoded values
|
||||
*/
|
||||
//#include <cutils/properties.h>
|
||||
//static const char KEY_MEM_CAP[] = "ro.media.dec.jpeg.memcap";
|
||||
|
||||
static void overwrite_mem_buffer_size(j_decompress_ptr cinfo) {
|
||||
#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
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* If we need to better match the request, we might examine the image and
|
||||
@ -116,26 +166,39 @@ static bool valid_output_dimensions(const jpeg_decompress_struct& cinfo) {
|
||||
/* These are initialized to 0, so if they have non-zero values, we assume
|
||||
they are "valid" (i.e. have been computed by libjpeg)
|
||||
*/
|
||||
return cinfo.output_width != 0 && cinfo.output_height != 0;
|
||||
return 0 != cinfo.output_width && 0 != cinfo.output_height;
|
||||
}
|
||||
|
||||
static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer,
|
||||
int count) {
|
||||
static bool skip_src_rows(jpeg_decompress_struct* cinfo, void* buffer, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
JSAMPLE* rowptr = (JSAMPLE*)buffer;
|
||||
int row_count = jpeg_read_scanlines(cinfo, &rowptr, 1);
|
||||
if (row_count != 1) {
|
||||
if (1 != row_count) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
static bool skip_src_rows_tile(jpeg_decompress_struct* cinfo,
|
||||
huffman_index *index, void* buffer, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
JSAMPLE* rowptr = (JSAMPLE*)buffer;
|
||||
int row_count = jpeg_read_tile_scanline(cinfo, index, &rowptr);
|
||||
if (1 != row_count) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// This guy exists just to aid in debugging, as it allows debuggers to just
|
||||
// set a break-point in one place to see all error exists.
|
||||
static bool return_false(const jpeg_decompress_struct& cinfo,
|
||||
const SkBitmap& bm, const char msg[]) {
|
||||
#if 0
|
||||
#ifdef SK_DEBUG
|
||||
SkDebugf("libjpeg error %d <%s> from %s [%d %d]", cinfo.err->msg_code,
|
||||
cinfo.err->jpeg_message_table[cinfo.err->msg_code], msg,
|
||||
bm.width(), bm.height());
|
||||
@ -168,34 +231,31 @@ static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
|
||||
|
||||
bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
||||
#ifdef TIME_DECODE
|
||||
AutoTimeMillis atm("JPEG Decode");
|
||||
SkAutoTime atm("JPEG Decode");
|
||||
#endif
|
||||
|
||||
SkAutoMalloc srcStorage;
|
||||
JPEGAutoClean autoClean;
|
||||
|
||||
jpeg_decompress_struct cinfo;
|
||||
skjpeg_error_mgr sk_err;
|
||||
skjpeg_source_mgr sk_stream(stream, this, false);
|
||||
skjpeg_error_mgr errorManager;
|
||||
skjpeg_source_mgr srcManager(stream, this, false);
|
||||
|
||||
cinfo.err = jpeg_std_error(&sk_err);
|
||||
sk_err.error_exit = skjpeg_error_exit;
|
||||
cinfo.err = jpeg_std_error(&errorManager);
|
||||
errorManager.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.
|
||||
if (setjmp(sk_err.fJmpBuf)) {
|
||||
if (setjmp(errorManager.fJmpBuf)) {
|
||||
return return_false(cinfo, *bm, "setjmp");
|
||||
}
|
||||
|
||||
jpeg_create_decompress(&cinfo);
|
||||
autoClean.set(&cinfo);
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID
|
||||
overwrite_mem_buffer_size(&cinfo);
|
||||
#endif
|
||||
|
||||
//jpeg_stdio_src(&cinfo, file);
|
||||
cinfo.src = &sk_stream;
|
||||
cinfo.src = &srcManager;
|
||||
|
||||
int status = jpeg_read_header(&cinfo, true);
|
||||
if (status != JPEG_HEADER_OK) {
|
||||
@ -208,7 +268,12 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
||||
*/
|
||||
int sampleSize = this->getSampleSize();
|
||||
|
||||
cinfo.dct_method = JDCT_IFAST;
|
||||
if (this->getPreferQualityOverSpeed()) {
|
||||
cinfo.dct_method = JDCT_ISLOW;
|
||||
} else {
|
||||
cinfo.dct_method = JDCT_IFAST;
|
||||
}
|
||||
|
||||
cinfo.scale_num = 1;
|
||||
cinfo.scale_denom = sampleSize;
|
||||
|
||||
@ -250,7 +315,7 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sampleSize == 1 && mode == SkImageDecoder::kDecodeBounds_Mode) {
|
||||
if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) {
|
||||
bm->setConfig(config, cinfo.image_width, cinfo.image_height);
|
||||
bm->setIsOpaque(true);
|
||||
return true;
|
||||
@ -270,8 +335,7 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
||||
to complete the setup. However, output dimensions seem to get
|
||||
computed very early, which is why this special check can pay off.
|
||||
*/
|
||||
if (SkImageDecoder::kDecodeBounds_Mode == mode &&
|
||||
valid_output_dimensions(cinfo)) {
|
||||
if (SkImageDecoder::kDecodeBounds_Mode == mode && valid_output_dimensions(cinfo)) {
|
||||
SkScaledBitmapSampler smpl(cinfo.output_width, cinfo.output_height,
|
||||
recompute_sampleSize(sampleSize, cinfo));
|
||||
bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight());
|
||||
@ -284,11 +348,38 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
||||
sampleSize = recompute_sampleSize(sampleSize, cinfo);
|
||||
|
||||
// should we allow the Chooser (if present) to pick a config for us???
|
||||
if (!this->chooseFromOneChoice(config, cinfo.output_width,
|
||||
cinfo.output_height)) {
|
||||
if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_height)) {
|
||||
return return_false(cinfo, *bm, "chooseFromOneChoice");
|
||||
}
|
||||
|
||||
SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize);
|
||||
|
||||
bm->lockPixels();
|
||||
JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
|
||||
bm->unlockPixels();
|
||||
bool reuseBitmap = (rowptr != NULL);
|
||||
|
||||
if (reuseBitmap) {
|
||||
if (sampler.scaledWidth() != bm->width() ||
|
||||
sampler.scaledHeight() != bm->height()) {
|
||||
// Dimensions must match
|
||||
return false;
|
||||
} else if (SkImageDecoder::kDecodeBounds_Mode == mode) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
|
||||
bm->setIsOpaque(true);
|
||||
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
|
||||
return true;
|
||||
}
|
||||
if (!this->allocPixelRef(bm, NULL)) {
|
||||
return return_false(cinfo, *bm, "allocPixelRef");
|
||||
}
|
||||
}
|
||||
|
||||
SkAutoLockPixels alp(*bm);
|
||||
|
||||
#ifdef ANDROID_RGB
|
||||
/* short-circuit the SkScaledBitmapSampler when possible, as this gives
|
||||
a significant performance boost.
|
||||
@ -299,16 +390,7 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
||||
(config == SkBitmap::kRGB_565_Config &&
|
||||
cinfo.out_color_space == JCS_RGB_565)))
|
||||
{
|
||||
bm->setConfig(config, cinfo.output_width, cinfo.output_height);
|
||||
bm->setIsOpaque(true);
|
||||
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
|
||||
return true;
|
||||
}
|
||||
if (!this->allocPixelRef(bm, NULL)) {
|
||||
return return_false(cinfo, *bm, "allocPixelRef");
|
||||
}
|
||||
SkAutoLockPixels alp(*bm);
|
||||
JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
|
||||
rowptr = (JSAMPLE*)bm->getPixels();
|
||||
INT32 const bpr = bm->rowBytes();
|
||||
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
@ -323,6 +405,9 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
||||
}
|
||||
rowptr += bpr;
|
||||
}
|
||||
if (reuseBitmap) {
|
||||
bm->notifyPixelsChanged();
|
||||
}
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
return true;
|
||||
}
|
||||
@ -348,27 +433,13 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
||||
return return_false(cinfo, *bm, "jpeg colorspace");
|
||||
}
|
||||
|
||||
SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height,
|
||||
sampleSize);
|
||||
|
||||
bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
|
||||
// jpegs are always opaque (i.e. have no per-pixel alpha)
|
||||
bm->setIsOpaque(true);
|
||||
|
||||
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
|
||||
return true;
|
||||
}
|
||||
if (!this->allocPixelRef(bm, NULL)) {
|
||||
return return_false(cinfo, *bm, "allocPixelRef");
|
||||
}
|
||||
|
||||
SkAutoLockPixels alp(*bm);
|
||||
if (!sampler.begin(bm, sc, this->getDitherImage())) {
|
||||
return return_false(cinfo, *bm, "sampler.begin");
|
||||
}
|
||||
|
||||
// The CMYK work-around relies on 4 components per pixel here
|
||||
uint8_t* srcRow = (uint8_t*)srcStorage.reset(cinfo.output_width * 4);
|
||||
SkAutoMalloc srcStorage(cinfo.output_width * 4);
|
||||
uint8_t* srcRow = (uint8_t*)srcStorage.get();
|
||||
|
||||
// Possibly skip initial rows [sampler.srcY0]
|
||||
if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
|
||||
@ -406,12 +477,279 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
||||
cinfo.output_height - cinfo.output_scanline)) {
|
||||
return return_false(cinfo, *bm, "skip rows");
|
||||
}
|
||||
if (reuseBitmap) {
|
||||
bm->notifyPixelsChanged();
|
||||
}
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
// SkDebugf("------------------- bm2 size %d [%d %d] %d\n", bm->getSize(), bm->width(), bm->height(), bm->config());
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *height) {
|
||||
|
||||
SkJPEGImageIndex* imageIndex = SkNEW_ARGS(SkJPEGImageIndex, (stream, this));
|
||||
jpeg_decompress_struct* cinfo = imageIndex->cinfo();
|
||||
huffman_index* huffmanIndex = imageIndex->huffmanIndex();
|
||||
|
||||
skjpeg_error_mgr sk_err;
|
||||
cinfo->err = jpeg_std_error(&sk_err);
|
||||
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.
|
||||
if (setjmp(sk_err.fJmpBuf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// create the cinfo used to create/build the huffmanIndex
|
||||
imageIndex->initializeInfo();
|
||||
cinfo->do_fancy_upsampling = 0;
|
||||
cinfo->do_block_smoothing = 0;
|
||||
|
||||
int status = jpeg_read_header(cinfo, true);
|
||||
if (JPEG_HEADER_OK != status) {
|
||||
SkDELETE(imageIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
jpeg_create_huffman_index(cinfo, huffmanIndex);
|
||||
cinfo->scale_num = 1;
|
||||
cinfo->scale_denom = 1;
|
||||
if (!jpeg_build_huffman_index(cinfo, huffmanIndex)) {
|
||||
SkDELETE(imageIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
// destroy the cinfo used to create/build the huffman index
|
||||
jpeg_destroy_decompress(cinfo);
|
||||
|
||||
// Init decoder to image decode mode
|
||||
imageIndex->initializeInfo();
|
||||
|
||||
status = jpeg_read_header(cinfo, true);
|
||||
if (JPEG_HEADER_OK != status) {
|
||||
SkDELETE(imageIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
cinfo->out_color_space = JCS_RGBA_8888;
|
||||
cinfo->do_fancy_upsampling = 0;
|
||||
cinfo->do_block_smoothing = 0;
|
||||
|
||||
// instead of jpeg_start_decompress() we start a tiled decompress
|
||||
jpeg_start_tile_decompress(cinfo);
|
||||
|
||||
cinfo->scale_num = 1;
|
||||
*height = cinfo->output_height;
|
||||
*width = cinfo->output_width;
|
||||
fImageWidth = *width;
|
||||
fImageHeight = *height;
|
||||
|
||||
SkDELETE(fImageIndex);
|
||||
fImageIndex = imageIndex;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkJPEGImageDecoder::onDecodeRegion(SkBitmap* bm, const SkIRect& region) {
|
||||
if (NULL == fImageIndex) {
|
||||
return false;
|
||||
}
|
||||
jpeg_decompress_struct* cinfo = fImageIndex->cinfo();
|
||||
|
||||
SkIRect rect = SkIRect::MakeWH(fImageWidth, fImageHeight);
|
||||
if (!rect.intersect(region)) {
|
||||
// If the requested region is entirely outside the image return false
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
skjpeg_error_mgr errorManager;
|
||||
cinfo->err = jpeg_std_error(&errorManager);
|
||||
errorManager.error_exit = skjpeg_error_exit;
|
||||
if (setjmp(errorManager.fJmpBuf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int requestedSampleSize = this->getSampleSize();
|
||||
cinfo->scale_denom = requestedSampleSize;
|
||||
|
||||
if (this->getPreferQualityOverSpeed()) {
|
||||
cinfo->dct_method = JDCT_ISLOW;
|
||||
} else {
|
||||
cinfo->dct_method = JDCT_IFAST;
|
||||
}
|
||||
|
||||
SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
|
||||
if (config != SkBitmap::kARGB_8888_Config &&
|
||||
config != SkBitmap::kARGB_4444_Config &&
|
||||
config != SkBitmap::kRGB_565_Config) {
|
||||
config = SkBitmap::kARGB_8888_Config;
|
||||
}
|
||||
|
||||
/* default format is RGB */
|
||||
cinfo->out_color_space = JCS_RGB;
|
||||
|
||||
#ifdef ANDROID_RGB
|
||||
cinfo->dither_mode = JDITHER_NONE;
|
||||
if (SkBitmap::kARGB_8888_Config == config) {
|
||||
cinfo->out_color_space = JCS_RGBA_8888;
|
||||
} else if (SkBitmap::kRGB_565_Config == config) {
|
||||
cinfo->out_color_space = JCS_RGB_565;
|
||||
if (this->getDitherImage()) {
|
||||
cinfo->dither_mode = JDITHER_ORDERED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int startX = rect.fLeft;
|
||||
int startY = rect.fTop;
|
||||
int width = rect.width();
|
||||
int height = rect.height();
|
||||
|
||||
jpeg_init_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(),
|
||||
&startX, &startY, &width, &height);
|
||||
int skiaSampleSize = recompute_sampleSize(requestedSampleSize, *cinfo);
|
||||
int actualSampleSize = skiaSampleSize * (DCTSIZE / cinfo->min_DCT_scaled_size);
|
||||
|
||||
SkScaledBitmapSampler sampler(width, height, skiaSampleSize);
|
||||
|
||||
SkBitmap bitmap;
|
||||
bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
|
||||
bitmap.setIsOpaque(true);
|
||||
|
||||
// Check ahead of time if the swap(dest, src) is possible or not.
|
||||
// If yes, then we will stick to AllocPixelRef since it's cheaper with the
|
||||
// swap happening. If no, then we will use alloc to allocate pixels to
|
||||
// prevent garbage collection.
|
||||
int w = rect.width() / actualSampleSize;
|
||||
int h = rect.height() / actualSampleSize;
|
||||
bool swapOnly = (rect == region) && bm->isNull() &&
|
||||
(w == bitmap.width()) && (h == bitmap.height()) &&
|
||||
((startX - rect.x()) / actualSampleSize == 0) &&
|
||||
((startY - rect.y()) / actualSampleSize == 0);
|
||||
if (swapOnly) {
|
||||
if (!this->allocPixelRef(&bitmap, NULL)) {
|
||||
return return_false(*cinfo, bitmap, "allocPixelRef");
|
||||
}
|
||||
} else {
|
||||
if (!bitmap.allocPixels()) {
|
||||
return return_false(*cinfo, bitmap, "allocPixels");
|
||||
}
|
||||
}
|
||||
|
||||
SkAutoLockPixels alp(bitmap);
|
||||
|
||||
#ifdef ANDROID_RGB
|
||||
/* short-circuit the SkScaledBitmapSampler when possible, as this gives
|
||||
a significant performance boost.
|
||||
*/
|
||||
if (skiaSampleSize == 1 &&
|
||||
((config == SkBitmap::kARGB_8888_Config &&
|
||||
cinfo->out_color_space == JCS_RGBA_8888) ||
|
||||
(config == SkBitmap::kRGB_565_Config &&
|
||||
cinfo->out_color_space == JCS_RGB_565)))
|
||||
{
|
||||
JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels();
|
||||
INT32 const bpr = bitmap.rowBytes();
|
||||
int rowTotalCount = 0;
|
||||
|
||||
while (rowTotalCount < height) {
|
||||
int rowCount = jpeg_read_tile_scanline(cinfo,
|
||||
fImageIndex->huffmanIndex(),
|
||||
&rowptr);
|
||||
// if row_count == 0, then we didn't get a scanline, so abort.
|
||||
// if we supported partial images, we might return true in this case
|
||||
if (0 == rowCount) {
|
||||
return return_false(*cinfo, bitmap, "read_scanlines");
|
||||
}
|
||||
if (this->shouldCancelDecode()) {
|
||||
return return_false(*cinfo, bitmap, "shouldCancelDecode");
|
||||
}
|
||||
rowTotalCount += rowCount;
|
||||
rowptr += bpr;
|
||||
}
|
||||
|
||||
if (swapOnly) {
|
||||
bm->swap(bitmap);
|
||||
} else {
|
||||
cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
|
||||
region.width(), region.height(), startX, startY);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// check for supported formats
|
||||
SkScaledBitmapSampler::SrcConfig sc;
|
||||
if (JCS_CMYK == cinfo->out_color_space) {
|
||||
// In this case we will manually convert the CMYK values to RGB
|
||||
sc = SkScaledBitmapSampler::kRGBX;
|
||||
} else if (3 == cinfo->out_color_components && JCS_RGB == cinfo->out_color_space) {
|
||||
sc = SkScaledBitmapSampler::kRGB;
|
||||
#ifdef ANDROID_RGB
|
||||
} else if (JCS_RGBA_8888 == cinfo->out_color_space) {
|
||||
sc = SkScaledBitmapSampler::kRGBX;
|
||||
} else if (JCS_RGB_565 == cinfo->out_color_space) {
|
||||
sc = SkScaledBitmapSampler::kRGB_565;
|
||||
#endif
|
||||
} else if (1 == cinfo->out_color_components &&
|
||||
JCS_GRAYSCALE == cinfo->out_color_space) {
|
||||
sc = SkScaledBitmapSampler::kGray;
|
||||
} else {
|
||||
return return_false(*cinfo, *bm, "jpeg colorspace");
|
||||
}
|
||||
|
||||
if (!sampler.begin(&bitmap, sc, this->getDitherImage())) {
|
||||
return return_false(*cinfo, bitmap, "sampler.begin");
|
||||
}
|
||||
|
||||
// The CMYK work-around relies on 4 components per pixel here
|
||||
SkAutoMalloc srcStorage(width * 4);
|
||||
uint8_t* srcRow = (uint8_t*)srcStorage.get();
|
||||
|
||||
// Possibly skip initial rows [sampler.srcY0]
|
||||
if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow, sampler.srcY0())) {
|
||||
return return_false(*cinfo, bitmap, "skip rows");
|
||||
}
|
||||
|
||||
// now loop through scanlines until y == bitmap->height() - 1
|
||||
for (int y = 0;; y++) {
|
||||
JSAMPLE* rowptr = (JSAMPLE*)srcRow;
|
||||
int row_count = jpeg_read_tile_scanline(cinfo, fImageIndex->huffmanIndex(), &rowptr);
|
||||
if (0 == row_count) {
|
||||
return return_false(*cinfo, bitmap, "read_scanlines");
|
||||
}
|
||||
if (this->shouldCancelDecode()) {
|
||||
return return_false(*cinfo, bitmap, "shouldCancelDecode");
|
||||
}
|
||||
|
||||
if (JCS_CMYK == cinfo->out_color_space) {
|
||||
convert_CMYK_to_RGB(srcRow, width);
|
||||
}
|
||||
|
||||
sampler.next(srcRow);
|
||||
if (bitmap.height() - 1 == y) {
|
||||
// we're done
|
||||
break;
|
||||
}
|
||||
|
||||
if (!skip_src_rows_tile(cinfo, fImageIndex->huffmanIndex(), srcRow,
|
||||
sampler.srcDY() - 1)) {
|
||||
return return_false(*cinfo, bitmap, "skip rows");
|
||||
}
|
||||
}
|
||||
if (swapOnly) {
|
||||
bm->swap(bitmap);
|
||||
} else {
|
||||
cropBitmap(bm, &bitmap, actualSampleSize, region.x(), region.y(),
|
||||
region.width(), region.height(), startX, startY);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SkColorPriv.h"
|
||||
@ -582,7 +920,7 @@ class SkJPEGImageEncoder : public SkImageEncoder {
|
||||
protected:
|
||||
virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) {
|
||||
#ifdef TIME_ENCODE
|
||||
AutoTimeMillis atm("JPEG Encode");
|
||||
SkAutoTime atm("JPEG Encode");
|
||||
#endif
|
||||
|
||||
const WriteScanline writer = ChooseWriter(bm);
|
||||
|
@ -9,14 +9,41 @@
|
||||
|
||||
#include "SkJpegUtility.h"
|
||||
|
||||
// Uncomment to enable the code path used by the Android framework with their
|
||||
// custom image decoders.
|
||||
//#if defined(SK_BUILD_FOR_ANDROID) && defined(SK_DEBUG)
|
||||
// #define SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
//#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
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;
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
src->current_offset = 0;
|
||||
#endif
|
||||
src->fStream->rewind();
|
||||
}
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
static boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) {
|
||||
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
|
||||
|
||||
if (byte_offset > src->current_offset) {
|
||||
(void)src->fStream->skip(byte_offset - src->current_offset);
|
||||
} else {
|
||||
src->fStream->rewind();
|
||||
(void)src->fStream->skip(byte_offset);
|
||||
}
|
||||
|
||||
src->current_offset = byte_offset;
|
||||
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
||||
src->bytes_in_buffer = 0;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
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()) {
|
||||
@ -29,6 +56,9 @@ static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
src->current_offset += bytes;
|
||||
#endif
|
||||
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
||||
src->bytes_in_buffer = bytes;
|
||||
return TRUE;
|
||||
@ -46,6 +76,9 @@ static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
|
||||
cinfo->err->error_exit((j_common_ptr)cinfo);
|
||||
return;
|
||||
}
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
src->current_offset += bytes;
|
||||
#endif
|
||||
bytesToSkip -= bytes;
|
||||
}
|
||||
src->next_input_byte = (const JOCTET*)src->fBuffer;
|
||||
@ -74,40 +107,11 @@ static boolean sk_resync_to_restart(j_decompress_ptr cinfo, int desired) {
|
||||
static void sk_term_source(j_decompress_ptr /*cinfo*/) {}
|
||||
|
||||
|
||||
#if 0 // UNUSED
|
||||
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*/) {}
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder,
|
||||
bool ownStream) : fStream(stream) {
|
||||
fDecoder = decoder;
|
||||
// const void* baseAddr = stream->getMemoryBase();
|
||||
fMemoryBase = NULL;
|
||||
fUnrefStream = ownStream;
|
||||
fMemoryBaseSize = 0;
|
||||
@ -117,6 +121,9 @@ skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder,
|
||||
skip_input_data = sk_skip_input_data;
|
||||
resync_to_restart = sk_resync_to_restart;
|
||||
term_source = sk_term_source;
|
||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||
seek_input_data = sk_seek_input_data;
|
||||
#endif
|
||||
// SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user