aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWei-Ta Chen <weita@google.com>2010-10-12 20:19:47 -0700
committerWei-Ta Chen <weita@google.com>2011-01-11 23:12:54 -0800
commitb4f070ed646ef1cbb92c3eaaa073640e30954873 (patch)
tree7912299e8965b19115d7c43a8b642c81471d266b
parent956f20cebc0d9c7a1c59dc18a556b7aaff22b39c (diff)
downloadskia-gingerbread.tar.gz
Backport changes/fixes related to tile-based decoder from Honeycomb to Gingerbread. Bug: 3309014 //////////////////////////////////////////////////////////////////// This is a combination of 3 commits. Fix 3071104, where decodeRegion returned false for some large image. decodeRegion() returns false when it cannot find a suitable color config for SkScaledBitmapSampler. Currently SkScaledBitmapSampler does not support RGB_565. If cinfo->out_color_space is set to RGB_565 and we require SkScaledBitmapSampler to do the extra sampling, we will fail in finding a suitable color config for SkScaledBitmapSampler. To fix it, we add support of RGB_565 into SkSclaedBitmapSampler. Change-Id: I506f4f8c55518ff356345e616e16c4b4cd0712de Fix 3117581, where BitmapRegionDecoder fails in building tile index for PNG files. The virtual method of building tile index in SkImageDecoder was changed to onBuildTileIndex(). SkPNGImageDecoder needs to override the method. Change-Id: I7c78844a4d4f7aadff5fa8fa1aa99173317139b2 Add fPreferQualityOverSpeed to SkImageDecoder. Currently the field only affects JPEG decode, in that when it is set to true, we choose a more accurate, but slightly slower, IDCT method. Bug: 3238925 /////////////////////////////////////////////////////////////////////
-rw-r--r--include/images/SkImageDecoder.h15
-rw-r--r--src/images/SkImageDecoder_libjpeg.cpp45
-rw-r--r--src/images/SkImageDecoder_libpng.cpp28
-rw-r--r--src/images/SkScaledBitmapSampler.cpp26
-rw-r--r--src/images/SkScaledBitmapSampler.h3
5 files changed, 70 insertions, 47 deletions
diff --git a/include/images/SkImageDecoder.h b/include/images/SkImageDecoder.h
index 3bb287d49e..3c904ca3b4 100644
--- a/include/images/SkImageDecoder.h
+++ b/include/images/SkImageDecoder.h
@@ -75,6 +75,20 @@ public:
*/
void setDitherImage(bool dither) { fDitherImage = dither; }
+ /** Returns true if the decoder should try to decode the
+ resulting image to a higher quality even at the expense of
+ the decoding speed.
+ */
+ bool getPreferQualityOverSpeed() const { return fPreferQualityOverSpeed; }
+
+ /** Set to true if the the decoder should try to decode the
+ resulting image to a higher quality even at the expense of
+ the decoding speed.
+ */
+ void setPreferQualityOverSpeed(bool qualityOverSpeed) {
+ fPreferQualityOverSpeed = qualityOverSpeed;
+ }
+
/** \class Peeker
Base class for optional callbacks to retrieve meta/chunk data out of
@@ -389,6 +403,7 @@ private:
bool fDitherImage;
bool fUsePrefTable;
mutable bool fShouldCancelDecode;
+ bool fPreferQualityOverSpeed;
// illegal
SkImageDecoder(const SkImageDecoder&);
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index e3aefeabf3..7e425c1d3c 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -236,7 +236,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;
@@ -264,13 +269,9 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
if (config == SkBitmap::kARGB_8888_Config) {
cinfo.out_color_space = JCS_RGBA_8888;
} else if (config == SkBitmap::kRGB_565_Config) {
- if (sampleSize == 1) {
- // SkScaledBitmapSampler can't handle RGB_565 yet,
- // so don't even try.
- cinfo.out_color_space = JCS_RGB_565;
- if (this->getDitherImage()) {
- cinfo.dither_mode = JDITHER_ORDERED;
- }
+ cinfo.out_color_space = JCS_RGB_565;
+ if (this->getDitherImage()) {
+ cinfo.dither_mode = JDITHER_ORDERED;
}
}
#endif
@@ -360,8 +361,8 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
#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;
+ } 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) {
@@ -468,7 +469,6 @@ bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream,
index->index = (huffman_index*)malloc(sizeof(huffman_index));
jpeg_create_huffman_index(cinfo, index->index);
- cinfo->dct_method = JDCT_IFAST;
cinfo->scale_num = 1;
cinfo->scale_denom = 1;
if (!jpeg_build_huffman_index(cinfo, index->index)) {
@@ -497,7 +497,6 @@ bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream,
//jpeg_start_decompress(cinfo);
jpeg_start_tile_decompress(cinfo);
- cinfo->dct_method = JDCT_IFAST;
cinfo->scale_num = 1;
index->cinfo = cinfo;
*height = cinfo->output_height;
@@ -526,24 +525,30 @@ bool SkJPEGImageDecoder::onDecodeRegion(SkBitmap* bm, SkIRect region) {
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 (config == SkBitmap::kARGB_8888_Config) {
cinfo->out_color_space = JCS_RGBA_8888;
} else if (config == SkBitmap::kRGB_565_Config) {
- if (requestedSampleSize == 1) {
- // SkScaledBitmapSampler can't handle RGB_565 yet,
- // so don't even try.
- cinfo->out_color_space = JCS_RGB_565;
- if (this->getDitherImage()) {
- cinfo->dither_mode = JDITHER_ORDERED;
- }
+ cinfo->out_color_space = JCS_RGB_565;
+ if (this->getDitherImage()) {
+ cinfo->dither_mode = JDITHER_ORDERED;
}
}
#endif
@@ -606,6 +611,8 @@ bool SkJPEGImageDecoder::onDecodeRegion(SkBitmap* bm, SkIRect region) {
#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) {
diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp
index 2b6a28e555..cd240b44e0 100644
--- a/src/images/SkImageDecoder_libpng.cpp
+++ b/src/images/SkImageDecoder_libpng.cpp
@@ -62,10 +62,10 @@ public:
delete index;
}
}
- virtual bool buildTileIndex(SkStream *stream,
- int *width, int *height, bool isShareable);
protected:
+ virtual bool onBuildTileIndex(SkStream *stream,
+ int *width, int *height);
virtual bool onDecodeRegion(SkBitmap* bitmap, SkIRect rect);
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
@@ -419,33 +419,13 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
return true;
}
-bool SkPNGImageDecoder::buildTileIndex(SkStream* sk_stream,
- int *width, int *height, bool isShareable) {
+bool SkPNGImageDecoder::onBuildTileIndex(SkStream* sk_stream, int *width,
+ int *height) {
png_structp png_ptr;
png_infop info_ptr;
this->index = new SkPNGImageIndex();
- if (!isShareable) {
- size_t len, inputLen = 0;
- size_t bufferSize = 4096;
- void *tmp = sk_malloc_throw(bufferSize);
-
- while ((len = sk_stream->read((char*) tmp + inputLen,
- bufferSize - inputLen)) != 0) {
- inputLen += len;
- if (inputLen == bufferSize) {
- bufferSize *= 2;
- tmp = sk_realloc_throw(tmp, bufferSize);
- }
- }
- tmp = sk_realloc_throw(tmp, inputLen);
-
- SkMemoryStream *mem_stream = new SkMemoryStream(tmp, inputLen, true);
- this->index->inputStream = mem_stream;
- sk_stream = mem_stream;
- }
-
if (onDecodeInit(sk_stream, &png_ptr, &info_ptr) == false) {
return false;
}
diff --git a/src/images/SkScaledBitmapSampler.cpp b/src/images/SkScaledBitmapSampler.cpp
index 3ba38f7b16..32b78efcc9 100644
--- a/src/images/SkScaledBitmapSampler.cpp
+++ b/src/images/SkScaledBitmapSampler.cpp
@@ -93,6 +93,18 @@ static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
return false;
}
+static bool Sample_D565_D565(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int, const SkPMColor[]) {
+ uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
+ uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src;
+ for (int x = 0; x < width; x++) {
+ dst[x] = castedSrc[0];
+ castedSrc += deltaSrc >> 1;
+ }
+ return false;
+}
+
static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
const uint8_t* SK_RESTRICT src,
int width, int deltaSrc, int y, const SkPMColor[]) {
@@ -335,21 +347,25 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
Sample_RGBx_D8888, Sample_RGBx_D8888,
Sample_RGBA_D8888, Sample_RGBA_D8888,
Sample_Index_D8888, Sample_Index_D8888,
+ NULL, NULL,
// 565 (no alpha distinction)
Sample_Gray_D565, Sample_Gray_D565_D,
Sample_RGBx_D565, Sample_RGBx_D565_D,
Sample_RGBx_D565, Sample_RGBx_D565_D,
Sample_Index_D565, Sample_Index_D565_D,
+ Sample_D565_D565, Sample_D565_D565,
// 4444
Sample_Gray_D4444, Sample_Gray_D4444_D,
Sample_RGBx_D4444, Sample_RGBx_D4444_D,
Sample_RGBA_D4444, Sample_RGBA_D4444_D,
Sample_Index_D4444, Sample_Index_D4444_D,
+ NULL, NULL,
// Index8
NULL, NULL,
NULL, NULL,
NULL, NULL,
Sample_Index_DI, Sample_Index_DI,
+ NULL, NULL,
};
fCTable = ctable;
@@ -379,6 +395,10 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
fSrcPixelSize = 1;
index += 6;
break;
+ case SkScaledBitmapSampler::kRGB_565:
+ fSrcPixelSize = 2;
+ index += 8;
+ break;
default:
return false;
}
@@ -388,13 +408,13 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
index += 0;
break;
case SkBitmap::kRGB_565_Config:
- index += 8;
+ index += 10;
break;
case SkBitmap::kARGB_4444_Config:
- index += 16;
+ index += 20;
break;
case SkBitmap::kIndex8_Config:
- index += 24;
+ index += 30;
break;
default:
return false;
diff --git a/src/images/SkScaledBitmapSampler.h b/src/images/SkScaledBitmapSampler.h
index 84a75ba544..43f166946a 100644
--- a/src/images/SkScaledBitmapSampler.h
+++ b/src/images/SkScaledBitmapSampler.h
@@ -21,7 +21,8 @@ public:
kIndex, // 1 byte per pixel
kRGB, // 3 bytes per pixel
kRGBX, // 4 byes per pixel (ignore 4th)
- kRGBA // 4 bytes per pixel
+ kRGBA, // 4 bytes per pixel
+ kRGB_565 // 2 bytes per pixel
};
// Given a dst bitmap (with pixels already allocated) and a src-config,