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

Side by Side Diff: tools/SkBitmapRegionCanvas.cpp

Issue 1402863002: Implementation of SkBitmapRegionDecoder using SkAndroidCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@split1
Patch Set: Add AndroidCodec strategy to benchmark 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
« no previous file with comments | « gyp/tools.gyp ('k') | tools/SkBitmapRegionCodec.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 /*
19 * Chooses the correct image subset offsets and dimensions for the partial decod e.
20 *
21 * @return true if the subset is completely contained within the image
22 * false otherwise
23 */
24 static bool set_subset_region(int inputOffset, int inputDimension,
25 int imageOriginalDimension, int* imageSubsetOffset, int* outOffset,
26 int* imageSubsetDimension) {
27
28 // This must be at least zero, we can't start decoding the image at a negati ve coordinate.
29 *imageSubsetOffset = SkTMax(0, inputOffset);
30
31 // If inputOffset is less than zero, we decode to an offset location in the output bitmap.
32 *outOffset = *imageSubsetOffset - inputOffset;
33
34 // Use imageSusetOffset to make sure we don't decode pixels past the edge of the image.
35 // Use outOffset to make sure we don't decode pixels past the edge of the re gion.
36 *imageSubsetDimension = SkTMin(imageOriginalDimension - *imageSubsetOffset,
37 inputDimension - *outOffset);
38
39 return (*outOffset == 0) && (*imageSubsetDimension == inputDimension);
40 }
41
42 /*
43 * Three differences from the Android version: 19 * Three differences from the Android version:
44 * Returns a Skia bitmap instead of an Android bitmap. 20 * Returns a Skia bitmap instead of an Android bitmap.
45 * Android version attempts to reuse a recycled bitmap. 21 * Android version attempts to reuse a recycled bitmap.
46 * Removed the options object and used parameters for color type and 22 * Removed the options object and used parameters for color type and
47 * sample size. 23 * sample size.
48 */ 24 */
49 SkBitmap* SkBitmapRegionCanvas::decodeRegion(int inputX, int inputY, 25 SkBitmap* SkBitmapRegionCanvas::decodeRegion(int inputX, int inputY,
50 int inputWidth, int inputHeight, 26 int inputWidth, int inputHeight,
51 int sampleSize, 27 int sampleSize,
52 SkColorType dstColorType) { 28 SkColorType dstColorType) {
53 // Reject color types not supported by this method 29 // Reject color types not supported by this method
54 if (kIndex_8_SkColorType == dstColorType || kGray_8_SkColorType == dstColorT ype) { 30 if (kIndex_8_SkColorType == dstColorType || kGray_8_SkColorType == dstColorT ype) {
55 SkCodecPrintf("Error: Color type not supported.\n"); 31 SkCodecPrintf("Error: Color type not supported.\n");
56 return nullptr; 32 return nullptr;
57 } 33 }
58 34
59 // The client may not necessarily request a region that is fully within 35 // Fix the input sampleSize if necessary.
60 // the image. We may need to do some calculation to determine what part 36 if (sampleSize < 1) {
61 // of the image to decode. 37 sampleSize = 1;
62 38 }
63 // The left offset of the portion of the image we want, where zero
64 // indicates the left edge of the image.
65 int imageSubsetX;
66 39
67 // The size of the output bitmap is determined by the size of the 40 // The size of the output bitmap is determined by the size of the
68 // requested region, not by the size of the intersection of the region 41 // requested subset, not by the size of the intersection of the subset
69 // and the image dimensions. If inputX is negative, we will need to 42 // and the image dimensions.
70 // place decoded pixels into the output bitmap starting at a left offset. 43 // If inputX is negative, we will need to place decoded pixels into the
71 // If this is non-zero, imageSubsetX must be zero. 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.
72 int outX; 49 int outX;
73
74 // The width of the portion of the image that we will write to the output
75 // bitmap. If the region is not fully contained within the image, this
76 // will not be the same as inputWidth.
77 int imageSubsetWidth;
78 bool imageContainsEntireSubset = set_subset_region(inputX, inputWidth, this- >width(),
79 &imageSubsetX, &outX, &imageSubsetWidth);
80
81 // The top offset of the portion of the image we want, where zero
82 // indicates the top edge of the image.
83 int imageSubsetY;
84
85 // The size of the output bitmap is determined by the size of the
86 // requested region, not by the size of the intersection of the region
87 // and the image dimensions. If inputY is negative, we will need to
88 // place decoded pixels into the output bitmap starting at a top offset.
89 // If this is non-zero, imageSubsetY must be zero.
90 int outY; 50 int outY;
91 51 SkIRect subset = SkIRect::MakeXYWH(inputX, inputY, inputWidth, inputHeight);
92 // The height of the portion of the image that we will write to the output 52 SubsetType type = adjust_subset_rect(fDecoder->getInfo().dimensions(), &subs et, &outX, &outY);
93 // bitmap. If the region is not fully contained within the image, this 53 if (SubsetType::kOutside_SubsetType == type) {
94 // will not be the same as inputHeight.
95 int imageSubsetHeight;
96 imageContainsEntireSubset &= set_subset_region(inputY, inputHeight, this->he ight(),
97 &imageSubsetY, &outY, &imageSubsetHeight);
98
99 if (imageSubsetWidth <= 0 || imageSubsetHeight <= 0) {
100 SkCodecPrintf("Error: Region must intersect part of the image.\n");
101 return nullptr; 54 return nullptr;
102 } 55 }
103 56
104 // Create the image info for the decode 57 // Create the image info for the decode
105 SkAlphaType dstAlphaType = fDecoder->getInfo().alphaType(); 58 SkAlphaType dstAlphaType = fDecoder->getInfo().alphaType();
106 if (kUnpremul_SkAlphaType == dstAlphaType) { 59 if (kUnpremul_SkAlphaType == dstAlphaType) {
107 dstAlphaType = kPremul_SkAlphaType; 60 dstAlphaType = kPremul_SkAlphaType;
108 } 61 }
109 SkImageInfo decodeInfo = SkImageInfo::Make(this->width(), this->height(), 62 SkImageInfo decodeInfo = SkImageInfo::Make(this->width(), this->height(),
110 dstColorType, dstAlphaType); 63 dstColorType, dstAlphaType);
111 64
112 // Start the scanline decoder 65 // Start the scanline decoder
113 SkCodec::Result r = fDecoder->startScanlineDecode(decodeInfo); 66 SkCodec::Result r = fDecoder->startScanlineDecode(decodeInfo);
114 if (SkCodec::kSuccess != r) { 67 if (SkCodec::kSuccess != r) {
115 SkCodecPrintf("Error: Could not start scanline decoder.\n"); 68 SkCodecPrintf("Error: Could not start scanline decoder.\n");
116 return nullptr; 69 return nullptr;
117 } 70 }
118 71
119 // Allocate a bitmap for the unscaled decode 72 // Allocate a bitmap for the unscaled decode
120 SkBitmap tmp; 73 SkBitmap tmp;
121 SkImageInfo tmpInfo = decodeInfo.makeWH(this->width(), imageSubsetHeight); 74 SkImageInfo tmpInfo = decodeInfo.makeWH(this->width(), subset.height());
122 if (!tmp.tryAllocPixels(tmpInfo)) { 75 if (!tmp.tryAllocPixels(tmpInfo)) {
123 SkCodecPrintf("Error: Could not allocate pixels.\n"); 76 SkCodecPrintf("Error: Could not allocate pixels.\n");
124 return nullptr; 77 return nullptr;
125 } 78 }
126 79
127 // Skip the unneeded rows 80 // Skip the unneeded rows
128 if (!fDecoder->skipScanlines(imageSubsetY)) { 81 if (!fDecoder->skipScanlines(subset.y())) {
129 SkCodecPrintf("Error: Failed to skip scanlines.\n"); 82 SkCodecPrintf("Error: Failed to skip scanlines.\n");
130 return nullptr; 83 return nullptr;
131 } 84 }
132 85
133 // Decode the necessary rows 86 // Decode the necessary rows
134 fDecoder->getScanlines(tmp.getAddr(0, 0), imageSubsetHeight, tmp.rowBytes()) ; 87 fDecoder->getScanlines(tmp.getAddr(0, 0), subset.height(), tmp.rowBytes());
135 88
136 // Calculate the size of the output 89 // Calculate the size of the output
137 const int outWidth = get_scaled_dimension(inputWidth, sampleSize); 90 const int outWidth = get_scaled_dimension(inputWidth, sampleSize);
138 const int outHeight = get_scaled_dimension(inputHeight, sampleSize); 91 const int outHeight = get_scaled_dimension(inputHeight, sampleSize);
139 92
140 // Initialize the destination bitmap 93 // Initialize the destination bitmap
141 SkAutoTDelete<SkBitmap> bitmap(new SkBitmap()); 94 SkAutoTDelete<SkBitmap> bitmap(new SkBitmap());
142 SkImageInfo dstInfo = decodeInfo.makeWH(outWidth, outHeight); 95 SkImageInfo dstInfo = decodeInfo.makeWH(outWidth, outHeight);
143 if (!bitmap->tryAllocPixels(dstInfo)) { 96 if (!bitmap->tryAllocPixels(dstInfo)) {
144 SkCodecPrintf("Error: Could not allocate pixels.\n"); 97 SkCodecPrintf("Error: Could not allocate pixels.\n");
145 return nullptr; 98 return nullptr;
146 } 99 }
147 100
148 // Zero the bitmap if the region is not completely within the image. 101 // Zero the bitmap if the region is not completely within the image.
149 // TODO (msarett): Can we make this faster by implementing it to only 102 // TODO (msarett): Can we make this faster by implementing it to only
150 // zero parts of the image that we won't overwrite with 103 // zero parts of the image that we won't overwrite with
151 // pixels? 104 // pixels?
152 // TODO (msarett): This could be skipped if memory is zero initialized. 105 // TODO (msarett): This could be skipped if memory is zero initialized.
153 // This would matter if this code is moved to Android and 106 // This would matter if this code is moved to Android and
154 // uses Android bitmaps. 107 // uses Android bitmaps.
155 if (!imageContainsEntireSubset) { 108 if (SubsetType::kPartiallyInside_SubsetType == type) {
156 bitmap->eraseColor(0); 109 bitmap->eraseColor(0);
157 } 110 }
158 111
159 // Use a canvas to crop and scale to the destination bitmap 112 // Use a canvas to crop and scale to the destination bitmap
160 SkCanvas canvas(*bitmap); 113 SkCanvas canvas(*bitmap);
161 // TODO (msarett): Maybe we can take advantage of the fact that SkRect uses floats? 114 // TODO (msarett): Maybe we can take advantage of the fact that SkRect uses floats?
162 SkRect src = SkRect::MakeXYWH((SkScalar) imageSubsetX, (SkScalar) 0, 115 SkRect src = SkRect::MakeXYWH((SkScalar) subset.x(), (SkScalar) 0,
163 (SkScalar) imageSubsetWidth, (SkScalar) imageSubsetHeight); 116 (SkScalar) subset.width(), (SkScalar) subset.height());
164 SkRect dst = SkRect::MakeXYWH((SkScalar) (outX / sampleSize), (SkScalar) (ou tY / sampleSize), 117 SkRect dst = SkRect::MakeXYWH((SkScalar) (outX / sampleSize), (SkScalar) (ou tY / sampleSize),
165 (SkScalar) get_scaled_dimension(imageSubsetWidth, sampleSize), 118 (SkScalar) get_scaled_dimension(subset.width(), sampleSize),
166 (SkScalar) get_scaled_dimension(imageSubsetHeight, sampleSize)); 119 (SkScalar) get_scaled_dimension(subset.height(), sampleSize));
167 SkPaint paint; 120 SkPaint paint;
168 // Overwrite the dst with the src pixels 121 // Overwrite the dst with the src pixels
169 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 122 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
170 // TODO (msarett): Test multiple filter qualities. kNone is the default. 123 // TODO (msarett): Test multiple filter qualities. kNone is the default.
171 canvas.drawBitmapRect(tmp, src, dst, &paint); 124 canvas.drawBitmapRect(tmp, src, dst, &paint);
172 125
173 return bitmap.detach(); 126 return bitmap.detach();
174 } 127 }
175 128
176 bool SkBitmapRegionCanvas::conversionSupported(SkColorType colorType) { 129 bool SkBitmapRegionCanvas::conversionSupported(SkColorType colorType) {
177 // SkCanvas does not draw to these color types. 130 // SkCanvas does not draw to these color types.
178 if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorType) { 131 if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorType) {
179 return false; 132 return false;
180 } 133 }
181 134
182 // FIXME: Call virtual function when it lands. 135 // FIXME: Call virtual function when it lands.
183 SkImageInfo info = SkImageInfo::Make(0, 0, colorType, fDecoder->getInfo().al phaType(), 136 SkImageInfo info = SkImageInfo::Make(0, 0, colorType, fDecoder->getInfo().al phaType(),
184 fDecoder->getInfo().profileType()); 137 fDecoder->getInfo().profileType());
185 return conversion_possible(info, fDecoder->getInfo()); 138 return conversion_possible(info, fDecoder->getInfo());
186 } 139 }
OLDNEW
« no previous file with comments | « gyp/tools.gyp ('k') | tools/SkBitmapRegionCodec.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698