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

Unified Diff: src/utils/SkBitmapRegionCanvas.cpp

Issue 1288963002: Provides multiple implementations of Android's SkBitmapRegionDecoder (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 4 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: src/utils/SkBitmapRegionCanvas.cpp
diff --git a/src/utils/SkBitmapRegionCanvas.cpp b/src/utils/SkBitmapRegionCanvas.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d6cf36bf3905c32000f31ddd2e9ae03ac214ef88
--- /dev/null
+++ b/src/utils/SkBitmapRegionCanvas.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SkBitmapRegionCanvas.h"
+#include "SkCanvas.h"
+#include "SkScanlineDecoder.h"
+
+SkBitmapRegionCanvas::SkBitmapRegionCanvas(SkScanlineDecoder* decoder)
+ : INHERITED(decoder->getInfo().width(), decoder->getInfo().height())
+ , fDecoder(decoder)
+{}
+
+/*
+ * This has several key differences from the Android version:
+ * Returns a Skia bitmap instead of an Android bitmap.
+ * Android version attempts to reuse a recycled bitmap.
+ */
+SkBitmap* SkBitmapRegionCanvas::decodeRegion(int input_x, int input_y,
+ int input_w, int input_h,
+ int sampleSize,
+ SkColorType colorType) {
scroggo 2015/08/13 16:53:07 nit: Maybe this should be dstColorType?
msarett 2015/08/13 18:10:23 Done.
+ // Reject color types not supported by this method
+ if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorType) {
+ SkDebugf("Error: Color type not supported.\n");
+ return NULL;
+ }
+
+ // Correct the output region if necessary
+ int left = SkTMax(0, input_x);
+ int leftOffset = left - input_x;
+ int top = SkTMax(0, input_y);
+ int topOffset = top - input_y;
+ int width = SkTMin(this->width() - left, input_w - leftOffset);
+ int height = SkTMin(this->height() - top, input_h - topOffset);
+ if (width <= 0 || height <= 0) {
+ SkDebugf("Error: Region must intersect part of the image.\n");
+ return NULL;
+ }
+
+ // Create the image info the decode
+ SkAlphaType alphaType = fDecoder->getInfo().alphaType();
+ if (kUnpremul_SkAlphaType == alphaType) {
+ alphaType = kPremul_SkAlphaType;
+ }
+ SkImageInfo decodeInfo = SkImageInfo::Make(this->width(), this->height(),
+ colorType, alphaType);
+
+ // Start the scanline decoder
+ SkCodec::Result r = fDecoder->start(decodeInfo);
+ if (SkCodec::kSuccess != r) {
+ SkDebugf("Error: Could not start scanline decoder.\n");
+ return NULL;
+ }
+
+ // Allocate a bitmap for the unscaled decode
+ SkBitmap tmp;
+ SkImageInfo tmpInfo = decodeInfo.makeWH(this->width(), height);
+ if (!tmp.tryAllocPixels(tmpInfo)) {
+ SkDebugf("Error: Could not allocate pixels.\n");
+ return NULL;
+ }
+
+ // Skip the unneeded rows
+ SkCodec::Result result =
+ fDecoder->skipScanlines(top);
+ switch (result) {
+ case SkCodec::kSuccess:
+ case SkCodec::kIncompleteInput:
scroggo 2015/08/13 16:53:07 It seems like if we got incomplete at this point,
msarett 2015/08/13 18:10:23 Agreed. Changing this.
+ break;
+ default:
+ SkDebugf("Error: Failed to skip scanlines.\n");
+ return NULL;
+ }
+
+ // Decode the necessary rows
+ result = fDecoder->getScanlines(tmp.getAddr(0, 0), height,
+ tmp.rowBytes());
+ switch (result) {
+ case SkCodec::kSuccess:
+ case SkCodec::kIncompleteInput:
+ break;
+ default:
+ SkDebugf("Error: Failed to get scanlines.\n");
+ return NULL;
+ }
+
+ // Calculate the size of the output
+ int outWidth = SkTMax(1, input_w / sampleSize);
+ int outHeight = SkTMax(1, input_h / sampleSize);
+
+ // Initialize the destination bitmap
+ SkAutoTDelete<SkBitmap> bitmap(SkNEW(SkBitmap));
+ SkImageInfo dstInfo = decodeInfo.makeWH(outWidth, outHeight);
+ if (!bitmap->tryAllocPixels(dstInfo)) {
+ SkDebugf("Error: Could not allocate pixels.\n");
+ return NULL;
+ }
+ bitmap->eraseColor(0);
msarett 2015/08/13 15:16:34 This was necessary for images with transparency.
scroggo 2015/08/13 16:53:07 Seems like a good candidate for a FIXME.
msarett 2015/08/13 18:10:23 Yes on all counts. This has been added. SkFilter
+
+ // Use a canvas to crop and scale to the destination bitmap
+ SkAutoTDelete<SkCanvas> canvas(SkNEW_ARGS(SkCanvas, (*bitmap)));
+ SkRect src = SkRect::MakeXYWH(left, 0, width, height);
+ SkRect dst = SkRect::MakeXYWH(leftOffset / sampleSize, topOffset / sampleSize,
+ SkTMax(1, width / sampleSize), SkTMax(1, height / sampleSize));
+ canvas->drawBitmapRect(tmp, src, dst, NULL);
+
+ return bitmap.detach();
+}

Powered by Google App Engine
This is Rietveld 408576698