Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(307)

Unified Diff: tools/SkBitmapRegionCanvas.cpp

Issue 1418093006: Refactor SkBitmapRegionDecoderInterface for Android (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
}

Powered by Google App Engine
This is Rietveld 408576698