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

Side by Side Diff: src/codec/SkScaledCodec.cpp

Issue 1406223002: Create an SkAndroidCodec API separate from SkCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Response to comments 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 | « src/codec/SkSampledCodec.h ('k') | src/codec/SkSwizzler.cpp » ('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 "SkCodec.h"
8 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
9 #include "SkScaledCodec.h" 10 #include "SkSampledCodec.h"
10 #include "SkStream.h" 11
11 #include "SkWebpCodec.h" 12 // FIXME: Rename this file to SkSampledCodec.cpp
12 13
13 14 SkSampledCodec::SkSampledCodec(SkCodec* codec)
14 SkCodec* SkScaledCodec::NewFromStream(SkStream* stream) { 15 : INHERITED(codec->getInfo())
15 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream));
16 if (nullptr == codec) {
17 return nullptr;
18 }
19
20 switch (codec->getEncodedFormat()) {
21 case kWEBP_SkEncodedFormat:
22 // Webp codec supports scaling and subsetting natively
23 return codec.detach();
24 case kPNG_SkEncodedFormat:
25 case kJPEG_SkEncodedFormat:
26 // wrap in new SkScaledCodec
27 return new SkScaledCodec(codec.detach());
28 default:
29 // FIXME: SkScaledCodec is temporarily disabled for other formats
30 // while focusing on the formats that are supported by
31 // BitmapRegionDecoder.
32 return nullptr;
33 }
34 }
35
36 SkCodec* SkScaledCodec::NewFromData(SkData* data) {
37 if (!data) {
38 return nullptr;
39 }
40 return NewFromStream(new SkMemoryStream(data));
41 }
42
43 SkScaledCodec::SkScaledCodec(SkCodec* codec)
44 : INHERITED(codec->getInfo(), nullptr)
45 , fCodec(codec) 16 , fCodec(codec)
46 {} 17 {}
47 18
48 SkScaledCodec::~SkScaledCodec() {} 19 static bool is_in_range(int coord, int offset, int length) {
49 20 return coord >= offset && coord < offset + length;
50 bool SkScaledCodec::onRewind() { 21 }
51 return fCodec->onRewind(); 22
52 } 23 SkISize SkSampledCodec::onGetSampledDimensions(int sampleSize) const {
53 24 // Fast path for when we are not scaling.
54 static SkISize best_scaled_dimensions(const SkISize& origDims, const SkISize& na tiveDims, 25 if (1 == sampleSize) {
55 const SkISize& scaledCodecDims, float desi redScale) { 26 return fCodec->getInfo().dimensions();
56 if (nativeDims == scaledCodecDims) { 27 }
57 // does not matter which to return if equal. Return here to skip below c alculations 28
58 return nativeDims; 29 const int width = fCodec->getInfo().width();
59 } 30 const int height = fCodec->getInfo().height();
60 float idealWidth = origDims.width() * desiredScale; 31
61 float idealHeight = origDims.height() * desiredScale; 32 // Check if the codec can provide the scaling natively.
62 33 float scale = get_scale_from_sample_size(sampleSize);
63 // calculate difference between native dimensions and ideal dimensions 34 SkSize idealSize = SkSize::Make(scale * (float) width, scale * (float) heigh t);
64 float nativeWDiff = SkTAbs(idealWidth - nativeDims.width()); 35 SkISize nativeSize = fCodec->getScaledDimensions(scale);
65 float nativeHDiff = SkTAbs(idealHeight - nativeDims.height()); 36 float widthDiff = SkTAbs(((float) nativeSize.width()) - idealSize.width());
66 float nativeDiff = nativeWDiff + nativeHDiff; 37 float heightDiff = SkTAbs(((float) nativeSize.height()) - idealSize.height() );
67 38 if (widthDiff < 1.0f && heightDiff < 1.0f) {
68 // Native scaling is preferred to sampling. If we can scale natively to 39 return nativeSize;
scroggo 2015/10/19 20:03:20 It looks like this comment didn't survive, but I t
msarett 2015/10/19 21:39:22 I'll add the comment back in.
69 // within one of the ideal value, we should choose to scale natively. 40 }
70 if (nativeWDiff < 1.0f && nativeHDiff < 1.0f) { 41
71 return nativeDims; 42 // Provide the scaling by sampling.
72 } 43 return SkISize::Make(get_scaled_dimension(width, sampleSize),
73 44 get_scaled_dimension(height, sampleSize));
74 // calculate difference between scaledCodec dimensions and ideal dimensions 45 }
75 float scaledCodecWDiff = SkTAbs(idealWidth - scaledCodecDims.width()); 46
76 float scaledCodecHDiff = SkTAbs(idealHeight - scaledCodecDims.height()); 47 SkCodec::Result SkSampledCodec::onGetAndroidPixels(const SkImageInfo& info, void * pixels,
77 float scaledCodecDiff = scaledCodecWDiff + scaledCodecHDiff; 48 size_t rowBytes, AndroidOptions& options) {
78 49 // Create an Options struct for the codec.
79 // return dimensions closest to ideal dimensions. 50 SkCodec::Options codecOptions;
80 // If the differences are equal, return nativeDims, as native scaling is mor e efficient. 51 codecOptions.fZeroInitialized = options.fZeroInitialized;
81 return nativeDiff > scaledCodecDiff ? scaledCodecDims : nativeDims; 52
82 } 53 SkIRect* subset = options.fSubset;
83 54 if (!subset || subset->size() == fCodec->getInfo().dimensions()) {
84 /* 55 // Try to use the native codec to perform the decode.
85 * Return a valid set of output dimensions for this decoder, given an input scal e 56 SkCodec::Result result = fCodec->getPixels(info, pixels, rowBytes, &code cOptions,
scroggo 2015/10/19 20:03:20 Why not check fCodec->dimensionsSupported()? If tr
msarett 2015/10/19 21:39:22 sgtm
86 */ 57 options.fColorPtr, options.fColorCount);
87 SkISize SkScaledCodec::onGetScaledDimensions(float desiredScale) const { 58
88 SkISize nativeDimensions = fCodec->getScaledDimensions(desiredScale); 59 if (SkCodec::kInvalidScale != result) {
89 // support scaling down by integer numbers. Ex: 1/2, 1/3, 1/4 ... 60 return result;
90 SkISize scaledCodecDimensions; 61 }
91 if (desiredScale > 0.5f) { 62
92 // sampleSize = 1 63 // If the native codec does not support the requested scale, scale by sa mpling.
93 scaledCodecDimensions = fCodec->getInfo().dimensions(); 64 return sampledDecode(info, pixels, rowBytes, options);
94 } 65 }
95 // sampleSize determines the step size between samples 66
96 // Ex: sampleSize = 2, sample every second pixel in x and y directions 67 // We are performing a subset decode.
97 int sampleSize = int ((1.0f / desiredScale) + 0.5f); 68 // First attempt to use the native codec. The native codec needs to know th e scaled size
98 69 // of the image and the subset.
99 int scaledWidth = get_scaled_dimension(this->getInfo().width(), sampleSize); 70 int sampleSize = options.fSampleSize;
100 int scaledHeight = get_scaled_dimension(this->getInfo().height(), sampleSize ); 71 SkISize scaledSize = this->onGetSampledDimensions(sampleSize);
101 72 int scaledSubsetX = subset->x() / sampleSize;
102 // Return the calculated output dimensions for the given scale 73 int scaledSubsetY = subset->y() / sampleSize;
103 scaledCodecDimensions = SkISize::Make(scaledWidth, scaledHeight); 74 int scaledSubsetWidth = info.width();
104 75 int scaledSubsetHeight = info.height();
105 return best_scaled_dimensions(this->getInfo().dimensions(), nativeDimensions , 76
106 scaledCodecDimensions, desiredScale); 77 // The scanline decoder only needs to be aware of scaledSubsetX and scaledSu bestWidth.
107 } 78 // We will handling subsetting in the y-dimension by skipping scanlines.
108 79 SkIRect scanlineSubset = SkIRect::MakeXYWH(scaledSubsetX, 0, scaledSubsetWid th,
109 // check if scaling to dstInfo size from srcInfo size using sampleSize is possib le 80 scaledSize.height());
110 static bool scaling_supported(const SkISize& dstDim, const SkISize& srcDim, 81 codecOptions.fSubset = &scanlineSubset;
111 int* sampleX, int* sampleY) { 82 SkCodec::Result result = fCodec->startScanlineDecode(info.makeWH(scaledSize. width(),
112 SkScaledCodec::ComputeSampleSize(dstDim, srcDim, sampleX, sampleY); 83 scaledSize.height()), &codecOptions, options.fColorPtr, options.fCol orCount);
113 const int dstWidth = dstDim.width(); 84 switch (result) {
114 const int dstHeight = dstDim.height(); 85 case SkCodec::kSuccess:
115 const int srcWidth = srcDim.width(); 86 break;
116 const int srcHeight = srcDim.height(); 87 case SkCodec::kInvalidScale:
117 // only support down sampling, not up sampling 88 // If the native codec does not support the requested scale, scale b y sampling.
118 if (dstWidth > srcWidth || dstHeight > srcHeight) { 89 return sampledDecode(info, pixels, rowBytes, options);
119 return false; 90 default:
120 } 91 return result;
121 // check that srcWidth is scaled down by an integer value 92 }
122 if (get_scaled_dimension(srcWidth, *sampleX) != dstWidth) { 93
123 return false; 94 switch (fCodec->getScanlineOrder()) {
124 } 95 case SkCodec::kTopDown_SkScanlineOrder:
125 // check that src height is scaled down by an integer value 96 case SkCodec::kNone_SkScanlineOrder: {
126 if (get_scaled_dimension(srcHeight, *sampleY) != dstHeight) { 97 if (!fCodec->skipScanlines(scaledSubsetY)) {
127 return false; 98 fCodec->fillIncompleteImage(info, pixels, rowBytes, options.fZer oInitialized,
128 } 99 scaledSubsetHeight, 0);
129 // sampleX and sampleY should be equal unless the original sampleSize reques ted was larger 100 return SkCodec::kIncompleteInput;
130 // than srcWidth or srcHeight. If so, the result of this is dstWidth or dstH eight = 1. 101 }
131 // This functionality allows for tall thin images to still be scaled down by scaling factors. 102
132 if (*sampleX != *sampleY){ 103 int decodedLines = fCodec->getScanlines(pixels, scaledSubsetHeight, rowBytes);
133 if (1 != dstWidth && 1 != dstHeight) { 104 if (decodedLines != scaledSubsetHeight) {
134 return false; 105 return SkCodec::kIncompleteInput;
135 } 106 }
136 } 107 return SkCodec::kSuccess;
137 return true; 108 }
138 } 109 case SkCodec::kBottomUp_SkScanlineOrder:
139 110 case SkCodec::kOutOfOrder_SkScanlineOrder: {
140 bool SkScaledCodec::onDimensionsSupported(const SkISize& dim) { 111 for (int y = 0; y < scaledSize.height(); y++) {
141 // Check with fCodec first. No need to call the non-virtual version, which 112 int dstY = fCodec->nextScanline();
142 // just checks if it matches the original, since a match means this method 113 if (is_in_range(dstY, scaledSubsetY, scaledSubsetHeight)) {
143 // will not be called. 114 void* pixelsPtr = SkTAddOffset<void>(pixels, rowBytes * (dst Y - scaledSubsetY));
144 if (fCodec->onDimensionsSupported(dim)) { 115 if (1 != fCodec->getScanlines(pixelsPtr, 1, rowBytes)) {
145 return true; 116 // FIXME: Fill incomplete images skbug.com/4428
146 } 117 return SkCodec::kIncompleteInput;
147 118 }
148 // FIXME: These variables are unused, but are needed by scaling_supported. 119 } else {
149 // This class could also cache these values, and avoid calling this in 120 if (!fCodec->skipScanlines(1)) {
150 // onGetPixels (since getPixels already calls it). 121 // FIXME: Fill incomplete images skbug.com/4428
151 int sampleX; 122 return SkCodec::kIncompleteInput;
152 int sampleY; 123 }
153 return scaling_supported(dim, this->getInfo().dimensions(), &sampleX, &sampl eY); 124 }
154 } 125 }
155 126 return SkCodec::kSuccess;
156 // calculates sampleSize in x and y direction 127 }
157 void SkScaledCodec::ComputeSampleSize(const SkISize& dstDim, const SkISize& srcD im, 128 default:
158 int* sampleXPtr, int* sampleYPtr) { 129 SkASSERT(false);
159 int srcWidth = srcDim.width(); 130 return SkCodec::kUnimplemented;
160 int dstWidth = dstDim.width(); 131 }
161 int srcHeight = srcDim.height(); 132 }
162 int dstHeight = dstDim.height(); 133
163 134
164 int sampleX = srcWidth / dstWidth; 135 SkCodec::Result SkSampledCodec::sampledDecode(const SkImageInfo& info, void* pix els,
165 int sampleY = srcHeight / dstHeight; 136 size_t rowBytes, AndroidOptions& options) {
166 137 // Create options struct for the codec.
167 // only support down sampling, not up sampling 138 SkCodec::Options sampledOptions;
168 SkASSERT(dstWidth <= srcWidth); 139 sampledOptions.fZeroInitialized = options.fZeroInitialized;
169 SkASSERT(dstHeight <= srcHeight); 140
170 141 // Check if there is a subset.
171 // sampleX and sampleY should be equal unless the original sampleSize reques ted was 142 SkIRect subset;
172 // larger than srcWidth or srcHeight. 143 int subsetY = 0;
173 // If so, the result of this is dstWidth or dstHeight = 1. This functionalit y 144 int subsetWidth = fCodec->getInfo().width();
174 // allows for tall thin images to still be scaled down by scaling factors. 145 int subsetHeight = fCodec->getInfo().height();
175
176 if (sampleX != sampleY){
177 if (1 != dstWidth && 1 != dstHeight) {
178
179 // rounding during onGetScaledDimensions can cause different sampleS izes
180 // Ex: srcWidth = 79, srcHeight = 20, sampleSize = 10
181 // dstWidth = 7, dstHeight = 2, sampleX = 79/7 = 11, sampleY = 20/2 = 10
182 // correct for this rounding by comparing width to sampleY and heigh t to sampleX
183
184 if (get_scaled_dimension(srcWidth, sampleY) == dstWidth) {
185 sampleX = sampleY;
186 } else if (get_scaled_dimension(srcHeight, sampleX) == dstHeight) {
187 sampleY = sampleX;
188 }
189 }
190 }
191
192 if (sampleXPtr) {
193 *sampleXPtr = sampleX;
194 }
195 if (sampleYPtr) {
196 *sampleYPtr = sampleY;
197 }
198 }
199
200 // TODO: Implement subsetting in onGetPixels which works when and when not sampl ing
201
202 SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi d* dst,
203 size_t rowBytes, const Options& optio ns,
204 SkPMColor ctable[], int* ctableCount,
205 int* rowsDecoded) {
206
207 if (options.fSubset) { 146 if (options.fSubset) {
208 // Subsets are not supported. 147 // We will need to know about subsetting in the y-dimension in order to use the
209 return kUnimplemented; 148 // scanline decoder.
210 } 149 SkIRect* subsetPtr = options.fSubset;
211 150 subsetY = subsetPtr->y();
212 if (fCodec->dimensionsSupported(requestedInfo.dimensions())) { 151 subsetWidth = subsetPtr->width();
213 // Make sure that the parent class does not fill on an incomplete decode , since 152 subsetHeight = subsetPtr->height();
214 // fCodec will take care of filling the uninitialized lines. 153
215 *rowsDecoded = requestedInfo.height(); 154 // The scanline decoder only needs to be aware of subsetting in the x-di mension.
216 return fCodec->getPixels(requestedInfo, dst, rowBytes, &options, ctable, ctableCount); 155 subset.setXYWH(subsetPtr->x(), 0, subsetWidth, fCodec->getInfo().height( ));
217 } 156 sampledOptions.fSubset = &subset;
218 157 }
219 // scaling requested 158
220 int sampleX; 159 // Start the scanline decode.
221 int sampleY; 160 SkCodec::Result result = fCodec->startScanlineDecode(
222 if (!scaling_supported(requestedInfo.dimensions(), fCodec->getInfo().dimensi ons(), 161 info.makeWH(fCodec->getInfo().width(), fCodec->getInfo().height()), &sampledOptions,
223 &sampleX, &sampleY)) { 162 options.fColorPtr, options.fColorCount);
224 // onDimensionsSupported would have returned false, meaning we should ne ver reach here. 163 if (SkCodec::kSuccess != result) {
225 SkASSERT(false);
226 return kInvalidScale;
227 }
228
229 // set first sample pixel in y direction
230 const int Y0 = get_start_coord(sampleY);
231
232 const int dstHeight = requestedInfo.height();
233 const int srcWidth = fCodec->getInfo().width();
234 const int srcHeight = fCodec->getInfo().height();
235
236 const SkImageInfo info = requestedInfo.makeWH(srcWidth, srcHeight);
237
238 Result result = fCodec->startScanlineDecode(info, &options, ctable, ctableCo unt);
239
240 if (kSuccess != result) {
241 return result; 164 return result;
242 } 165 }
243 166
244 SkSampler* sampler = fCodec->getSampler(true); 167 SkSampler* sampler = fCodec->getSampler(true);
245 if (!sampler) { 168 if (!sampler) {
246 return kUnimplemented; 169 return SkCodec::kUnimplemented;
247 } 170 }
248 171
249 if (sampler->setSampleX(sampleX) != requestedInfo.width()) { 172 // Since we guarantee that output dimensions are always at least one (even i f the sampleSize
250 return kInvalidScale; 173 // is greater than a given dimension), the input sampleSize is not always th e sampleSize that
251 } 174 // we use in practice.
252 175 int sampleX = subsetWidth / info.width();
176 int sampleY = subsetHeight / info.height();
177 if (sampler->setSampleX(sampleX) != info.width()) {
178 return SkCodec::kInvalidScale;
179 }
180 if (get_scaled_dimension(subsetHeight, sampleY) != info.height()) {
181 return SkCodec::kInvalidScale;
182 }
183
184 int y0 = get_start_coord(sampleY);
185 int dstHeight = info.height();
253 switch(fCodec->getScanlineOrder()) { 186 switch(fCodec->getScanlineOrder()) {
254 case SkCodec::kTopDown_SkScanlineOrder: { 187 case SkCodec::kTopDown_SkScanlineOrder: {
255 if (!fCodec->skipScanlines(Y0)) { 188 if (!fCodec->skipScanlines(y0 + subsetY)) {
256 *rowsDecoded = 0; 189 fCodec->fillIncompleteImage(info, pixels, rowBytes, options.fZer oInitialized,
257 return kIncompleteInput; 190 dstHeight, 0);
258 } 191 return SkCodec::kIncompleteInput;
192 }
193 void* pixelPtr = pixels;
259 for (int y = 0; y < dstHeight; y++) { 194 for (int y = 0; y < dstHeight; y++) {
260 if (1 != fCodec->getScanlines(dst, 1, rowBytes)) { 195 if (1 != fCodec->getScanlines(pixelPtr, 1, rowBytes)) {
261 // The failed call to getScanlines() will take care of 196 fCodec->fillIncompleteImage(info, pixels, rowBytes, options. fZeroInitialized,
262 // filling the failed row, so we indicate that we have 197 dstHeight, y + 1);
263 // decoded (y + 1) rows. 198 return SkCodec::kIncompleteInput;
264 *rowsDecoded = y + 1; 199 }
265 return kIncompleteInput; 200 int linesToSkip = SkTMin(sampleY - 1, dstHeight - y - 1);
266 } 201 if (!fCodec->skipScanlines(linesToSkip)) {
267 if (y < dstHeight - 1) { 202 fCodec->fillIncompleteImage(info, pixels, rowBytes, options. fZeroInitialized,
268 if (!fCodec->skipScanlines(sampleY - 1)) { 203 dstHeight, y + 1);
269 *rowsDecoded = y + 1; 204 return SkCodec::kIncompleteInput;
270 return kIncompleteInput; 205 }
271 } 206 pixelPtr = SkTAddOffset<void>(pixelPtr, rowBytes);
272 } 207 }
273 dst = SkTAddOffset<void>(dst, rowBytes); 208 return SkCodec::kSuccess;
274 }
275 return kSuccess;
276 } 209 }
277 case SkCodec::kBottomUp_SkScanlineOrder: 210 case SkCodec::kBottomUp_SkScanlineOrder:
278 case SkCodec::kOutOfOrder_SkScanlineOrder: { 211 case SkCodec::kOutOfOrder_SkScanlineOrder: {
279 Result result = kSuccess; 212 SkCodec::Result result = SkCodec::kSuccess;
280 int y; 213 int y;
281 for (y = 0; y < srcHeight; y++) { 214 for (y = 0; y < fCodec->getInfo().height(); y++) {
282 int srcY = fCodec->nextScanline(); 215 int srcY = fCodec->nextScanline();
283 if (is_coord_necessary(srcY, sampleY, dstHeight)) { 216 if (is_coord_necessary(srcY, sampleY, dstHeight, subsetY)) {
284 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * get_dst_co ord(srcY, sampleY)); 217 void* pixelPtr = SkTAddOffset<void>(pixels,
285 if (1 != fCodec->getScanlines(dstPtr, 1, rowBytes)) { 218 rowBytes * get_dst_coord(srcY, sampleY));
286 result = kIncompleteInput; 219 if (1 != fCodec->getScanlines(pixelPtr, 1, rowBytes)) {
220 result = SkCodec::kIncompleteInput;
287 break; 221 break;
288 } 222 }
289 } else { 223 } else {
290 if (!fCodec->skipScanlines(1)) { 224 if (!fCodec->skipScanlines(1)) {
291 result = kIncompleteInput; 225 result = SkCodec::kIncompleteInput;
292 break; 226 break;
293 } 227 }
294 } 228 }
295 } 229 }
296 230
297 // We handle filling uninitialized memory here instead of in the par ent class. 231 // We handle filling uninitialized memory here instead of using fCod ec.
298 // The parent class does not know that we are sampling. 232 // fCodec does not know that we are sampling.
299 if (kIncompleteInput == result) { 233 if (SkCodec::kIncompleteInput == result) {
300 const uint32_t fillValue = fCodec->getFillValue(requestedInfo.co lorType(), 234 const uint32_t fillValue = fCodec->getFillValue(info.colorType() ,
301 requestedInfo.alphaType()); 235 info.alphaType());
302 for (; y < srcHeight; y++) { 236 for (; y < fCodec->getInfo().height(); y++) {
303 int srcY = fCodec->outputScanline(y); 237 int srcY = fCodec->outputScanline(y);
304 if (is_coord_necessary(srcY, sampleY, dstHeight)) { 238 if (is_coord_necessary(srcY, sampleY, dstHeight, subsetY)) {
305 void* dstRow = SkTAddOffset<void>(dst, 239 void* pixelPtr = SkTAddOffset<void>(pixels,
306 rowBytes * get_dst_coord(srcY, sampleY)); 240 rowBytes * get_dst_coord(srcY, sampleY));
307 SkSampler::Fill(requestedInfo.makeWH(requestedInfo.width (), 1), dstRow, 241 SkSampler::Fill(info.makeWH(info.width(), 1), pixelPtr, rowBytes, fillValue,
308 rowBytes, fillValue, options.fZeroInitialized); 242 options.fZeroInitialized);
309 } 243 }
310 } 244 }
311 *rowsDecoded = dstHeight;
312 } 245 }
313 return result; 246 return result;
314 } 247 }
315 case SkCodec::kNone_SkScanlineOrder: { 248 case SkCodec::kNone_SkScanlineOrder: {
316 SkAutoMalloc storage(srcHeight * rowBytes); 249 SkAutoMalloc storage((subsetHeight - y0) * rowBytes);
317 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); 250 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get());
318 int scanlines = fCodec->getScanlines(storagePtr, srcHeight, rowBytes ); 251 if (!fCodec->skipScanlines(subsetY + y0)) {
319 storagePtr += Y0 * rowBytes; 252 fCodec->fillIncompleteImage(info, pixels, rowBytes, options.fZer oInitialized,
320 scanlines -= Y0; 253 dstHeight, 0);
254 return SkCodec::kIncompleteInput;
255 }
256 int scanlines = fCodec->getScanlines(storagePtr, subsetHeight - y0, rowBytes);
321 int y = 0; 257 int y = 0;
322 while (y < dstHeight && scanlines > 0) { 258 void* pixelPtr = pixels;
323 memcpy(dst, storagePtr, rowBytes); 259 while (y < dstHeight) {
260 memcpy(pixelPtr, storagePtr, info.minRowBytes());
324 storagePtr += sampleY * rowBytes; 261 storagePtr += sampleY * rowBytes;
325 dst = SkTAddOffset<void>(dst, rowBytes); 262 pixelPtr = SkTAddOffset<void>(pixelPtr, rowBytes);
326 scanlines -= sampleY;
327 y++; 263 y++;
328 } 264 }
329 if (y < dstHeight) { 265 if (scanlines < dstHeight) {
330 // fCodec has already handled filling uninitialized memory. 266 // fCodec has already handled filling uninitialized memory.
331 *rowsDecoded = dstHeight; 267 return SkCodec::kIncompleteInput;
332 return kIncompleteInput; 268 }
333 } 269 return SkCodec::kSuccess;
334 return kSuccess;
335 } 270 }
336 default: 271 default:
337 SkASSERT(false); 272 SkASSERT(false);
338 return kUnimplemented; 273 return SkCodec::kUnimplemented;
339 } 274 }
340 } 275 }
341
342 uint32_t SkScaledCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaT ype) const {
343 return fCodec->onGetFillValue(colorType, alphaType);
344 }
345
346 SkCodec::SkScanlineOrder SkScaledCodec::onGetScanlineOrder() const {
347 return fCodec->onGetScanlineOrder();
348 }
OLDNEW
« no previous file with comments | « src/codec/SkSampledCodec.h ('k') | src/codec/SkSwizzler.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698