diff options
author | scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-05-03 20:14:28 +0000 |
---|---|---|
committer | scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-05-03 20:14:28 +0000 |
commit | 7e6fceeffd250d99eff9f1dbb459a916ae4a754e (patch) | |
tree | 12bd9ee920cd58a8a31b9aff4abde0429a95a372 /src | |
parent | dc9cdf8d49ecfe174c408845b7f2de6f5a756b1d (diff) |
Test region decoding in skimage, plus fixes.
Add tests in skimage to perform region decoding. Write out a
PNG of the region as well as a bitmap obtained with extractSubset
for comparison.
Rename decodeRegion to decodeSubset, so it will not be confused
with SkRegion. (Leave a function called decodeRegion which calls
decodeSubset.)
Clean up some comments.
Use png_set_interlaced_pass instead of modifying pass directly.
Make some changes to region decoding to fix problems I discovered
during testing:
Only call getAddr within a valid range.
Check for a NULL fInputStream.
Return a boolean for whether cropBitmap succeeded.
In cropBitmap, do not attempt to draw to a bitmap to an Index8
bitmap, which crashes. Use extractSubset instead.
Remove an assert.
R=djsollen@google.com
Review URL: https://codereview.chromium.org/14567011
git-svn-id: http://skia.googlecode.com/svn/trunk@8996 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/images/SkImageDecoder.cpp | 44 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libjpeg.cpp | 4 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libpng.cpp | 25 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libwebp.cpp | 4 |
4 files changed, 51 insertions, 26 deletions
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp index de0bc14c90..9ffae5f0e7 100644 --- a/src/images/SkImageDecoder.cpp +++ b/src/images/SkImageDecoder.cpp @@ -33,9 +33,14 @@ void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config) /////////////////////////////////////////////////////////////////////////////// SkImageDecoder::SkImageDecoder() - : fPeeker(NULL), fChooser(NULL), fAllocator(NULL), fSampleSize(1), - fDefaultPref(SkBitmap::kNo_Config), fDitherImage(true), - fUsePrefTable(false),fPreferQualityOverSpeed(false) { + : fPeeker(NULL) + , fChooser(NULL) + , fAllocator(NULL) + , fSampleSize(1) + , fDefaultPref(SkBitmap::kNo_Config) + , fDitherImage(true) + , fUsePrefTable(false) + , fPreferQualityOverSpeed(false) { } SkImageDecoder::~SkImageDecoder() { @@ -177,14 +182,14 @@ bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, return true; } -bool SkImageDecoder::decodeRegion(SkBitmap* bm, const SkIRect& rect, +bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect, SkBitmap::Config pref) { - // we reset this to false before calling onDecodeRegion + // we reset this to false before calling onDecodeSubset fShouldCancelDecode = false; // assign this, for use by getPrefConfig(), in case fUsePrefTable is false fDefaultPref = pref; - return this->onDecodeRegion(bm, rect); + return this->onDecodeSubset(bm, rect); } bool SkImageDecoder::buildTileIndex(SkStream* stream, @@ -195,11 +200,25 @@ bool SkImageDecoder::buildTileIndex(SkStream* stream, return this->onBuildTileIndex(stream, width, height); } -void SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, - int dstX, int dstY, int width, int height, - int srcX, int srcY) { +bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, + int dstX, int dstY, int width, int height, + int srcX, int srcY) { int w = width / sampleSize; int h = height / sampleSize; + if (src->getConfig() == SkBitmap::kIndex8_Config) { + // kIndex8 does not allow drawing via an SkCanvas, as is done below. + // Instead, use extractSubset. Note that this shares the SkPixelRef and + // SkColorTable. + // FIXME: Since src is discarded in practice, this holds on to more + // pixels than is strictly necessary. Switch to a copy if memory + // savings are more important than speed here. This also means + // that the pixels in dst can not be reused (though there is no + // allocation, which was already done on src). + int x = (dstX - srcX) / sampleSize; + int y = (dstY - srcY) / sampleSize; + SkIRect subset = SkIRect::MakeXYWH(x, y, w, h); + return src->extractSubset(dst, subset); + } // if the destination has no pixels then we must allocate them. if (dst->isNull()) { dst->setConfig(src->getConfig(), w, h); @@ -207,13 +226,15 @@ void SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, if (!this->allocPixelRef(dst, NULL)) { SkDEBUGF(("failed to allocate pixels needed to crop the bitmap")); - return; + return false; } } // check to see if the destination is large enough to decode the desired // region. If this assert fails we will just draw as much of the source // into the destination that we can. - SkASSERT(dst->width() >= w && dst->height() >= h); + if (dst->width() < w || dst->height() < h) { + SkDEBUGF(("SkImageDecoder::cropBitmap does not have a large enough bitmap.\n")); + } // Set the Src_Mode for the paint to prevent transparency issue in the // dest in the event that the dest was being re-used. @@ -224,6 +245,7 @@ void SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, canvas.drawSprite(*src, (srcX - dstX) / sampleSize, (srcY - dstY) / sampleSize, &paint); + return true; } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp index c55f4c4123..3ed3806543 100644 --- a/src/images/SkImageDecoder_libjpeg.cpp +++ b/src/images/SkImageDecoder_libjpeg.cpp @@ -118,7 +118,7 @@ public: protected: #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; + virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE; #endif virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; @@ -556,7 +556,7 @@ bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *hei return true; } -bool SkJPEGImageDecoder::onDecodeRegion(SkBitmap* bm, const SkIRect& region) { +bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { if (NULL == fImageIndex) { return false; } diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp index 0e02ccf08d..d967a69e84 100644 --- a/src/images/SkImageDecoder_libpng.cpp +++ b/src/images/SkImageDecoder_libpng.cpp @@ -72,7 +72,7 @@ public: protected: #ifdef SK_BUILD_FOR_ANDROID virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_OVERRIDE; - virtual bool onDecodeRegion(SkBitmap* bitmap, const SkIRect& region) SK_OVERRIDE; + virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) SK_OVERRIDE; #endif virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; @@ -642,7 +642,11 @@ bool SkPNGImageDecoder::onBuildTileIndex(SkStream* sk_stream, int *width, int *h return true; } -bool SkPNGImageDecoder::onDecodeRegion(SkBitmap* bm, const SkIRect& region) { +bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { + if (NULL == fImageIndex) { + return false; + } + png_structp png_ptr = fImageIndex->png_ptr; png_infop info_ptr = fImageIndex->info_ptr; if (setjmp(png_jmpbuf(png_ptr))) { @@ -657,7 +661,7 @@ bool SkPNGImageDecoder::onDecodeRegion(SkBitmap* bm, const SkIRect& region) { SkIRect rect = SkIRect::MakeWH(origWidth, origHeight); if (!rect.intersect(region)) { - // If the requested region is entirely outsides the image, just + // If the requested region is entirely outside the image, just // returns false return false; } @@ -731,8 +735,8 @@ bool SkPNGImageDecoder::onDecodeRegion(SkBitmap* bm, const SkIRect& region) { #if defined(PNG_1_0_X) || defined (PNG_1_2_X) png_ptr->pass = 0; #else - // FIXME: Figure out what (if anything) to do when Android moves to - // libpng > 1.2. + // FIXME: This sets pass as desired, but also sets iwidth. Is that ok? + png_set_interlaced_pass(png_ptr, 0); #endif png_read_update_info(png_ptr, info_ptr); @@ -745,7 +749,8 @@ bool SkPNGImageDecoder::onDecodeRegion(SkBitmap* bm, const SkIRect& region) { uint8_t* bmRow = decodedBitmap.getAddr8(0, 0); png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); } - for (png_uint_32 y = 0; y < origHeight; y++) { + png_uint_32 bitmapHeight = (png_uint_32) decodedBitmap.height(); + for (png_uint_32 y = 0; y < bitmapHeight; y++) { uint8_t* bmRow = decodedBitmap.getAddr8(0, y); png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); } @@ -826,12 +831,10 @@ bool SkPNGImageDecoder::onDecodeRegion(SkBitmap* bm, const SkIRect& region) { if (swapOnly) { bm->swap(decodedBitmap); - } else { - cropBitmap(bm, &decodedBitmap, sampleSize, region.x(), region.y(), - region.width(), region.height(), 0, rect.y()); + return true; } - - return true; + return this->cropBitmap(bm, &decodedBitmap, sampleSize, region.x(), region.y(), + region.width(), region.height(), 0, rect.y()); } #endif diff --git a/src/images/SkImageDecoder_libwebp.cpp b/src/images/SkImageDecoder_libwebp.cpp index a33d0f9b2f..e623f376d7 100644 --- a/src/images/SkImageDecoder_libwebp.cpp +++ b/src/images/SkImageDecoder_libwebp.cpp @@ -111,7 +111,7 @@ public: protected: virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_OVERRIDE; - virtual bool onDecodeRegion(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE; + virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE; virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; private: @@ -321,7 +321,7 @@ static bool is_config_compatible(const SkBitmap& bitmap) { config == SkBitmap::kARGB_8888_Config; } -bool SkWEBPImageDecoder::onDecodeRegion(SkBitmap* decodedBitmap, +bool SkWEBPImageDecoder::onDecodeSubset(SkBitmap* decodedBitmap, const SkIRect& region) { SkIRect rect = SkIRect::MakeWH(fOrigWidth, fOrigHeight); |