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

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: Use aligned memory in swizzler test 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/SkCodec_libgif.h ('k') | src/codec/SkCodec_libico.h » ('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_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) { 98 inline uint32_t ceil_div(uint32_t a, uint32_t b) {
99 return (a + b - 1) / b; 99 return (a + b - 1) / b;
100 } 100 }
101 101
102 /* 102 /*
103 * Gets the output row corresponding to the encoded row for interlaced gifs 103 * Gets the output row corresponding to the encoded row for interlaced gifs
104 */ 104 */
105 static uint32_t get_output_row_interlaced(uint32_t encodedRow, uint32_t height) { 105 inline uint32_t get_output_row_interlaced(uint32_t encodedRow, uint32_t height) {
106 SkASSERT(encodedRow < height); 106 SkASSERT(encodedRow < height);
107 // First pass 107 // First pass
108 if (encodedRow * 8 < height) { 108 if (encodedRow * 8 < height) {
109 return encodedRow * 8; 109 return encodedRow * 8;
110 } 110 }
111 // Second pass 111 // Second pass
112 if (encodedRow * 4 < height) { 112 if (encodedRow * 4 < height) {
113 return 4 + 8 * (encodedRow - ceil_div(height, 8)); 113 return 4 + 8 * (encodedRow - ceil_div(height, 8));
114 } 114 }
115 // Third pass 115 // Third pass
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 ZeroInitialized zeroInit) { 453 ZeroInitialized zeroInit) {
454 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 454 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
455 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, 455 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex,
456 colorPtr, dstInfo, zeroInit)); 456 colorPtr, dstInfo, zeroInit));
457 if (nullptr != fSwizzler.get()) { 457 if (nullptr != fSwizzler.get()) {
458 return kSuccess; 458 return kSuccess;
459 } 459 }
460 return kUnimplemented; 460 return kUnimplemented;
461 } 461 }
462 462
463 SkCodec::Result SkGifCodec::readRow() { 463 bool SkGifCodec::readRow() {
464 if (GIF_ERROR == DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width())) { 464 return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width());
465 return kIncompleteInput;
466 }
467 return kSuccess;
468 } 465 }
469 466
470 /* 467 /*
471 * Initiates the gif decode 468 * Initiates the gif decode
472 */ 469 */
473 SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo, 470 SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
474 void* dst, size_t dstRowBytes, 471 void* dst, size_t dstRowBytes,
475 const Options& opts, 472 const Options& opts,
476 SkPMColor* inputColorPtr, 473 SkPMColor* inputColorPtr,
477 int* inputColorCount) { 474 int* inputColorCount,
475 int* rowsDecoded) {
478 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, opts); 476 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, opts);
479 if (kSuccess != result) { 477 if (kSuccess != result) {
480 return result; 478 return result;
481 } 479 }
482 480
483 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 481 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
484 return gif_error("Scaling not supported.\n", kInvalidScale); 482 return gif_error("Scaling not supported.\n", kInvalidScale);
485 } 483 }
486 484
487 // Initialize the swizzler 485 // Initialize the swizzler
488 if (fFrameIsSubset) { 486 if (fFrameIsSubset) {
489 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); 487 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height());
490 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { 488 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) {
491 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 489 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
492 } 490 }
493 491
494 // Fill the background 492 // Fill the background
495 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 493 SkSampler::Fill(dstInfo, dst, dstRowBytes,
496 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, this->getInfo().height(), 494 this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()),
497 fFillIndex, colorPtr, opts.fZeroInitialized); 495 opts.fZeroInitialized);
498 496
499 // Modify the dst pointer 497 // Modify the dst pointer
500 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype()); 498 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype());
501 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() + 499 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() +
502 dstBytesPerPixel * fFrameRect.left()); 500 dstBytesPerPixel * fFrameRect.left());
503 } else { 501 } else {
504 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { 502 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) {
505 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 503 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
506 } 504 }
507 } 505 }
508 506
509 // Check the interlace flag and iterate over rows of the input 507 // Iterate over rows of the input
510 uint32_t width = fFrameRect.width();
511 uint32_t height = fFrameRect.height(); 508 uint32_t height = fFrameRect.height();
512 if (fGif->Image.Interlace) { 509 for (uint32_t y = 0; y < height; y++) {
513 // In interlace mode, the rows of input are rearranged in 510 if (!this->readRow()) {
514 // the output image. We a helper function to help us 511 *rowsDecoded = y;
515 // rearrange the decoded rows. 512 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 } 513 }
531 } else { 514 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * this->outputScanlin e(y));
532 // Standard mode 515 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 } 516 }
545 return kSuccess; 517 return kSuccess;
546 } 518 }
547 519
520 // FIXME: This is similar to the implementation for bmp and png. Can we share m ore code or
521 // possibly make this non-virtual?
522 uint32_t SkGifCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType ) const {
523 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
524 return get_color_table_fill_value(colorType, colorPtr, fFillIndex);
525 }
526
548 SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, 527 SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
549 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count) { 528 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count) {
550 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, 529
551 this->options()); 530 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, this->options());
552 if (kSuccess != result) { 531 if (kSuccess != result) {
553 return result; 532 return result;
554 } 533 }
555 534
556 // Initialize the swizzler 535 // Initialize the swizzler
557 if (fFrameIsSubset) { 536 if (fFrameIsSubset) {
558 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height()); 537 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFr ameRect.height());
559 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { 538 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) {
560 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 539 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
561 } 540 }
562 } else { 541 } else {
563 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { 542 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) {
564 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 543 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
565 } 544 }
566 } 545 }
567 546
568 return kSuccess; 547 return kSuccess;
569 } 548 }
570 549
571 SkCodec::Result SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes ) { 550 int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
551 int rowsBeforeFrame = 0;
552 int rowsAfterFrame = 0;
553 int rowsInFrame = count;
572 if (fFrameIsSubset) { 554 if (fFrameIsSubset) {
573 // Fill the requested rows 555 // Fill the requested rows
574 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 556 SkImageInfo fillInfo = this->dstInfo().makeWH(this->dstInfo().width(), c ount);
575 SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, count, fFillIndex, 557 uint32_t fillValue = this->onGetFillValue(this->dstInfo().colorType(),
576 colorPtr, this->options().fZeroInitialized); 558 this->dstInfo().alphaType());
559 SkSampler::Fill(fillInfo, dst, rowBytes, fillValue, this->options().fZer oInitialized);
577 560
578 // Do nothing for rows before the image frame 561 // Do nothing for rows before the image frame
579 int rowsBeforeFrame = SkTMax(0, fFrameRect.top() - this->INHERITED::onNe xtScanline()); 562 rowsBeforeFrame = SkTMax(0, fFrameRect.top() - this->INHERITED::nextScan line());
580 count = SkTMax(0, count - rowsBeforeFrame); 563 rowsInFrame = SkTMax(0, rowsInFrame - rowsBeforeFrame);
581 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame); 564 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame);
582 565
583 // Do nothing for rows after the image frame 566 // Do nothing for rows after the image frame
584 int rowsAfterFrame = SkTMax(0, 567 rowsAfterFrame = SkTMax(0,
585 this->INHERITED::onNextScanline() + count - fFrameRect.bottom()) ; 568 this->INHERITED::nextScanline() + rowsInFrame - fFrameRect.botto m());
586 count = SkTMax(0, count - rowsAfterFrame); 569 rowsInFrame = SkTMax(0, rowsInFrame - rowsAfterFrame);
587 570
588 // Adjust dst pointer for left offset 571 // Adjust dst pointer for left offset
589 int offset = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFr ameRect.left(); 572 int offset = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFr ameRect.left();
590 dst = SkTAddOffset<void>(dst, offset); 573 dst = SkTAddOffset<void>(dst, offset);
591 } 574 }
592 575
593 for (int i = 0; i < count; i++) { 576 for (int i = 0; i < rowsInFrame; i++) {
594 if (kSuccess != this->readRow()) { 577 if (!this->readRow()) {
595 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 578 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 } 579 }
601 fSwizzler->swizzle(dst, fSrcBuffer.get()); 580 fSwizzler->swizzle(dst, fSrcBuffer.get());
602 dst = SkTAddOffset<void>(dst, rowBytes); 581 dst = SkTAddOffset<void>(dst, rowBytes);
603 } 582 }
604 return kSuccess; 583
584 return count;
605 } 585 }
606 586
607 SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const { 587 SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const {
608 if (fGif->Image.Interlace) { 588 if (fGif->Image.Interlace) {
609 return kOutOfOrder_SkScanlineOrder; 589 return kOutOfOrder_SkScanlineOrder;
610 } else {
611 return kTopDown_SkScanlineOrder;
612 } 590 }
591 return kTopDown_SkScanlineOrder;
613 } 592 }
614 593
615 int SkGifCodec::onNextScanline() const { 594 int SkGifCodec::onOutputScanline(int inputScanline) const {
616 int nextScanline = this->INHERITED::onNextScanline();
617 if (fGif->Image.Interlace) { 595 if (fGif->Image.Interlace) {
618 if (nextScanline < fFrameRect.top() || nextScanline >= fFrameRect.bottom ()) { 596 if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bott om()) {
619 return nextScanline; 597 return inputScanline;
620 } 598 }
621 return get_output_row_interlaced(nextScanline - fFrameRect.top(), fFrame Rect.height()); 599 return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFram eRect.height());
622 } 600 }
623 return nextScanline; 601 return inputScanline;
624 } 602 }
625
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libgif.h ('k') | src/codec/SkCodec_libico.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698