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

Side by Side 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: Response to Leon's comments 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 unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkBitmapRegionCanvas.h"
9 #include "SkCanvas.h"
10 #include "SkScanlineDecoder.h"
11
12 SkBitmapRegionCanvas::SkBitmapRegionCanvas(SkScanlineDecoder* decoder)
13 : INHERITED(decoder->getInfo().width(), decoder->getInfo().height())
14 , fDecoder(decoder)
15 {}
16
17 /*
18 * This has several key differences from the Android version:
19 * Returns a Skia bitmap instead of an Android bitmap.
20 * Android version attempts to reuse a recycled bitmap.
21 */
22 SkBitmap* SkBitmapRegionCanvas::decodeRegion(int input_x, int input_y,
23 int input_w, int input_h,
24 int sampleSize,
25 SkColorType dstColorType) {
26 // Reject color types not supported by this method
27 if (kIndex_8_SkColorType == dstColorType || kGray_8_SkColorType == dstColorT ype) {
28 SkDebugf("Error: Color type not supported.\n");
29 return NULL;
30 }
31
32 // Correct the output region if necessary
33 int left = SkTMax(0, input_x);
34 int leftOffset = left - input_x;
35 int top = SkTMax(0, input_y);
36 int topOffset = top - input_y;
37 int width = SkTMin(this->width() - left, input_w - leftOffset);
38 int height = SkTMin(this->height() - top, input_h - topOffset);
39 if (width <= 0 || height <= 0) {
40 SkDebugf("Error: Region must intersect part of the image.\n");
41 return NULL;
42 }
43
44 // Create the image info the decode
45 SkAlphaType dstAlphaType = fDecoder->getInfo().alphaType();
46 if (kUnpremul_SkAlphaType == dstAlphaType) {
47 dstAlphaType = kPremul_SkAlphaType;
48 }
49 SkImageInfo decodeInfo = SkImageInfo::Make(this->width(), this->height(),
50 dstColorType, dstAlphaType);
51
52 // Start the scanline decoder
53 SkCodec::Result r = fDecoder->start(decodeInfo);
54 if (SkCodec::kSuccess != r) {
55 SkDebugf("Error: Could not start scanline decoder.\n");
56 return NULL;
57 }
58
59 // Allocate a bitmap for the unscaled decode
60 SkBitmap tmp;
61 SkImageInfo tmpInfo = decodeInfo.makeWH(this->width(), height);
62 if (!tmp.tryAllocPixels(tmpInfo)) {
63 SkDebugf("Error: Could not allocate pixels.\n");
64 return NULL;
65 }
66
67 // Skip the unneeded rows
68 SkCodec::Result result =
69 fDecoder->skipScanlines(top);
scroggo 2015/08/28 13:49:43 nit: could fit on one line?
msarett 2015/08/28 18:45:50 Done.
70 switch (result) {
71 case SkCodec::kSuccess:
scroggo 2015/08/28 13:49:44 Perhaps this can be if (fDecoder->skipScanlines(t
msarett 2015/08/28 18:45:50 Done.
72 break;
73 default:
74 SkDebugf("Error: Failed to skip scanlines.\n");
75 return NULL;
76 }
77
78 // Decode the necessary rows
79 result = fDecoder->getScanlines(tmp.getAddr(0, 0), height,
80 tmp.rowBytes());
81 switch (result) {
82 case SkCodec::kSuccess:
83 case SkCodec::kIncompleteInput:
84 break;
85 default:
86 SkDebugf("Error: Failed to get scanlines.\n");
87 return NULL;
88 }
89
90 // Calculate the size of the output
91 int outWidth = SkTMax(1, input_w / sampleSize);
92 int outHeight = SkTMax(1, input_h / sampleSize);
93
94 // Initialize the destination bitmap
95 SkAutoTDelete<SkBitmap> bitmap(SkNEW(SkBitmap));
96 SkImageInfo dstInfo = decodeInfo.makeWH(outWidth, outHeight);
97 if (!bitmap->tryAllocPixels(dstInfo)) {
98 SkDebugf("Error: Could not allocate pixels.\n");
99 return NULL;
100 }
101
102 // Zero the bitmap if the region is not completely within the image.
103 // TODO (msarett): We could implement this to the only zero the parts of
104 // the bitmap that we won't overwrite with image data.
105 // However, it's not certain that this would be faster,
106 // it would be more complex (requires creating rects with
107 // bounds scaled by sampleSize), and performance probably
108 // isn't critical for clients who call this API with
scroggo 2015/08/28 13:49:44 Why not? Don't clients actually use it in this way
msarett 2015/08/28 18:45:50 Revising this comment.
109 // "invalid" values.
110 // TODO (msarett): This could be skipped if memory is zero initialized.
111 // This would matter if this code is moved to Android and
112 // uses Android bitmaps.
113 if (0 != leftOffset || 0 != topOffset ||
114 input_x + input_w > this->width() ||
115 input_y + input_h > this->height()) {
116 bitmap->eraseColor(0);
scroggo 2015/08/28 13:49:43 Why zero? I thought you said we should draw black
msarett 2015/08/28 18:45:50 Yeah I did say that. I thought I saw a comment in
117 }
118
119 // Use a canvas to crop and scale to the destination bitmap
120 SkAutoTDelete<SkCanvas> canvas(SkNEW_ARGS(SkCanvas, (*bitmap)));
121 SkRect src = SkRect::MakeXYWH(left, 0, width, height);
122 SkRect dst = SkRect::MakeXYWH(leftOffset / sampleSize, topOffset / sampleSiz e,
123 SkTMax(1, width / sampleSize), SkTMax(1, height / sampleSize));
124 SkPaint* paint = new SkPaint();
125 // Overwrite the dst with the src pixels
126 paint->setXfermodeMode(SkXfermode::kSrc_Mode);
127 // Set the scaling quality, kNone is the default
scroggo 2015/08/28 13:49:44 // TODO: Use other qualities? It seems like we ca
msarett 2015/08/28 18:45:50 Yep this is unnecessary. I think I was just teach
128 paint->setFilterQuality(SkFilterQuality::kNone_SkFilterQuality);
129 canvas->drawBitmapRect(tmp, src, dst, paint);
130
131 return bitmap.detach();
132 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698