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

Powered by Google App Engine
This is Rietveld 408576698