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

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

Issue 1010903003: Add scanline decoding to SkCodec. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Cleanups Created 5 years, 9 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_libpng.h" 8 #include "SkCodec_libpng.h"
9 #include "SkColorPriv.h" 9 #include "SkColorPriv.h"
10 #include "SkColorTable.h" 10 #include "SkColorTable.h"
11 #include "SkBitmap.h" 11 #include "SkBitmap.h"
12 #include "SkMath.h" 12 #include "SkMath.h"
13 #include "SkScanlineDecoder.h"
13 #include "SkSize.h" 14 #include "SkSize.h"
14 #include "SkStream.h" 15 #include "SkStream.h"
15 #include "SkSwizzler.h" 16 #include "SkSwizzler.h"
16 17
17 /////////////////////////////////////////////////////////////////////////////// 18 ///////////////////////////////////////////////////////////////////////////////
18 // Helper macros 19 // Helper macros
19 /////////////////////////////////////////////////////////////////////////////// 20 ///////////////////////////////////////////////////////////////////////////////
20 21
21 #ifndef png_jmpbuf 22 #ifndef png_jmpbuf
22 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 23 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); 107 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
107 return num_trans > 0; 108 return num_trans > 0;
108 } 109 }
109 110
110 // Method for coverting to either an SkPMColor or a similarly packed 111 // Method for coverting to either an SkPMColor or a similarly packed
111 // unpremultiplied color. 112 // unpremultiplied color.
112 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); 113 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
113 114
114 // Note: SkColorTable claims to store SkPMColors, which is not necessarily 115 // Note: SkColorTable claims to store SkPMColors, which is not necessarily
115 // the case here. 116 // the case here.
116 SkColorTable* decode_palette(png_structp png_ptr, png_infop info_ptr, 117 bool SkPngCodec::decodePalette(bool premultiply) {
117 bool premultiply, SkAlphaType* outAlphaType) {
118 SkASSERT(outAlphaType != NULL);
119 int numPalette; 118 int numPalette;
120 png_colorp palette; 119 png_colorp palette;
121 png_bytep trans; 120 png_bytep trans;
122 121
123 if (!png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette)) { 122 if (!png_get_PLTE(fPng_ptr, fInfo_ptr, &palette, &numPalette)) {
124 return NULL; 123 return false;
125 } 124 }
126 125
127 /* BUGGY IMAGE WORKAROUND 126 /* BUGGY IMAGE WORKAROUND
128 127
129 We hit some images (e.g. fruit_.png) who contain bytes that are == color table_count 128 We hit some images (e.g. fruit_.png) who contain bytes that are == color table_count
130 which is a problem since we use the byte as an index. To work around thi s we grow 129 which is a problem since we use the byte as an index. To work around thi s we grow
131 the colortable by 1 (if its < 256) and duplicate the last color into tha t slot. 130 the colortable by 1 (if its < 256) and duplicate the last color into tha t slot.
132 */ 131 */
133 const int colorCount = numPalette + (numPalette < 256); 132 const int colorCount = numPalette + (numPalette < 256);
134 // Note: These are not necessarily SkPMColors. 133 // Note: These are not necessarily SkPMColors.
135 SkPMColor colorStorage[256]; // worst-case storage 134 SkPMColor colorStorage[256]; // worst-case storage
136 SkPMColor* colorPtr = colorStorage; 135 SkPMColor* colorPtr = colorStorage;
137 136
138 int numTrans; 137 int numTrans;
139 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { 138 if (png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)) {
140 png_get_tRNS(png_ptr, info_ptr, &trans, &numTrans, NULL); 139 png_get_tRNS(fPng_ptr, fInfo_ptr, &trans, &numTrans, NULL);
141 } else { 140 } else {
142 numTrans = 0; 141 numTrans = 0;
143 } 142 }
144 143
145 // check for bad images that might make us crash 144 // check for bad images that might make us crash
146 if (numTrans > numPalette) { 145 if (numTrans > numPalette) {
147 numTrans = numPalette; 146 numTrans = numPalette;
148 } 147 }
149 148
150 int index = 0; 149 int index = 0;
151 int transLessThanFF = 0; 150 int transLessThanFF = 0;
152 151
153 // Choose which function to use to create the color table. If the final dest ination's 152 // Choose which function to use to create the color table. If the final dest ination's
154 // colortype is unpremultiplied, the color table will store unpremultiplied colors. 153 // colortype is unpremultiplied, the color table will store unpremultiplied colors.
155 PackColorProc proc; 154 PackColorProc proc;
156 if (premultiply) { 155 if (premultiply) {
157 proc = &SkPreMultiplyARGB; 156 proc = &SkPreMultiplyARGB;
158 } else { 157 } else {
159 proc = &SkPackARGB32NoCheck; 158 proc = &SkPackARGB32NoCheck;
160 } 159 }
161 for (; index < numTrans; index++) { 160 for (; index < numTrans; index++) {
162 transLessThanFF |= (int)*trans - 0xFF; 161 transLessThanFF |= (int)*trans - 0xFF;
163 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue ); 162 *colorPtr++ = proc(*trans++, palette->red, palette->green, palette->blue );
164 palette++; 163 palette++;
165 } 164 }
166 165
167 if (transLessThanFF < 0) { 166 fReallyHasAlpha = transLessThanFF < 0;
168 *outAlphaType = premultiply ? kPremul_SkAlphaType : kUnpremul_SkAlphaTyp e;
169 } else {
170 *outAlphaType = kOpaque_SkAlphaType;
171 }
172 167
173 for (; index < numPalette; index++) { 168 for (; index < numPalette; index++) {
174 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette-> blue); 169 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette-> blue);
175 palette++; 170 palette++;
176 } 171 }
177 172
178 // see BUGGY IMAGE WORKAROUND comment above 173 // see BUGGY IMAGE WORKAROUND comment above
179 if (numPalette < 256) { 174 if (numPalette < 256) {
180 *colorPtr = colorPtr[-1]; 175 *colorPtr = colorPtr[-1];
181 } 176 }
182 177
183 return SkNEW_ARGS(SkColorTable, (colorStorage, colorCount)); 178 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorStorage, colorCount)));
179 return true;
184 } 180 }
185 181
186 /////////////////////////////////////////////////////////////////////////////// 182 ///////////////////////////////////////////////////////////////////////////////
187 // Creation 183 // Creation
188 /////////////////////////////////////////////////////////////////////////////// 184 ///////////////////////////////////////////////////////////////////////////////
189 185
190 #define PNG_BYTES_TO_CHECK 4 186 #define PNG_BYTES_TO_CHECK 4
191 187
192 bool SkPngCodec::IsPng(SkStream* stream) { 188 bool SkPngCodec::IsPng(SkStream* stream) {
193 char buf[PNG_BYTES_TO_CHECK]; 189 char buf[PNG_BYTES_TO_CHECK];
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 321
326 // FIXME: Also need to check for sRGB (skbug.com/3471). 322 // FIXME: Also need to check for sRGB (skbug.com/3471).
327 323
328 SkImageInfo info = SkImageInfo::Make(origWidth, origHeight, skColorType, 324 SkImageInfo info = SkImageInfo::Make(origWidth, origHeight, skColorType,
329 skAlphaType); 325 skAlphaType);
330 SkCodec* codec = SkNEW_ARGS(SkPngCodec, (info, stream, png_ptr, info_ptr)); 326 SkCodec* codec = SkNEW_ARGS(SkPngCodec, (info, stream, png_ptr, info_ptr));
331 autoClean.detach(); 327 autoClean.detach();
332 return codec; 328 return codec;
333 } 329 }
334 330
331 #define INVALID_NUMBER_PASSES -1
335 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, 332 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream,
336 png_structp png_ptr, png_infop info_ptr) 333 png_structp png_ptr, png_infop info_ptr)
337 : INHERITED(info, stream) 334 : INHERITED(info, stream)
338 , fPng_ptr(png_ptr) 335 , fPng_ptr(png_ptr)
339 , fInfo_ptr(info_ptr) {} 336 , fInfo_ptr(info_ptr)
337 , fSc(SkSwizzler::kUnknown)
338 , fNumberPasses(INVALID_NUMBER_PASSES)
339 , fReallyHasAlpha(false)
340 {}
340 341
341 SkPngCodec::~SkPngCodec() { 342 SkPngCodec::~SkPngCodec() {
342 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); 343 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL);
343 } 344 }
344 345
345 /////////////////////////////////////////////////////////////////////////////// 346 ///////////////////////////////////////////////////////////////////////////////
346 // Getting the pixels 347 // Getting the pixels
347 /////////////////////////////////////////////////////////////////////////////// 348 ///////////////////////////////////////////////////////////////////////////////
348 349
349 static bool premul_and_unpremul(SkAlphaType A, SkAlphaType B) { 350 static bool premul_and_unpremul(SkAlphaType A, SkAlphaType B) {
350 return kPremul_SkAlphaType == A && kUnpremul_SkAlphaType == B; 351 return kPremul_SkAlphaType == A && kUnpremul_SkAlphaType == B;
351 } 352 }
352 353
353 static bool conversion_possible(const SkImageInfo& A, const SkImageInfo& B) { 354 static bool conversion_possible(const SkImageInfo& A, const SkImageInfo& B) {
354 // TODO: Support other conversions 355 // TODO: Support other conversions
355 if (A.colorType() != B.colorType()) { 356 if (A.colorType() != B.colorType()) {
356 return false; 357 return false;
357 } 358 }
358 if (A.profileType() != B.profileType()) { 359 if (A.profileType() != B.profileType()) {
359 return false; 360 return false;
360 } 361 }
361 if (A.alphaType() == B.alphaType()) { 362 if (A.alphaType() == B.alphaType()) {
362 return true; 363 return true;
363 } 364 }
364 return premul_and_unpremul(A.alphaType(), B.alphaType()) 365 return premul_and_unpremul(A.alphaType(), B.alphaType())
365 || premul_and_unpremul(B.alphaType(), A.alphaType()); 366 || premul_and_unpremul(B.alphaType(), A.alphaType());
366 } 367 }
367 368
368 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst, 369 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, void* dst,
369 size_t rowBytes, SkPMColor ctable[], 370 size_t rowBytes) {
370 int* ctableCount) {
371 if (!this->rewindIfNeeded()) {
372 return kCouldNotRewind;
373 }
374 if (requestedInfo.dimensions() != this->getOriginalInfo().dimensions()) {
375 return kInvalidScale;
376 }
377 if (!conversion_possible(requestedInfo, this->getOriginalInfo())) {
378 return kInvalidConversion;
379 }
380
381 SkBitmap decodedBitmap;
382 // If installPixels would have failed, getPixels should have failed before
383 // calling onGetPixels.
384 SkAssertResult(decodedBitmap.installPixels(requestedInfo, dst, rowBytes));
385
386 // Initialize all non-trivial objects before setjmp.
387 SkAutoTUnref<SkColorTable> colorTable;
388 SkAutoTDelete<SkSwizzler> swizzler;
389 SkAutoMalloc storage; // Scratch memory for pre-swizzled r ows.
390
391 // FIXME: Could we use the return value of setjmp to specify the type of 371 // FIXME: Could we use the return value of setjmp to specify the type of
392 // error? 372 // error?
393 if (setjmp(png_jmpbuf(fPng_ptr))) { 373 if (setjmp(png_jmpbuf(fPng_ptr))) {
394 SkDebugf("setjmp long jump!\n"); 374 SkDebugf("setjmp long jump!\n");
395 return kInvalidInput; 375 return kInvalidInput;
396 } 376 }
397 377
398 // FIXME: We already retrieved this information. Store it in SkPngCodec? 378 // FIXME: We already retrieved this information. Store it in SkPngCodec?
399 png_uint_32 origWidth, origHeight; 379 png_uint_32 origWidth, origHeight;
400 int bitDepth, pngColorType, interlaceType; 380 int bitDepth, pngColorType, interlaceType;
401 png_get_IHDR(fPng_ptr, fInfo_ptr, &origWidth, &origHeight, &bitDepth, 381 png_get_IHDR(fPng_ptr, fInfo_ptr, &origWidth, &origHeight, &bitDepth,
402 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); 382 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL);
403 383
404 const int numberPasses = (interlaceType != PNG_INTERLACE_NONE) ? 384 fNumberPasses = (interlaceType != PNG_INTERLACE_NONE) ?
405 png_set_interlace_handling(fPng_ptr) : 1; 385 png_set_interlace_handling(fPng_ptr) : 1;
406 386
407 SkSwizzler::SrcConfig sc; 387 // Set to the default before calling decodePalette, which may change it.
408 bool reallyHasAlpha = false; 388 fReallyHasAlpha = false;
409 if (PNG_COLOR_TYPE_PALETTE == pngColorType) { 389 if (PNG_COLOR_TYPE_PALETTE == pngColorType) {
410 sc = SkSwizzler::kIndex; 390 fSc = SkSwizzler::kIndex;
411 SkAlphaType at = requestedInfo.alphaType(); 391 if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaType( ))) {
412 colorTable.reset(decode_palette(fPng_ptr, fInfo_ptr,
413 kPremul_SkAlphaType == at,
414 &at));
415 if (!colorTable) {
416 return kInvalidInput; 392 return kInvalidInput;
417 } 393 }
418
419 reallyHasAlpha = (at != kOpaque_SkAlphaType);
420
421 if (at != requestedInfo.alphaType()) {
422 // It turns out the image is opaque.
423 SkASSERT(kOpaque_SkAlphaType == at);
424 }
425 } else if (kAlpha_8_SkColorType == requestedInfo.colorType()) { 394 } else if (kAlpha_8_SkColorType == requestedInfo.colorType()) {
426 // Note: we check the destination, since otherwise we would have 395 // Note: we check the destination, since otherwise we would have
427 // told png to upscale. 396 // told png to upscale.
428 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); 397 SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType);
429 sc = SkSwizzler::kGray; 398 fSc = SkSwizzler::kGray;
430 } else if (this->getOriginalInfo().alphaType() == kOpaque_SkAlphaType) { 399 } else if (this->getOriginalInfo().alphaType() == kOpaque_SkAlphaType) {
431 sc = SkSwizzler::kRGBX; 400 fSc = SkSwizzler::kRGBX;
432 } else { 401 } else {
433 sc = SkSwizzler::kRGBA; 402 fSc = SkSwizzler::kRGBA;
434 } 403 }
435 const SkPMColor* colors = colorTable ? colorTable->readColors() : NULL; 404 const SkPMColor* colors = fColorTable ? fColorTable->readColors() : NULL;
436 // TODO: Support skipZeroes. 405 // TODO: Support skipZeroes.
437 swizzler.reset(SkSwizzler::CreateSwizzler(sc, colors, requestedInfo, 406 fSwizzler.reset(SkSwizzler::CreateSwizzler(fSc, colors, requestedInfo,
438 dst, rowBytes, false)); 407 dst, rowBytes, false));
439 if (!swizzler) { 408 if (!fSwizzler) {
440 // FIXME: CreateSwizzler could fail for another reason. 409 // FIXME: CreateSwizzler could fail for another reason.
441 return kUnimplemented; 410 return kUnimplemented;
442 } 411 }
443 412
444 // FIXME: Here is where we should likely insert some of the modifications 413 // FIXME: Here is where we should likely insert some of the modifications
445 // made in the factory. 414 // made in the factory.
446 png_read_update_info(fPng_ptr, fInfo_ptr); 415 png_read_update_info(fPng_ptr, fInfo_ptr);
447 416
448 if (numberPasses > 1) { 417 return kSuccess;
418 }
419
420 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst,
421 size_t rowBytes, SkPMColor ctable[],
422 int* ctableCount) {
423 if (!this->rewindIfNeeded()) {
424 return kCouldNotRewind;
425 }
426 if (requestedInfo.dimensions() != this->getOriginalInfo().dimensions()) {
427 return kInvalidScale;
428 }
429 if (!conversion_possible(requestedInfo, this->getOriginalInfo())) {
430 return kInvalidConversion;
431 }
432
433 const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes) ;
434 if (result != kSuccess) {
435 return result;
436 }
437
438 // FIXME: Could we use the return value of setjmp to specify the type of
439 // error?
440 if (setjmp(png_jmpbuf(fPng_ptr))) {
441 SkDebugf("setjmp long jump!\n");
442 return kInvalidInput;
443 }
444
445 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES);
446 SkAutoMalloc storage;
447 if (fNumberPasses > 1) {
449 const int width = requestedInfo.width(); 448 const int width = requestedInfo.width();
450 const int height = requestedInfo.height(); 449 const int height = requestedInfo.height();
451 const int bpp = SkSwizzler::BytesPerPixel(sc); 450 const int bpp = SkSwizzler::BytesPerPixel(fSc);
452 const size_t rowBytes = width * bpp; 451 const size_t rowBytes = width * bpp;
453 452
454 storage.reset(width * height * bpp); 453 storage.reset(width * height * bpp);
455 uint8_t* const base = static_cast<uint8_t*>(storage.get()); 454 uint8_t* const base = static_cast<uint8_t*>(storage.get());
456 455
457 for (int i = 0; i < numberPasses; i++) { 456 for (int i = 0; i < fNumberPasses; i++) {
458 uint8_t* row = base; 457 uint8_t* row = base;
459 for (int y = 0; y < height; y++) { 458 for (int y = 0; y < height; y++) {
460 uint8_t* bmRow = row; 459 uint8_t* bmRow = row;
461 png_read_rows(fPng_ptr, &bmRow, png_bytepp_NULL, 1); 460 png_read_rows(fPng_ptr, &bmRow, png_bytepp_NULL, 1);
462 row += rowBytes; 461 row += rowBytes;
463 } 462 }
464 } 463 }
465 464
466 // Now swizzle it. 465 // Now swizzle it.
467 uint8_t* row = base; 466 uint8_t* row = base;
468 for (int y = 0; y < height; y++) { 467 for (int y = 0; y < height; y++) {
469 reallyHasAlpha |= swizzler->next(row); 468 fReallyHasAlpha |= fSwizzler->next(row);
470 row += rowBytes; 469 row += rowBytes;
471 } 470 }
472 } else { 471 } else {
473 storage.reset(requestedInfo.width() * SkSwizzler::BytesPerPixel(sc)); 472 storage.reset(requestedInfo.width() * SkSwizzler::BytesPerPixel(fSc));
474 uint8_t* srcRow = static_cast<uint8_t*>(storage.get()); 473 uint8_t* srcRow = static_cast<uint8_t*>(storage.get());
475 for (int y = 0; y < requestedInfo.height(); y++) { 474 for (int y = 0; y < requestedInfo.height(); y++) {
476 png_read_rows(fPng_ptr, &srcRow, png_bytepp_NULL, 1); 475 png_read_rows(fPng_ptr, &srcRow, png_bytepp_NULL, 1);
477 reallyHasAlpha |= swizzler->next(srcRow); 476 fReallyHasAlpha |= fSwizzler->next(srcRow);
478 } 477 }
479 } 478 }
480 479
480 // FIXME: do we need substituteTranspColor? Note that we cannot do it for
481 // scanline decoding, but we could do it here. Alternatively, we could do
482 // it as we go, instead of in post-processing like SkPNGImageDecoder.
483
484 return this->finish();
485 }
486
487 SkImageGenerator::Result SkPngCodec::finish() {
488 // FIXME: Maybe these should return incomplete?
489 if (setjmp(png_jmpbuf(fPng_ptr))) {
490 SkDebugf("setjmp long jump!\n");
491 return kInvalidInput;
492 }
481 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ 493 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
482 png_read_end(fPng_ptr, fInfo_ptr); 494 png_read_end(fPng_ptr, fInfo_ptr);
483 495
484 // FIXME: do we need substituteTranspColor?
485
486 if (reallyHasAlpha && requestedInfo.alphaType() != kOpaque_SkAlphaType) {
487 // FIXME: We want to alert the caller. Is this the right way?
488 SkImageInfo* modInfo = const_cast<SkImageInfo*>(&requestedInfo);
489 *modInfo = requestedInfo.makeAlphaType(kOpaque_SkAlphaType);
490 }
491 return kSuccess; 496 return kSuccess;
492 } 497 }
498
499 class SkPngScanlineDecoder : public SkScanlineDecoder {
500 public:
501 // FIXME: Need to support subsets...
502 SkPngScanlineDecoder(const SkImageInfo& origInfo, const SkImageInfo& dstInfo ,
503 SkPngCodec* codec)
504 // FIXME: Does SkScanlineDecoder need origInfo? Maybe for subsets?
505 : INHERITED(origInfo, dstInfo)
506 , fDstInfo(dstInfo)
507 , fCodec(codec)
508 , fHasAlpha(false)
509 {
510 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSc)) ;
511 fSrcRow = static_cast<uint8_t*>(fStorage.get());
512 }
513
514 SkImageGenerator::Result onGetNextScanline(void* dst) SK_OVERRIDE {
reed1 2015/03/19 15:31:39 Is it easy to override the N-scanlines method here
scroggo 2015/03/19 17:59:19 Yes.
515 // FIXME: Could we use the return value of setjmp to specify the type of
516 // error?
517 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) {
518 SkDebugf("setjmp long jump!\n");
519 return SkImageGenerator::kInvalidInput;
520 }
521
522 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1);
523 fCodec->fSwizzler->setDstRow(dst);
524 fHasAlpha |= fCodec->fSwizzler->next(fSrcRow);
525 return SkImageGenerator::kSuccess;
526 }
527
528 SkImageGenerator::Result onFinish() SK_OVERRIDE {
529 return fCodec->finish();
530 }
531
532 bool onReallyHasAlpha() const SK_OVERRIDE { return fHasAlpha; }
533
534 private:
535 const SkImageInfo& fDstInfo;
536 SkPngCodec* fCodec; // Unowned.
537 bool fHasAlpha;
538 SkAutoMalloc fStorage;
539 uint8_t* fSrcRow;
540
541 typedef SkScanlineDecoder INHERITED;
542 };
543
544 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo,
545 const SkIRect& origSubset) {
546 // Check to see if scaling was requested.
547 if (dstInfo.dimensions() != origSubset.size()) {
548 SkDebugf("Scaling not supported: dimensions: %d %d\toriginal: %d %d\n",
549 dstInfo.width(), dstInfo.height(),
550 origSubset.width(), origSubset.height());
551 return NULL;
552 }
553
554 if (!conversion_possible(dstInfo, this->getOriginalInfo())) {
555 SkDebugf("no conversion possible\n");
556 return NULL;
557 }
558
559 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee ded,
560 // since we'll be manually updating the dstRow, but the SkSwizzler requires it to
561 // be at least dstInfo.minRowBytes.
562 if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes()) != kSucce ss) {
563 SkDebugf("failed to initialize the swizzler.\n");
564 return NULL;
565 }
566
567 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES);
568 if (fNumberPasses > 1) {
569 // We cannot efficiently do scanline decoding.
570 return NULL;
571 }
572
573 return SkNEW_ARGS(SkPngScanlineDecoder, (this->getOriginalInfo(), dstInfo, t his));
574 }
575
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698