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

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

Issue 1997703003: Make SkPngCodec decode progressively. (Closed) Base URL: https://skia.googlesource.com/skia.git@foil
Patch Set: Add explanatory comment Created 4 years, 6 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 "SkBmpCodec.h" 8 #include "SkBmpCodec.h"
9 #include "SkCodec.h" 9 #include "SkCodec.h"
10 #include "SkCodecPriv.h" 10 #include "SkCodecPriv.h"
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 // startScanlineDecode will need to be called before decoding scanlines. 147 // startScanlineDecode will need to be called before decoding scanlines.
148 fCurrScanline = -1; 148 fCurrScanline = -1;
149 149
150 if (!fStream->rewind()) { 150 if (!fStream->rewind()) {
151 return false; 151 return false;
152 } 152 }
153 153
154 return this->onRewind(); 154 return this->onRewind();
155 } 155 }
156 156
157 #define CHECK_COLOR_TABLE \
158 if (kIndex_8_SkColorType == info.colorType()) { \
159 if (nullptr == ctable || nullptr == ctableCount) { \
160 return SkCodec::kInvalidParameters; \
161 } \
162 } else { \
163 if (ctableCount) { \
164 *ctableCount = 0; \
165 } \
166 ctableCount = nullptr; \
167 ctable = nullptr; \
168 }
169
170
157 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 171 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
158 const Options* options, SkPMColor ctable[], i nt* ctableCount) { 172 const Options* options, SkPMColor ctable[], i nt* ctableCount) {
159 if (kUnknown_SkColorType == info.colorType()) { 173 if (kUnknown_SkColorType == info.colorType()) {
160 return kInvalidConversion; 174 return kInvalidConversion;
161 } 175 }
162 if (nullptr == pixels) { 176 if (nullptr == pixels) {
163 return kInvalidParameters; 177 return kInvalidParameters;
164 } 178 }
165 if (rowBytes < info.minRowBytes()) { 179 if (rowBytes < info.minRowBytes()) {
166 return kInvalidParameters; 180 return kInvalidParameters;
167 } 181 }
168 182
169 if (kIndex_8_SkColorType == info.colorType()) { 183 CHECK_COLOR_TABLE;
170 if (nullptr == ctable || nullptr == ctableCount) {
171 return kInvalidParameters;
172 }
173 } else {
174 if (ctableCount) {
175 *ctableCount = 0;
176 }
177 ctableCount = nullptr;
178 ctable = nullptr;
179 }
180 184
181 if (!this->rewindIfNeeded()) { 185 if (!this->rewindIfNeeded()) {
182 return kCouldNotRewind; 186 return kCouldNotRewind;
183 } 187 }
184 188
185 // Default options. 189 // Default options.
186 Options optsStorage; 190 Options optsStorage;
187 if (nullptr == options) { 191 if (nullptr == options) {
188 options = &optsStorage; 192 options = &optsStorage;
189 } else if (options->fSubset) { 193 } else if (options->fSubset) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 rowsDecoded); 225 rowsDecoded);
222 } 226 }
223 227
224 return result; 228 return result;
225 } 229 }
226 230
227 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { 231 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
228 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr); 232 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr);
229 } 233 }
230 234
231 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo, 235 SkCodec::Result SkCodec::startIncrementalDecode(const SkImageInfo& info, void* p ixels,
236 size_t rowBytes, const SkCodec::Options* options, SkPMColor* ctable, int * ctableCount) {
237 fStartedIncrementalDecode = false;
238
239 if (kUnknown_SkColorType == info.colorType()) {
240 return kInvalidConversion;
241 }
242 if (nullptr == pixels) {
243 return kInvalidParameters;
244 }
245
246 // Ensure that valid color ptrs are passed in for kIndex8 color type
247 CHECK_COLOR_TABLE;
248
249 // FIXME: If the rows come after the rows of a previous incremental decode,
250 // we might be able to skip the rewind, but only the implementation knows
251 // that. (e.g. PNG will always need to rewind, since we called longjmp, but
252 // a bottom-up BMP could skip rewinding if the new rows are above the old
253 // rows.)
254 if (!this->rewindIfNeeded()) {
255 return kCouldNotRewind;
256 }
257
258 // Set options.
259 Options optsStorage;
260 if (nullptr == options) {
261 options = &optsStorage;
262 } else if (options->fSubset) {
263 SkIRect size = SkIRect::MakeSize(info.dimensions());
264 if (!size.contains(*options->fSubset)) {
265 return kInvalidParameters;
266 }
267
268 const int top = options->fSubset->top();
269 const int bottom = options->fSubset->bottom();
270 if (top < 0 || top >= info.height() || top >= bottom || bottom > info.he ight()) {
271 return kInvalidParameters;
272 }
273 }
274
275 if (!this->dimensionsSupported(info.dimensions())) {
276 return kInvalidScale;
277 }
278
279 fDstInfo = info;
280 fOptions = *options;
281
282 const Result result = this->onStartIncrementalDecode(info, pixels, rowBytes,
283 fOptions, ctable, ctableCount);
284 if (kSuccess == result) {
285 fStartedIncrementalDecode = true;
286 } else if (kUnimplemented == result) {
287 // FIXME: This is temporarily necessary, until we transition SkCodec
288 // implementations from scanline decoding to incremental decoding.
289 // SkAndroidCodec will first attempt to use incremental decoding, but
290 // will fall back to scanline decoding if incremental returns
291 // kUnimplemented. rewindIfNeeded(), above, set fNeedsRewind to true
292 // (after potentially rewinding), but we do not want the next call to
293 // startScanlineDecode() to do a rewind.
294 fNeedsRewind = false;
295 }
296 return result;
297 }
298
299
300 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& info,
232 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) { 301 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) {
233 // Reset fCurrScanline in case of failure. 302 // Reset fCurrScanline in case of failure.
234 fCurrScanline = -1; 303 fCurrScanline = -1;
235 // Ensure that valid color ptrs are passed in for kIndex8 color type 304 // Ensure that valid color ptrs are passed in for kIndex8 color type
236 if (kIndex_8_SkColorType == dstInfo.colorType()) { 305 CHECK_COLOR_TABLE;
237 if (nullptr == ctable || nullptr == ctableCount) {
238 return SkCodec::kInvalidParameters;
239 }
240 } else {
241 if (ctableCount) {
242 *ctableCount = 0;
243 }
244 ctableCount = nullptr;
245 ctable = nullptr;
246 }
247 306
248 if (!this->rewindIfNeeded()) { 307 if (!this->rewindIfNeeded()) {
249 return kCouldNotRewind; 308 return kCouldNotRewind;
250 } 309 }
251 310
252 // Set options. 311 // Set options.
253 Options optsStorage; 312 Options optsStorage;
254 if (nullptr == options) { 313 if (nullptr == options) {
255 options = &optsStorage; 314 options = &optsStorage;
256 } else if (options->fSubset) { 315 } else if (options->fSubset) {
257 SkIRect size = SkIRect::MakeSize(dstInfo.dimensions()); 316 SkIRect size = SkIRect::MakeSize(info.dimensions());
258 if (!size.contains(*options->fSubset)) { 317 if (!size.contains(*options->fSubset)) {
259 return kInvalidInput; 318 return kInvalidInput;
260 } 319 }
261 320
262 // We only support subsetting in the x-dimension for scanline decoder. 321 // We only support subsetting in the x-dimension for scanline decoder.
263 // Subsetting in the y-dimension can be accomplished using skipScanlines (). 322 // Subsetting in the y-dimension can be accomplished using skipScanlines ().
264 if (options->fSubset->top() != 0 || options->fSubset->height() != dstInf o.height()) { 323 if (options->fSubset->top() != 0 || options->fSubset->height() != info.h eight()) {
265 return kInvalidInput; 324 return kInvalidInput;
266 } 325 }
267 } 326 }
268 327
269 // FIXME: Support subsets somehow? 328 // FIXME: Support subsets somehow?
270 if (!this->dimensionsSupported(dstInfo.dimensions())) { 329 if (!this->dimensionsSupported(info.dimensions())) {
271 return kInvalidScale; 330 return kInvalidScale;
272 } 331 }
273 332
274 const Result result = this->onStartScanlineDecode(dstInfo, *options, ctable, ctableCount); 333 const Result result = this->onStartScanlineDecode(info, *options, ctable, ct ableCount);
275 if (result != SkCodec::kSuccess) { 334 if (result != SkCodec::kSuccess) {
276 return result; 335 return result;
277 } 336 }
278 337
279 fCurrScanline = 0; 338 fCurrScanline = 0;
280 fDstInfo = dstInfo; 339 fDstInfo = info;
281 fOptions = *options; 340 fOptions = *options;
282 return kSuccess; 341 return kSuccess;
283 } 342 }
284 343
285 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo) { 344 #undef CHECK_COLOR_TABLE
286 return this->startScanlineDecode(dstInfo, nullptr, nullptr, nullptr); 345
346 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& info) {
347 return this->startScanlineDecode(info, nullptr, nullptr, nullptr);
287 } 348 }
288 349
289 int SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) { 350 int SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) {
290 if (fCurrScanline < 0) { 351 if (fCurrScanline < 0) {
291 return 0; 352 return 0;
292 } 353 }
293 354
294 SkASSERT(!fDstInfo.isEmpty()); 355 SkASSERT(!fDstInfo.isEmpty());
295 if (countLines <= 0 || fCurrScanline + countLines > fDstInfo.height()) { 356 if (countLines <= 0 || fCurrScanline + countLines > fDstInfo.height()) {
296 return 0; 357 return 0;
(...skipping 27 matching lines...) Expand all
324 } 385 }
325 386
326 int SkCodec::outputScanline(int inputScanline) const { 387 int SkCodec::outputScanline(int inputScanline) const {
327 SkASSERT(0 <= inputScanline && inputScanline < this->getInfo().height()); 388 SkASSERT(0 <= inputScanline && inputScanline < this->getInfo().height());
328 return this->onOutputScanline(inputScanline); 389 return this->onOutputScanline(inputScanline);
329 } 390 }
330 391
331 int SkCodec::onOutputScanline(int inputScanline) const { 392 int SkCodec::onOutputScanline(int inputScanline) const {
332 switch (this->getScanlineOrder()) { 393 switch (this->getScanlineOrder()) {
333 case kTopDown_SkScanlineOrder: 394 case kTopDown_SkScanlineOrder:
334 case kNone_SkScanlineOrder:
335 return inputScanline; 395 return inputScanline;
336 case kBottomUp_SkScanlineOrder: 396 case kBottomUp_SkScanlineOrder:
337 return this->getInfo().height() - inputScanline - 1; 397 return this->getInfo().height() - inputScanline - 1;
338 default: 398 default:
339 // This case indicates an interlaced gif and is implemented by SkGif Codec. 399 // This case indicates an interlaced gif and is implemented by SkGif Codec.
340 SkASSERT(false); 400 SkASSERT(false);
341 return 0; 401 return 0;
342 } 402 }
343 } 403 }
344 404
(...skipping 13 matching lines...) Expand all
358 const uint32_t fillValue = this->getFillValue(info.colorType()); 418 const uint32_t fillValue = this->getFillValue(info.colorType());
359 const int linesRemaining = linesRequested - linesDecoded; 419 const int linesRemaining = linesRequested - linesDecoded;
360 SkSampler* sampler = this->getSampler(false); 420 SkSampler* sampler = this->getSampler(false);
361 421
362 int fillWidth = info.width(); 422 int fillWidth = info.width();
363 if (fOptions.fSubset) { 423 if (fOptions.fSubset) {
364 fillWidth = fOptions.fSubset->width(); 424 fillWidth = fOptions.fSubset->width();
365 } 425 }
366 426
367 switch (this->getScanlineOrder()) { 427 switch (this->getScanlineOrder()) {
368 case kTopDown_SkScanlineOrder: 428 case kTopDown_SkScanlineOrder: {
369 case kNone_SkScanlineOrder: {
370 const SkImageInfo fillInfo = info.makeWH(fillWidth, linesRemaining); 429 const SkImageInfo fillInfo = info.makeWH(fillWidth, linesRemaining);
371 fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes); 430 fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes);
372 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler) ; 431 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler) ;
373 break; 432 break;
374 } 433 }
375 case kBottomUp_SkScanlineOrder: { 434 case kBottomUp_SkScanlineOrder: {
376 fillDst = dst; 435 fillDst = dst;
377 const SkImageInfo fillInfo = info.makeWH(fillWidth, linesRemaining); 436 const SkImageInfo fillInfo = info.makeWH(fillWidth, linesRemaining);
378 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler) ; 437 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler) ;
379 break; 438 break;
380 } 439 }
381 case kOutOfOrder_SkScanlineOrder: { 440 case kOutOfOrder_SkScanlineOrder: {
382 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested); 441 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested);
383 const SkImageInfo fillInfo = info.makeWH(fillWidth, 1); 442 const SkImageInfo fillInfo = info.makeWH(fillWidth, 1);
384 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) { 443 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) {
385 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes); 444 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r owBytes);
386 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, samp ler); 445 fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, samp ler);
387 } 446 }
388 break; 447 break;
389 } 448 }
390 } 449 }
391 } 450 }
OLDNEW
« no previous file with comments | « include/codec/SkCodec.h ('k') | src/codec/SkGifCodec.cpp » ('j') | src/codec/SkPngCodec.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698