Index: tools/SkBitmapRegionCanvas.cpp |
diff --git a/tools/SkBitmapRegionCanvas.cpp b/tools/SkBitmapRegionCanvas.cpp |
index f9c9573c445c2c3e7a86704cbf09fd11c7fa611b..3b1a039a73e0666d41a89f1edbe71ff7e6472b16 100644 |
--- a/tools/SkBitmapRegionCanvas.cpp |
+++ b/tools/SkBitmapRegionCanvas.cpp |
@@ -15,125 +15,101 @@ SkBitmapRegionCanvas::SkBitmapRegionCanvas(SkCodec* decoder) |
, fDecoder(decoder) |
{} |
-/* |
- * Three differences from the Android version: |
- * Returns a Skia bitmap instead of an Android bitmap. |
- * Android version attempts to reuse a recycled bitmap. |
- * Removed the options object and used parameters for color type and |
- * sample size. |
- */ |
-SkBitmap* SkBitmapRegionCanvas::decodeRegion(int inputX, int inputY, |
- int inputWidth, int inputHeight, |
- int sampleSize, |
- SkColorType dstColorType) { |
+bool SkBitmapRegionCanvas::prepareRegion(const SkIRect& desiredSubset, |
+ int sampleSize, |
+ SkColorType dstColorType, |
+ bool requireUnpremul, |
+ SkImageInfo* outInfo) { |
// Reject color types not supported by this method |
if (kIndex_8_SkColorType == dstColorType || kGray_8_SkColorType == dstColorType) { |
scroggo
2015/10/27 15:00:50
Should we also check for requireUnpremul here? I s
|
SkCodecPrintf("Error: Color type not supported.\n"); |
- return nullptr; |
+ return false; |
} |
// Fix the input sampleSize if necessary. |
if (sampleSize < 1) { |
sampleSize = 1; |
} |
+ fSampleSize = sampleSize; |
- // The size of the output bitmap is determined by the size of the |
- // requested subset, not by the size of the intersection of the subset |
- // and the image dimensions. |
- // If inputX is negative, we will need to place decoded pixels into the |
- // output bitmap starting at a left offset. Call this outX. |
- // If outX is non-zero, subsetX must be zero. |
- // If inputY is negative, we will need to place decoded pixels into the |
- // output bitmap starting at a top offset. Call this outY. |
- // If outY is non-zero, subsetY must be zero. |
- int outX; |
- int outY; |
- SkIRect subset = SkIRect::MakeXYWH(inputX, inputY, inputWidth, inputHeight); |
- SubsetType type = adjust_subset_rect(fDecoder->getInfo().dimensions(), &subset, &outX, &outY); |
- if (SubsetType::kOutside_SubsetType == type) { |
- return nullptr; |
+ fSubset = desiredSubset; |
+ fSubsetType = adjust_subset_rect(fDecoder->getInfo().dimensions(), &fSubset, &fOutX, &fOutY); |
+ if (SubsetType::kOutside_SubsetType == fSubsetType) { |
+ return false; |
} |
- // Create the image info for the decode |
+ // Create the image info. |
SkAlphaType dstAlphaType = fDecoder->getInfo().alphaType(); |
- if (kUnpremul_SkAlphaType == dstAlphaType) { |
- dstAlphaType = kPremul_SkAlphaType; |
+ if (kOpaque_SkAlphaType != dstAlphaType) { |
+ dstAlphaType = requireUnpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType; |
+ } |
+ fOutInfo = SkImageInfo::Make(get_scaled_dimension(desiredSubset.width(), sampleSize), |
+ get_scaled_dimension(desiredSubset.height(), sampleSize), dstColorType, dstAlphaType); |
+ *outInfo = fOutInfo; |
+ |
+ // The decoder does not know anything about the scale that we are applying. |
+ fDecodeInfo = fOutInfo.makeWH(this->width(), this->height()); |
+ |
+ // Check that we can convert to the requested color and alpha types. |
+ return conversion_possible(fOutInfo, fDecoder->getInfo()); |
+} |
+ |
+bool SkBitmapRegionCanvas::decodeRegion(SkBitmap& bitmap) { |
+ if (fOutInfo.isEmpty()) { |
+ SkCodecPrintf("Error: Call prepareRegion() first."); |
+ return false; |
+ } |
+ |
+ if (bitmap.width() < fOutInfo.width() || bitmap.height() < fOutInfo.height() || |
+ bitmap.colorType() != fOutInfo.colorType()) { |
+ SkCodecPrintf("Error: Invalid size or color type for input bitmap."); |
+ return false; |
} |
- SkImageInfo decodeInfo = SkImageInfo::Make(this->width(), this->height(), |
- dstColorType, dstAlphaType); |
+ bitmap.setAlphaType(fOutInfo.alphaType()); |
// Start the scanline decoder |
- SkCodec::Result r = fDecoder->startScanlineDecode(decodeInfo); |
+ SkCodec::Result r = fDecoder->startScanlineDecode(fDecodeInfo); |
if (SkCodec::kSuccess != r) { |
SkCodecPrintf("Error: Could not start scanline decoder.\n"); |
- return nullptr; |
+ return false; |
} |
// Allocate a bitmap for the unscaled decode |
SkBitmap tmp; |
- SkImageInfo tmpInfo = decodeInfo.makeWH(this->width(), subset.height()); |
+ SkImageInfo tmpInfo = fDecodeInfo.makeWH(this->width(), fSubset.height()); |
if (!tmp.tryAllocPixels(tmpInfo)) { |
SkCodecPrintf("Error: Could not allocate pixels.\n"); |
- return nullptr; |
+ return false; |
} |
// Skip the unneeded rows |
- if (!fDecoder->skipScanlines(subset.y())) { |
+ if (!fDecoder->skipScanlines(fSubset.y())) { |
SkCodecPrintf("Error: Failed to skip scanlines.\n"); |
- return nullptr; |
+ return false; |
} |
// Decode the necessary rows |
- fDecoder->getScanlines(tmp.getAddr(0, 0), subset.height(), tmp.rowBytes()); |
- |
- // Calculate the size of the output |
- const int outWidth = get_scaled_dimension(inputWidth, sampleSize); |
- const int outHeight = get_scaled_dimension(inputHeight, sampleSize); |
- |
- // Initialize the destination bitmap |
- SkAutoTDelete<SkBitmap> bitmap(new SkBitmap()); |
- SkImageInfo dstInfo = decodeInfo.makeWH(outWidth, outHeight); |
- if (!bitmap->tryAllocPixels(dstInfo)) { |
- SkCodecPrintf("Error: Could not allocate pixels.\n"); |
- return nullptr; |
- } |
+ fDecoder->getScanlines(tmp.getAddr(0, 0), fSubset.height(), tmp.rowBytes()); |
// Zero the bitmap if the region is not completely within the image. |
- // TODO (msarett): Can we make this faster by implementing it to only |
- // zero parts of the image that we won't overwrite with |
- // pixels? |
- // TODO (msarett): This could be skipped if memory is zero initialized. |
- // This would matter if this code is moved to Android and |
- // uses Android bitmaps. |
- if (SubsetType::kPartiallyInside_SubsetType == type) { |
- bitmap->eraseColor(0); |
+ if (SubsetType::kPartiallyInside_SubsetType == fSubsetType) { |
+ bitmap.eraseColor(0); |
} |
// Use a canvas to crop and scale to the destination bitmap |
- SkCanvas canvas(*bitmap); |
+ SkCanvas canvas(bitmap); |
// TODO (msarett): Maybe we can take advantage of the fact that SkRect uses floats? |
- SkRect src = SkRect::MakeXYWH((SkScalar) subset.x(), (SkScalar) 0, |
- (SkScalar) subset.width(), (SkScalar) subset.height()); |
- SkRect dst = SkRect::MakeXYWH((SkScalar) (outX / sampleSize), (SkScalar) (outY / sampleSize), |
- (SkScalar) get_scaled_dimension(subset.width(), sampleSize), |
- (SkScalar) get_scaled_dimension(subset.height(), sampleSize)); |
+ SkRect src = SkRect::MakeXYWH((SkScalar) fSubset.x(), (SkScalar) 0, |
+ (SkScalar) fSubset.width(), (SkScalar) fSubset.height()); |
+ SkRect dst = SkRect::MakeXYWH((SkScalar) (fOutX / fSampleSize), |
+ (SkScalar) (fOutY / fSampleSize), |
+ (SkScalar) get_scaled_dimension(fSubset.width(), fSampleSize), |
+ (SkScalar) get_scaled_dimension(fSubset.height(), fSampleSize)); |
SkPaint paint; |
// Overwrite the dst with the src pixels |
paint.setXfermodeMode(SkXfermode::kSrc_Mode); |
// TODO (msarett): Test multiple filter qualities. kNone is the default. |
canvas.drawBitmapRect(tmp, src, dst, &paint); |
- return bitmap.detach(); |
-} |
- |
-bool SkBitmapRegionCanvas::conversionSupported(SkColorType colorType) { |
- // SkCanvas does not draw to these color types. |
- if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorType) { |
- return false; |
- } |
- |
- // FIXME: Call virtual function when it lands. |
- SkImageInfo info = SkImageInfo::Make(0, 0, colorType, fDecoder->getInfo().alphaType(), |
- fDecoder->getInfo().profileType()); |
- return conversion_possible(info, fDecoder->getInfo()); |
+ return true; |
} |