diff options
-rw-r--r-- | src/images/SkImageDecoder.cpp | 43 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libjpeg.cpp | 41 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libpng.cpp | 23 |
3 files changed, 82 insertions, 25 deletions
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp index de0afbb..23dec76 100644 --- a/src/images/SkImageDecoder.cpp +++ b/src/images/SkImageDecoder.cpp @@ -171,19 +171,14 @@ bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, bool SkImageDecoder::decodeRegion(SkBitmap* bm, SkIRect rect, SkBitmap::Config pref) { - // pass a temporary bitmap, so that if we return false, we are assured of - // leaving the caller's bitmap untouched. - SkBitmap tmp; - // we reset this to false before calling onDecodeRegion fShouldCancelDecode = false; // assign this, for use by getPrefConfig(), in case fUsePrefTable is false fDefaultPref = pref; - if (!this->onDecodeRegion(&tmp, rect)) { + if (!this->onDecodeRegion(bm, rect)) { return false; } - bm->swap(tmp); return true; } @@ -201,24 +196,40 @@ void SkImageDecoder::cropBitmap(SkBitmap *dest, SkBitmap *src, int w = width / sampleSize; int h = height / sampleSize; if (w == src->width() && h == src->height() && - (srcX - destX) / sampleSize == 0 && (srcY - destY) / sampleSize == 0) { + (srcX - destX) / sampleSize == 0 && + (srcY - destY) / sampleSize == 0 && + dest->isNull() + ) { // The output rect is the same as the decode result dest->swap(*src); return; } - dest->setConfig(src->getConfig(), w, h); - dest->setIsOpaque(src->isOpaque()); - if (!this->allocPixelRef(dest, NULL)) { -#ifdef SK_DEBUG - SkDebugf("failed to allocate pixels needed to crop the bitmap"); -#endif - return; + // if the destination has no pixels then we must allocate them. + if (dest->isNull()) { + // The output rect is smaller than the decode result + dest->setConfig(src->getConfig(), w, h); + dest->setIsOpaque(src->isOpaque()); + + if (!this->allocPixelRef(dest, NULL)) { + SkDEBUGF(("failed to allocate pixels needed to crop the bitmap")); + return; + } } + // 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(dest->width() >= w && dest->height() >= h); + + // Set the Src_Mode for the paint to prevent transparency issue in the + // dest in the event that the dest was being re-used. + SkPaint paint; + paint.setXfermodeMode(SkXfermode::kSrc_Mode); SkCanvas canvas(*dest); - canvas.drawBitmap(*src, (srcX - destX) / sampleSize, - (srcY - destY) / sampleSize); + canvas.drawSprite(*src, (srcX - destX) / sampleSize, + (srcY - destY) / sampleSize, + &paint); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp index 8d87450..b191848 100644 --- a/src/images/SkImageDecoder_libjpeg.cpp +++ b/src/images/SkImageDecoder_libjpeg.cpp @@ -604,9 +604,27 @@ bool SkJPEGImageDecoder::onDecodeRegion(SkBitmap* bm, SkIRect region) { { bitmap->setConfig(config, cinfo->output_width, height); bitmap->setIsOpaque(true); - if (!this->allocPixelRef(bitmap, NULL)) { - return return_false(*cinfo, *bitmap, "allocPixelRef"); + // Check ahead of time if the swap(dest, src) is possible in crop 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 = oriWidth / actualSampleSize; + int h = oriHeight / actualSampleSize; + if (w == bitmap->width() && h == bitmap->height() && + (startX - oriStartX) / actualSampleSize == 0 && + (startY - oriStartY) / actualSampleSize == 0 && bm->isNull()) { + // Not using a recycled-bitmap and the output rect is same as the + // decoded region. + if (!this->allocPixelRef(bitmap, NULL)) { + return return_false(*cinfo, *bitmap, "allocPixelRef"); + } } + else { + if (!bitmap->allocPixels()) { + return return_false(*cinfo, *bitmap, "allocPixels"); + } + } + SkAutoLockPixels alp(*bitmap); JSAMPLE* rowptr = (JSAMPLE*)bitmap->getPixels(); INT32 const bpr = bitmap->rowBytes(); @@ -653,8 +671,23 @@ bool SkJPEGImageDecoder::onDecodeRegion(SkBitmap* bm, SkIRect region) { bitmap->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); bitmap->setIsOpaque(true); - if (!this->allocPixelRef(bitmap, NULL)) { - return return_false(*cinfo, *bitmap, "allocPixelRef"); + // Check ahead of time if the swap(dest, src) is possible in crop 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 = oriWidth / actualSampleSize; + int h = oriHeight / actualSampleSize; + if (w == bitmap->width() && h == bitmap->height() && + (startX - oriStartX) / actualSampleSize == 0 && + (startY - oriStartY) / actualSampleSize == 0 && bm->isNull()) { + if (!this->allocPixelRef(bitmap, NULL)) { + return return_false(*cinfo, *bitmap, "allocPixelRef"); + } + } + else { + if (!bitmap->allocPixels()) { + return return_false(*cinfo, *bitmap, "allocPixels"); + } } SkAutoLockPixels alp(*bitmap); diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp index 138c28c..bb31806 100644 --- a/src/images/SkImageDecoder_libpng.cpp +++ b/src/images/SkImageDecoder_libpng.cpp @@ -666,12 +666,25 @@ bool SkPNGImageDecoder::onDecodeRegion(SkBitmap* bm, SkIRect rect) { SkAutoUnref aur(colorTable); - if (!this->allocPixelRef(decodedBitmap, - SkBitmap::kIndex8_Config == config ? - colorTable : NULL)) { - return false; + // Check ahead of time if the swap(dest, src) is possible in crop 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 = requestedWidth / sampleSize; + int h = requestedHeight / sampleSize; + if (w == decodedBitmap->width() && h == decodedBitmap->height() && + (0 - rect.fLeft / sampleSize) == 0 && (rect.fTop - rect.fTop) / sampleSize == 0 && + bm->isNull()) { + if (!this->allocPixelRef(decodedBitmap, + SkBitmap::kIndex8_Config == config ? colorTable : NULL)) { + return false; + } + } + else { + if (!decodedBitmap->allocPixels( + NULL, SkBitmap::kIndex8_Config == config ? colorTable : NULL)) { + return false; + } } - SkAutoLockPixels alp(*decodedBitmap); /* Add filler (or alpha) byte (before/after each RGB triplet) */ |