aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/images/SkImageDecoder.cpp43
-rw-r--r--src/images/SkImageDecoder_libjpeg.cpp41
-rw-r--r--src/images/SkImageDecoder_libpng.cpp23
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) */