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

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 comments Created 5 years, 3 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 nullptr;
30 }
31
32 // Correct the output region if necessary
33 int left = SkTMax(0, input_x);
scroggo 2015/09/02 21:32:24 This is because BRD supports subsets that are not
msarett 2015/09/03 19:20:52 Yes :(
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);
scroggo 2015/09/02 21:32:24 Calculating width and height are very similar. Wha
msarett 2015/09/03 19:20:52 Seems like a good idea. Will do.
39 if (width <= 0 || height <= 0) {
40 SkDebugf("Error: Region must intersect part of the image.\n");
41 return nullptr;
42 }
43
44 // Create the image info the decode
scroggo 2015/09/02 21:32:24 for* the decode?
msarett 2015/09/03 19:20:52 Done.
45 SkAlphaType dstAlphaType = fDecoder->getInfo().alphaType();
46 if (kUnpremul_SkAlphaType == dstAlphaType) {
scroggo 2015/09/02 21:32:24 This is a downside to this version of BRD - we can
msarett 2015/09/03 19:20:52 Yeah agreed. I will file a bug for comparing/choo
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 SkASSERT(SkScanlineDecoder::kTopDown_SkScanlineOrder == fDecoder->getScanlin eOrder());
55 if (SkCodec::kSuccess != r) {
56 SkDebugf("Error: Could not start scanline decoder.\n");
57 return nullptr;
58 }
59
60 // Allocate a bitmap for the unscaled decode
61 SkBitmap tmp;
62 SkImageInfo tmpInfo = decodeInfo.makeWH(this->width(), height);
63 if (!tmp.tryAllocPixels(tmpInfo)) {
64 SkDebugf("Error: Could not allocate pixels.\n");
65 return nullptr;
66 }
67
68 // Skip the unneeded rows
69 if (SkCodec::kSuccess != fDecoder->skipScanlines(top)) {
70 SkDebugf("Error: Failed to skip scanlines.\n");
71 return nullptr;
72 }
73
74 // Decode the necessary rows
75 SkCodec::Result result = fDecoder->getScanlines(tmp.getAddr(0, 0), height,
76 tmp.rowBytes());
77 switch (result) {
78 case SkCodec::kSuccess:
79 case SkCodec::kIncompleteInput:
80 break;
81 default:
82 SkDebugf("Error: Failed to get scanlines.\n");
83 return nullptr;
84 }
85
86 // Calculate the size of the output
87 int outWidth = SkTMax(1, input_w / sampleSize);
scroggo 2015/09/02 21:32:24 It surprised me that this is input_w and not width
msarett 2015/09/03 19:20:51 Yes. No matter what (for backward compatibility)
88 int outHeight = SkTMax(1, input_h / sampleSize);
89
90 // Initialize the destination bitmap
91 SkAutoTDelete<SkBitmap> bitmap(SkNEW(SkBitmap));
scroggo 2015/09/02 21:32:24 nit: new
msarett 2015/09/03 19:20:52 Done.
92 SkImageInfo dstInfo = decodeInfo.makeWH(outWidth, outHeight);
93 if (!bitmap->tryAllocPixels(dstInfo)) {
94 SkDebugf("Error: Could not allocate pixels.\n");
95 return nullptr;
96 }
97
98 // Zero the bitmap if the region is not completely within the image.
99 // TODO (msarett): Can we make this faster by implementing it to only
100 // zero parts of the image that we won't overwrite with
101 // pixels?
102 // TODO (msarett): This could be skipped if memory is zero initialized.
103 // This would matter if this code is moved to Android and
104 // uses Android bitmaps.
105 if (0 != leftOffset || 0 != topOffset ||
106 input_x + input_w > this->width() ||
107 input_y + input_h > this->height()) {
108 bitmap->eraseColor(0);
109 }
110
111 // Use a canvas to crop and scale to the destination bitmap
scroggo 2015/09/02 21:32:24 Shouldn't we be using SkSurface? I guess we cannot
msarett 2015/09/03 19:20:52 I don't really know anything about SkSurface vs Sk
scroggo 2015/09/03 20:07:41 Yes.
msarett 2015/09/03 22:10:30 Ok that makes sense. Since we are returning an Sk
112 SkAutoTDelete<SkCanvas> canvas(SkNEW_ARGS(SkCanvas, (*bitmap)));
scroggo 2015/09/02 21:32:24 nit: new Actually, wait, can you put this on the
msarett 2015/09/03 19:20:51 Yes I believe so!
113 SkRect src = SkRect::MakeXYWH(left, 0, width, height);
114 SkRect dst = SkRect::MakeXYWH(leftOffset / sampleSize, topOffset / sampleSiz e,
115 SkTMax(1, width / sampleSize), SkTMax(1, height / sampleSize));
scroggo 2015/09/02 21:32:24 SkTMax(1, N / sampleSize) This pattern gets used
msarett 2015/09/03 19:20:51 Yes!
116 SkPaint* paint = new SkPaint();
scroggo 2015/09/02 21:32:24 This gets leaked. Why not just put it on the stack
msarett 2015/09/03 19:20:52 Putting on stack!
117 // Overwrite the dst with the src pixels
118 paint->setXfermodeMode(SkXfermode::kSrc_Mode);
119 // TODO (msarett): Test multiple filter qualities. kNone is the default.
120 canvas->drawBitmapRect(tmp, src, dst, paint);
121
122 return bitmap.detach();
123 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698