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

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: Use nullptr instead of NULL 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);
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 nullptr;
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 nullptr;
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 nullptr;
65 }
66
67 // Skip the unneeded rows
68 if (SkCodec::kSuccess != fDecoder->skipScanlines(top)) {
69 SkDebugf("Error: Failed to skip scanlines.\n");
70 return nullptr;
71 }
72
73 // Decode the necessary rows
74 SkCodec::Result result = fDecoder->getScanlines(tmp.getAddr(0, 0), height,
scroggo 2015/09/01 22:05:28 So this won't work for all BMP, for example, but t
msarett 2015/09/02 18:02:23 Correct. This was written before we had kBottomUp
75 tmp.rowBytes());
76 switch (result) {
77 case SkCodec::kSuccess:
78 case SkCodec::kIncompleteInput:
79 break;
80 default:
81 SkDebugf("Error: Failed to get scanlines.\n");
82 return nullptr;
83 }
84
85 // Calculate the size of the output
86 int outWidth = SkTMax(1, input_w / sampleSize);
87 int outHeight = SkTMax(1, input_h / sampleSize);
88
89 // Initialize the destination bitmap
90 SkAutoTDelete<SkBitmap> bitmap(SkNEW(SkBitmap));
91 SkImageInfo dstInfo = decodeInfo.makeWH(outWidth, outHeight);
92 if (!bitmap->tryAllocPixels(dstInfo)) {
93 SkDebugf("Error: Could not allocate pixels.\n");
94 return nullptr;
95 }
96
97 // Zero the bitmap if the region is not completely within the image.
98 // TODO (msarett): Can we make this faster by implementing it to only
99 // zero parts of the image that we won't overwrite with
100 // pixels?
101 // TODO (msarett): This could be skipped if memory is zero initialized.
102 // This would matter if this code is moved to Android and
103 // uses Android bitmaps.
104 if (0 != leftOffset || 0 != topOffset ||
105 input_x + input_w > this->width() ||
106 input_y + input_h > this->height()) {
107 bitmap->eraseColor(0);
108 }
109
110 // Use a canvas to crop and scale to the destination bitmap
111 SkAutoTDelete<SkCanvas> canvas(SkNEW_ARGS(SkCanvas, (*bitmap)));
112 SkRect src = SkRect::MakeXYWH(left, 0, width, height);
113 SkRect dst = SkRect::MakeXYWH(leftOffset / sampleSize, topOffset / sampleSiz e,
114 SkTMax(1, width / sampleSize), SkTMax(1, height / sampleSize));
115 SkPaint* paint = new SkPaint();
116 // Overwrite the dst with the src pixels
117 paint->setXfermodeMode(SkXfermode::kSrc_Mode);
118 // TODO (msarett): Test multiple filter qualities. kNone is the default.
119 canvas->drawBitmapRect(tmp, src, dst, paint);
120
121 return bitmap.detach();
122 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698