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

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

Issue 1332053002: Fill incomplete images in SkCodec parent class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Response to Patch Set 11 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_libgif.h" 8 #include "SkCodec_libgif.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 // There should only be one graphics control extension for the image frame 88 // There should only be one graphics control extension for the image frame
89 break; 89 break;
90 } 90 }
91 } 91 }
92 92
93 // Use maximum unsigned int (surely an invalid index) to indicate that a val id 93 // Use maximum unsigned int (surely an invalid index) to indicate that a val id
94 // index was not found. 94 // index was not found.
95 return SK_MaxU32; 95 return SK_MaxU32;
96 } 96 }
97 97
98 static inline uint32_t ceil_div(uint32_t a, uint32_t b) {
99 return (a + b - 1) / b;
100 }
101
102 /*
103 * Gets the output row corresponding to the encoded row for interlaced gifs
104 */
105 static uint32_t get_output_row_interlaced(uint32_t encodedRow, uint32_t height) {
106 SkASSERT(encodedRow < height);
107 // First pass
108 if (encodedRow * 8 < height) {
109 return encodedRow * 8;
110 }
111 // Second pass
112 if (encodedRow * 4 < height) {
113 return 4 + 8 * (encodedRow - ceil_div(height, 8));
114 }
115 // Third pass
116 if (encodedRow * 2 < height) {
117 return 2 + 4 * (encodedRow - ceil_div(height, 4));
118 }
119 // Fourth pass
120 return 1 + 2 * (encodedRow - ceil_div(height, 2));
121 }
122
123 /* 98 /*
124 * This function cleans up the gif object after the decode completes 99 * This function cleans up the gif object after the decode completes
125 * It is used in a SkAutoTCallIProc template 100 * It is used in a SkAutoTCallIProc template
126 */ 101 */
127 void SkGifCodec::CloseGif(GifFileType* gif) { 102 void SkGifCodec::CloseGif(GifFileType* gif) {
128 DGifCloseFile(gif, NULL); 103 DGifCloseFile(gif, NULL);
129 } 104 }
130 105
131 /* 106 /*
132 * This function free extension data that has been saved to assist the image 107 * This function free extension data that has been saved to assist the image
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 ZeroInitialized zeroInit) { 428 ZeroInitialized zeroInit) {
454 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 429 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
455 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, 430 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex,
456 colorPtr, dstInfo, zeroInit)); 431 colorPtr, dstInfo, zeroInit));
457 if (nullptr != fSwizzler.get()) { 432 if (nullptr != fSwizzler.get()) {
458 return kSuccess; 433 return kSuccess;
459 } 434 }
460 return kUnimplemented; 435 return kUnimplemented;
461 } 436 }
462 437
463 SkCodec::Result SkGifCodec::readRow() { 438 bool SkGifCodec::readRow() {
464 if (GIF_ERROR == DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width())) { 439 return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width());
465 return kIncompleteInput;
466 }
467 return kSuccess;
468 } 440 }
469 441
470 /* 442 /*
471 * Initiates the gif decode 443 * Initiates the gif decode
472 */ 444 */
473 SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo, 445 SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
474 void* dst, size_t dstRowBytes, 446 void* dst, size_t dstRowBytes,
475 const Options& opts, 447 const Options& opts,
476 SkPMColor* inputColorPtr, 448 SkPMColor* inputColorPtr,
477 int* inputColorCount) { 449 int* inputColorCount,
450 int* rowsDecoded) {
478 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, opts); 451 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, opts);
479 if (kSuccess != result) { 452 if (kSuccess != result) {
480 return result; 453 return result;
481 } 454 }
482 455
483 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 456 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
484 return gif_error("Scaling not supported.\n", kInvalidScale); 457 return gif_error("Scaling not supported.\n", kInvalidScale);
485 } 458 }
486 459
487 // Initialize the swizzler 460 // Initialize the swizzler
488 if (fFrameIsSubset) { 461 if (fFrameIsSubset) {
489 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); 462 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height());
490 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { 463 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) {
491 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 464 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
492 } 465 }
493 466
494 // Fill the background 467 // Fill the background
495 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 468 SkSampler::Fill(dst, dstInfo, dstRowBytes,
496 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, this->getInfo().height(), 469 this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()),
497 fFillIndex, colorPtr, opts.fZeroInitialized); 470 opts.fZeroInitialized);
498 471
499 // Modify the dst pointer 472 // Modify the dst pointer
500 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype()); 473 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype());
501 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() + 474 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() +
502 dstBytesPerPixel * fFrameRect.left()); 475 dstBytesPerPixel * fFrameRect.left());
503 } else { 476 } else {
504 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { 477 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) {
505 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 478 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
506 } 479 }
507 } 480 }
508 481
509 // Check the interlace flag and iterate over rows of the input 482 // Iterate over rows of the input
510 uint32_t width = fFrameRect.width(); 483 uint32_t width = fFrameRect.width();
511 uint32_t height = fFrameRect.height(); 484 uint32_t height = fFrameRect.height();
512 if (fGif->Image.Interlace) { 485 for (uint32_t y = 0; y < height; y++) {
513 // In interlace mode, the rows of input are rearranged in 486 if (!this->readRow()) {
514 // the output image. We a helper function to help us 487 *rowsDecoded = y;
515 // rearrange the decoded rows. 488 return gif_error("Could not decode line.\n", kIncompleteInput);
516 for (uint32_t y = 0; y < height; y++) {
517 if (kSuccess != this->readRow()) {
518 // Recover from error by filling remainder of image
519 memset(fSrcBuffer.get(), fFillIndex, width);
520 for (; y < height; y++) {
521 void* dstRow = SkTAddOffset<void>(dst,
522 dstRowBytes * get_output_row_interlaced(y, height));
523 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
524 }
525 return gif_error("Could not decode line.\n", kIncompleteInput);
526 }
527 void* dstRow = SkTAddOffset<void>(dst,
528 dstRowBytes * get_output_row_interlaced(y, height));
529 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
530 } 489 }
531 } else { 490 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * this->outputScanlin e(y));
532 // Standard mode 491 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
533 void* dstRow = dst;
534 for (uint32_t y = 0; y < height; y++) {
535 if (kSuccess != this->readRow()) {
536 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
537 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes,
538 height - y, fFillIndex, colorPtr, opts.fZeroInitialized) ;
539 return gif_error("Could not decode line\n", kIncompleteInput);
540 }
541 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
542 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
543 }
544 } 492 }
545 return kSuccess; 493 return kSuccess;
546 } 494 }
547 495
496 uint32_t SkGifCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType ) const {
scroggo 2015/10/08 13:50:30 It looks like there are three classes with similar
msarett 2015/10/08 15:33:25 It won't quite work because gif may have an fFillI
497 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
498 return get_color_table_fill_value(colorType, colorPtr, fFillIndex);
499 }
500
548 SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, 501 SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
549 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count) { 502 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count) {
550 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, 503
551 this->options()); 504 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, this->options());
552 if (kSuccess != result) { 505 if (kSuccess != result) {
553 return result; 506 return result;
554 } 507 }
555 508
556 // Initialize the swizzler 509 // Initialize the swizzler
557 if (fFrameIsSubset) { 510 if (fFrameIsSubset) {
558 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); 511 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height());
559 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { 512 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) {
560 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 513 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
561 } 514 }
562 } else { 515 } else {
563 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { 516 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) {
564 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 517 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
565 } 518 }
566 } 519 }
567 520
568 return kSuccess; 521 return kSuccess;
569 } 522 }
570 523
571 SkCodec::Result SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes ) { 524 int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
525 int rowsBeforeFrame = 0;
526 int rowsAfterFrame = 0;
527 int rowsInFrame = count;
572 if (fFrameIsSubset) { 528 if (fFrameIsSubset) {
573 // Fill the requested rows 529 // Fill the requested rows
574 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 530 SkSampler::Fill(dst, this->dstInfo().makeWH(this->dstInfo().width(), cou nt), rowBytes,
scroggo 2015/10/08 13:50:30 nit: some local variables would probably make this
msarett 2015/10/08 15:33:25 Done.
575 SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, count, fFillIndex, 531 this->onGetFillValue(this->dstInfo().colorType(), this->dstInfo( ).alphaType()),
576 colorPtr, this->options().fZeroInitialized); 532 this->options().fZeroInitialized);
577 533
578 // Do nothing for rows before the image frame 534 // Do nothing for rows before the image frame
579 int rowsBeforeFrame = SkTMax(0, fFrameRect.top() - this->INHERITED::onNe xtScanline()); 535 rowsBeforeFrame = SkTMax(0, fFrameRect.top() - this->INHERITED::nextScan line());
580 count = SkTMax(0, count - rowsBeforeFrame); 536 rowsInFrame = SkTMax(0, rowsInFrame - rowsBeforeFrame);
581 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame); 537 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame);
582 538
583 // Do nothing for rows after the image frame 539 // Do nothing for rows after the image frame
584 int rowsAfterFrame = SkTMax(0, 540 rowsAfterFrame = SkTMax(0,
585 this->INHERITED::onNextScanline() + count - fFrameRect.bottom()) ; 541 this->INHERITED::nextScanline() + rowsInFrame - fFrameRect.botto m());
586 count = SkTMax(0, count - rowsAfterFrame); 542 rowsInFrame = SkTMax(0, rowsInFrame - rowsAfterFrame);
587 543
588 // Adjust dst pointer for left offset 544 // Adjust dst pointer for left offset
589 int offset = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFr ameRect.left(); 545 int offset = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFr ameRect.left();
590 dst = SkTAddOffset<void>(dst, offset); 546 dst = SkTAddOffset<void>(dst, offset);
591 } 547 }
592 548
593 for (int i = 0; i < count; i++) { 549 for (int i = 0; i < rowsInFrame; i++) {
594 if (kSuccess != this->readRow()) { 550 if (!this->readRow()) {
595 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 551 return i + rowsBeforeFrame;
596 SkSwizzler::Fill(dst, this->dstInfo().makeWH(fFrameRect.width(),
597 this->dstInfo().height()), rowBytes, count - i, fFillIndex, colorPtr,
598 this->options().fZeroInitialized);
599 return kIncompleteInput;
600 } 552 }
601 fSwizzler->swizzle(dst, fSrcBuffer.get()); 553 fSwizzler->swizzle(dst, fSrcBuffer.get());
602 dst = SkTAddOffset<void>(dst, rowBytes); 554 dst = SkTAddOffset<void>(dst, rowBytes);
603 } 555 }
604 return kSuccess; 556
557 return count;
605 } 558 }
606 559
607 SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const { 560 SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const {
608 if (fGif->Image.Interlace) { 561 if (fGif->Image.Interlace) {
609 return kOutOfOrder_SkScanlineOrder; 562 return kOutOfOrder_SkScanlineOrder;
610 } else {
611 return kTopDown_SkScanlineOrder;
612 } 563 }
564 return kTopDown_SkScanlineOrder;
613 } 565 }
614 566
615 int SkGifCodec::onNextScanline() const { 567 int SkGifCodec::onOutputScanline(int inputScanline) const {
616 int nextScanline = this->INHERITED::onNextScanline();
617 if (fGif->Image.Interlace) { 568 if (fGif->Image.Interlace) {
618 if (nextScanline < fFrameRect.top() || nextScanline >= fFrameRect.bottom ()) { 569 if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bott om()) {
619 return nextScanline; 570 return inputScanline;
620 } 571 }
621 return get_output_row_interlaced(nextScanline - fFrameRect.top(), fFrame Rect.height()); 572 return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFram eRect.height());
622 } 573 }
623 return nextScanline; 574 return inputScanline;
624 } 575 }
625
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698