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

Side by Side 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkBitmapRegionCanvas.h" 8 #include "SkBitmapRegionCanvas.h"
9 #include "SkCanvas.h" 9 #include "SkCanvas.h"
10 #include "SkCodecPriv.h" 10 #include "SkCodecPriv.h"
11 #include "SkCodecTools.h" 11 #include "SkCodecTools.h"
12 12
13 SkBitmapRegionCanvas::SkBitmapRegionCanvas(SkCodec* decoder) 13 SkBitmapRegionCanvas::SkBitmapRegionCanvas(SkCodec* decoder)
14 : INHERITED(decoder->getInfo().width(), decoder->getInfo().height()) 14 : INHERITED(decoder->getInfo().width(), decoder->getInfo().height())
15 , fDecoder(decoder) 15 , fDecoder(decoder)
16 {} 16 {}
17 17
18 /* 18 bool SkBitmapRegionCanvas::prepareRegion(const SkIRect& desiredSubset,
19 * Three differences from the Android version: 19 int sampleSize,
20 * Returns a Skia bitmap instead of an Android bitmap. 20 SkColorType dstColorType,
21 * Android version attempts to reuse a recycled bitmap. 21 bool requireUnpremul,
22 * Removed the options object and used parameters for color type and 22 SkImageInfo* outInfo) {
23 * sample size.
24 */
25 SkBitmap* SkBitmapRegionCanvas::decodeRegion(int inputX, int inputY,
26 int inputWidth, int inputHeight,
27 int sampleSize,
28 SkColorType dstColorType) {
29 // Reject color types not supported by this method 23 // Reject color types not supported by this method
30 if (kIndex_8_SkColorType == dstColorType || kGray_8_SkColorType == dstColorT ype) { 24 if (kIndex_8_SkColorType == dstColorType || kGray_8_SkColorType == dstColorT ype) {
scroggo 2015/10/27 15:00:50 Should we also check for requireUnpremul here? I s
31 SkCodecPrintf("Error: Color type not supported.\n"); 25 SkCodecPrintf("Error: Color type not supported.\n");
32 return nullptr; 26 return false;
33 } 27 }
34 28
35 // Fix the input sampleSize if necessary. 29 // Fix the input sampleSize if necessary.
36 if (sampleSize < 1) { 30 if (sampleSize < 1) {
37 sampleSize = 1; 31 sampleSize = 1;
38 } 32 }
33 fSampleSize = sampleSize;
39 34
40 // The size of the output bitmap is determined by the size of the 35 fSubset = desiredSubset;
41 // requested subset, not by the size of the intersection of the subset 36 fSubsetType = adjust_subset_rect(fDecoder->getInfo().dimensions(), &fSubset, &fOutX, &fOutY);
42 // and the image dimensions. 37 if (SubsetType::kOutside_SubsetType == fSubsetType) {
43 // If inputX is negative, we will need to place decoded pixels into the 38 return false;
44 // output bitmap starting at a left offset. Call this outX.
45 // If outX is non-zero, subsetX must be zero.
46 // If inputY is negative, we will need to place decoded pixels into the
47 // output bitmap starting at a top offset. Call this outY.
48 // If outY is non-zero, subsetY must be zero.
49 int outX;
50 int outY;
51 SkIRect subset = SkIRect::MakeXYWH(inputX, inputY, inputWidth, inputHeight);
52 SubsetType type = adjust_subset_rect(fDecoder->getInfo().dimensions(), &subs et, &outX, &outY);
53 if (SubsetType::kOutside_SubsetType == type) {
54 return nullptr;
55 } 39 }
56 40
57 // Create the image info for the decode 41 // Create the image info.
58 SkAlphaType dstAlphaType = fDecoder->getInfo().alphaType(); 42 SkAlphaType dstAlphaType = fDecoder->getInfo().alphaType();
59 if (kUnpremul_SkAlphaType == dstAlphaType) { 43 if (kOpaque_SkAlphaType != dstAlphaType) {
60 dstAlphaType = kPremul_SkAlphaType; 44 dstAlphaType = requireUnpremul ? kUnpremul_SkAlphaType : kPremul_SkAlpha Type;
61 } 45 }
62 SkImageInfo decodeInfo = SkImageInfo::Make(this->width(), this->height(), 46 fOutInfo = SkImageInfo::Make(get_scaled_dimension(desiredSubset.width(), sam pleSize),
63 dstColorType, dstAlphaType); 47 get_scaled_dimension(desiredSubset.height(), sampleSize), dstColorTy pe, dstAlphaType);
48 *outInfo = fOutInfo;
49
50 // The decoder does not know anything about the scale that we are applying.
51 fDecodeInfo = fOutInfo.makeWH(this->width(), this->height());
52
53 // Check that we can convert to the requested color and alpha types.
54 return conversion_possible(fOutInfo, fDecoder->getInfo());
55 }
56
57 bool SkBitmapRegionCanvas::decodeRegion(SkBitmap& bitmap) {
58 if (fOutInfo.isEmpty()) {
59 SkCodecPrintf("Error: Call prepareRegion() first.");
60 return false;
61 }
62
63 if (bitmap.width() < fOutInfo.width() || bitmap.height() < fOutInfo.height() ||
64 bitmap.colorType() != fOutInfo.colorType()) {
65 SkCodecPrintf("Error: Invalid size or color type for input bitmap.");
66 return false;
67 }
68 bitmap.setAlphaType(fOutInfo.alphaType());
64 69
65 // Start the scanline decoder 70 // Start the scanline decoder
66 SkCodec::Result r = fDecoder->startScanlineDecode(decodeInfo); 71 SkCodec::Result r = fDecoder->startScanlineDecode(fDecodeInfo);
67 if (SkCodec::kSuccess != r) { 72 if (SkCodec::kSuccess != r) {
68 SkCodecPrintf("Error: Could not start scanline decoder.\n"); 73 SkCodecPrintf("Error: Could not start scanline decoder.\n");
69 return nullptr; 74 return false;
70 } 75 }
71 76
72 // Allocate a bitmap for the unscaled decode 77 // Allocate a bitmap for the unscaled decode
73 SkBitmap tmp; 78 SkBitmap tmp;
74 SkImageInfo tmpInfo = decodeInfo.makeWH(this->width(), subset.height()); 79 SkImageInfo tmpInfo = fDecodeInfo.makeWH(this->width(), fSubset.height());
75 if (!tmp.tryAllocPixels(tmpInfo)) { 80 if (!tmp.tryAllocPixels(tmpInfo)) {
76 SkCodecPrintf("Error: Could not allocate pixels.\n"); 81 SkCodecPrintf("Error: Could not allocate pixels.\n");
77 return nullptr; 82 return false;
78 } 83 }
79 84
80 // Skip the unneeded rows 85 // Skip the unneeded rows
81 if (!fDecoder->skipScanlines(subset.y())) { 86 if (!fDecoder->skipScanlines(fSubset.y())) {
82 SkCodecPrintf("Error: Failed to skip scanlines.\n"); 87 SkCodecPrintf("Error: Failed to skip scanlines.\n");
83 return nullptr; 88 return false;
84 } 89 }
85 90
86 // Decode the necessary rows 91 // Decode the necessary rows
87 fDecoder->getScanlines(tmp.getAddr(0, 0), subset.height(), tmp.rowBytes()); 92 fDecoder->getScanlines(tmp.getAddr(0, 0), fSubset.height(), tmp.rowBytes());
88
89 // Calculate the size of the output
90 const int outWidth = get_scaled_dimension(inputWidth, sampleSize);
91 const int outHeight = get_scaled_dimension(inputHeight, sampleSize);
92
93 // Initialize the destination bitmap
94 SkAutoTDelete<SkBitmap> bitmap(new SkBitmap());
95 SkImageInfo dstInfo = decodeInfo.makeWH(outWidth, outHeight);
96 if (!bitmap->tryAllocPixels(dstInfo)) {
97 SkCodecPrintf("Error: Could not allocate pixels.\n");
98 return nullptr;
99 }
100 93
101 // Zero the bitmap if the region is not completely within the image. 94 // Zero the bitmap if the region is not completely within the image.
102 // TODO (msarett): Can we make this faster by implementing it to only 95 if (SubsetType::kPartiallyInside_SubsetType == fSubsetType) {
103 // zero parts of the image that we won't overwrite with 96 bitmap.eraseColor(0);
104 // pixels?
105 // TODO (msarett): This could be skipped if memory is zero initialized.
106 // This would matter if this code is moved to Android and
107 // uses Android bitmaps.
108 if (SubsetType::kPartiallyInside_SubsetType == type) {
109 bitmap->eraseColor(0);
110 } 97 }
111 98
112 // Use a canvas to crop and scale to the destination bitmap 99 // Use a canvas to crop and scale to the destination bitmap
113 SkCanvas canvas(*bitmap); 100 SkCanvas canvas(bitmap);
114 // TODO (msarett): Maybe we can take advantage of the fact that SkRect uses floats? 101 // TODO (msarett): Maybe we can take advantage of the fact that SkRect uses floats?
115 SkRect src = SkRect::MakeXYWH((SkScalar) subset.x(), (SkScalar) 0, 102 SkRect src = SkRect::MakeXYWH((SkScalar) fSubset.x(), (SkScalar) 0,
116 (SkScalar) subset.width(), (SkScalar) subset.height()); 103 (SkScalar) fSubset.width(), (SkScalar) fSubset.height());
117 SkRect dst = SkRect::MakeXYWH((SkScalar) (outX / sampleSize), (SkScalar) (ou tY / sampleSize), 104 SkRect dst = SkRect::MakeXYWH((SkScalar) (fOutX / fSampleSize),
118 (SkScalar) get_scaled_dimension(subset.width(), sampleSize), 105 (SkScalar) (fOutY / fSampleSize),
119 (SkScalar) get_scaled_dimension(subset.height(), sampleSize)); 106 (SkScalar) get_scaled_dimension(fSubset.width(), fSampleSize),
107 (SkScalar) get_scaled_dimension(fSubset.height(), fSampleSize));
120 SkPaint paint; 108 SkPaint paint;
121 // Overwrite the dst with the src pixels 109 // Overwrite the dst with the src pixels
122 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 110 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
123 // TODO (msarett): Test multiple filter qualities. kNone is the default. 111 // TODO (msarett): Test multiple filter qualities. kNone is the default.
124 canvas.drawBitmapRect(tmp, src, dst, &paint); 112 canvas.drawBitmapRect(tmp, src, dst, &paint);
125 113
126 return bitmap.detach(); 114 return true;
127 } 115 }
128
129 bool SkBitmapRegionCanvas::conversionSupported(SkColorType colorType) {
130 // SkCanvas does not draw to these color types.
131 if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorType) {
132 return false;
133 }
134
135 // FIXME: Call virtual function when it lands.
136 SkImageInfo info = SkImageInfo::Make(0, 0, colorType, fDecoder->getInfo().al phaType(),
137 fDecoder->getInfo().profileType());
138 return conversion_possible(info, fDecoder->getInfo());
139 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698