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

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

Issue 1055743003: Swizzler changes Index8 and 565 (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 8 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_libbmp.h" 8 #include "SkCodec_libbmp.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
11 #include "SkStream.h" 11 #include "SkStream.h"
12 12
13 /* 13 /*
14 * 14 *
15 * Checks if the conversion between the input image and the requested output 15 * Checks if the conversion between the input image and the requested output
16 * image has been implemented 16 * image has been implemented
17 * 17 *
18 */ 18 */
19 static bool conversion_possible(const SkImageInfo& dst, 19 static bool conversion_possible(const SkImageInfo& dst,
20 const SkImageInfo& src) { 20 const SkImageInfo& src) {
21 // Ensure that the profile type is unchanged 21 // Ensure that the profile type is unchanged
22 if (dst.profileType() != src.profileType()) { 22 if (dst.profileType() != src.profileType()) {
23 return false; 23 return false;
24 } 24 }
25 25
26 // Check for supported color and alpha types 26 // Check for supported alpha types
27 if (src.alphaType() != dst.alphaType() &&
28 (kPremul_SkAlphaType != dst.alphaType() ||
29 kUnpremul_SkAlphaType == src.alphaType())) {
30 return false;
31 }
32
33 // Check for supported color types
27 switch (dst.colorType()) { 34 switch (dst.colorType()) {
35 // Allow output to kN32 from any type of input
28 case kN32_SkColorType: 36 case kN32_SkColorType:
29 return src.alphaType() == dst.alphaType() || 37 return true;
30 (kPremul_SkAlphaType == dst.alphaType() && 38 // Allow output to kIndex_8 from compatible inputs
31 kUnpremul_SkAlphaType == src.alphaType()); 39 case kIndex_8_SkColorType:
40 return kIndex_8_SkColorType == src.colorType();
32 default: 41 default:
33 return false; 42 return false;
34 } 43 }
35 } 44 }
36 45
37 /* 46 /*
38 * 47 *
39 * Defines the version and type of the second bitmap header 48 * Defines the version and type of the second bitmap header
40 * 49 *
41 */ 50 */
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 // Header types are matched based on size. If the header is 421 // Header types are matched based on size. If the header is
413 // V3+, we are guaranteed to be able to read at least this size. 422 // V3+, we are guaranteed to be able to read at least this size.
414 SkASSERT(infoBytesRemaining > 52); 423 SkASSERT(infoBytesRemaining > 52);
415 inputMasks.alpha = get_int(iBuffer.get(), 48); 424 inputMasks.alpha = get_int(iBuffer.get(), 48);
416 if (inputMasks.alpha != 0) { 425 if (inputMasks.alpha != 0) {
417 alphaType = kUnpremul_SkAlphaType; 426 alphaType = kUnpremul_SkAlphaType;
418 } 427 }
419 } 428 }
420 iBuffer.free(); 429 iBuffer.free();
421 430
422 // Additionally, 32 bit bmp-in-icos use the alpha channel 431 // Additionally, 32 bit bmp-in-icos use the alpha channel.
423 if (isIco && 32 == bitsPerPixel) { 432 // And, RLE inputs may skip pixels, leaving them as transparent. This
433 // is uncommon, but we cannot be certain that an RLE bmp will be opaque.
434 if ((isIco && 32 == bitsPerPixel) || (kRLE_BitmapInputFormat == inputFormat) ) {
424 alphaType = kUnpremul_SkAlphaType; 435 alphaType = kUnpremul_SkAlphaType;
425 } 436 }
426 437
427 // Check for valid bits per pixel input 438 // Check for valid bits per pixel.
439 // At the same time, use this information to choose a suggested color type
440 // and to set default masks.
441 SkColorType colorType = kN32_SkColorType;
428 switch (bitsPerPixel) { 442 switch (bitsPerPixel) {
429 // In addition to more standard pixel compression formats, bmp supports 443 // In addition to more standard pixel compression formats, bmp supports
430 // the use of bit masks to determine pixel components. The standard 444 // the use of bit masks to determine pixel components. The standard
431 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB), 445 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
432 // which does not map well to any Skia color formats. For this reason, 446 // which does not map well to any Skia color formats. For this reason,
433 // we will always enable mask mode with 16 bits per pixel. 447 // we will always enable mask mode with 16 bits per pixel.
434 case 16: 448 case 16:
435 if (kBitMask_BitmapInputFormat != inputFormat) { 449 if (kBitMask_BitmapInputFormat != inputFormat) {
436 inputMasks.red = 0x7C00; 450 inputMasks.red = 0x7C00;
437 inputMasks.green = 0x03E0; 451 inputMasks.green = 0x03E0;
438 inputMasks.blue = 0x001F; 452 inputMasks.blue = 0x001F;
439 inputFormat = kBitMask_BitmapInputFormat; 453 inputFormat = kBitMask_BitmapInputFormat;
440 } 454 }
441 break; 455 break;
456 // We want to decode to kIndex_8 for input formats that are already
457 // designed in index format.
442 case 1: 458 case 1:
443 case 2: 459 case 2:
444 case 4: 460 case 4:
445 case 8: 461 case 8:
462 // However, we cannot in RLE format since we may need to leave s ome
scroggo 2015/04/02 19:20:30 It seems a shame that we cannot support this. It s
msarett 2015/04/03 18:01:32 Agreed. Wish there was a good way.
463 // pixels as transparent. Similarly, we also cannot for ICO ima ges
464 // since we may need to apply a transparent mask.
465 if (kRLE_BitmapInputFormat != inputFormat && !isIco) {
466 colorType = kIndex_8_SkColorType;
467 }
446 case 24: 468 case 24:
447 case 32: 469 case 32:
448 break; 470 break;
449 default: 471 default:
450 SkCodecPrintf("Error: invalid input value for bits per pixel.\n"); 472 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
451 return false; 473 return false;
452 } 474 }
453 475
454 // Check that input bit masks are valid and create the masks object 476 // Check that input bit masks are valid and create the masks object
455 SkAutoTDelete<SkMasks> 477 SkAutoTDelete<SkMasks>
(...skipping 12 matching lines...) Expand all
468 490
469 // Calculate the number of bytes read so far 491 // Calculate the number of bytes read so far
470 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; 492 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
471 if (!isIco && offset < bytesRead) { 493 if (!isIco && offset < bytesRead) {
472 SkCodecPrintf("Error: pixel data offset less than header size.\n"); 494 SkCodecPrintf("Error: pixel data offset less than header size.\n");
473 return false; 495 return false;
474 } 496 }
475 497
476 if (codecOut) { 498 if (codecOut) {
477 // Return the codec 499 // Return the codec
478 // We will use ImageInfo to store width, height, and alpha type. We 500 // We will use ImageInfo to store width, height, suggested color type, a nd
479 // will set color type to kN32_SkColorType because that should be the 501 // suggested alpha type.
480 // default output.
481 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, 502 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
482 kN32_SkColorType, alphaType); 503 colorType, alphaType);
483 *codecOut = SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, 504 *codecOut = SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
484 inputFormat, masks.detach(), 505 inputFormat, masks.detach(),
485 numColors, bytesPerColor, 506 numColors, bytesPerColor,
486 offset - bytesRead, rowOrder, 507 offset - bytesRead, rowOrder,
487 RLEBytes, isIco)); 508 RLEBytes, isIco));
488 } 509 }
489 return true; 510 return true;
490 } 511 }
491 512
492 /* 513 /*
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 549
529 {} 550 {}
530 551
531 /* 552 /*
532 * 553 *
533 * Initiates the bitmap decode 554 * Initiates the bitmap decode
534 * 555 *
535 */ 556 */
536 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, 557 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
537 void* dst, size_t dstRowBytes, 558 void* dst, size_t dstRowBytes,
538 const Options&, 559 const Options& opts,
539 SkPMColor*, int*) { 560 SkPMColor* inputColorPtr,
561 int* inputColorCount) {
540 // Check for proper input and output formats 562 // Check for proper input and output formats
541 SkCodec::RewindState rewindState = this->rewindIfNeeded(); 563 SkCodec::RewindState rewindState = this->rewindIfNeeded();
542 if (rewindState == kCouldNotRewind_RewindState) { 564 if (rewindState == kCouldNotRewind_RewindState) {
543 return kCouldNotRewind; 565 return kCouldNotRewind;
544 } else if (rewindState == kRewound_RewindState) { 566 } else if (rewindState == kRewound_RewindState) {
545 if (!ReadHeader(this->stream(), fIsIco, NULL)) { 567 if (!ReadHeader(this->stream(), fIsIco, NULL)) {
546 return kCouldNotRewind; 568 return kCouldNotRewind;
547 } 569 }
548 } 570 }
549 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 571 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
550 SkCodecPrintf("Error: scaling not supported.\n"); 572 SkCodecPrintf("Error: scaling not supported.\n");
551 return kInvalidScale; 573 return kInvalidScale;
552 } 574 }
553 if (!conversion_possible(dstInfo, this->getInfo())) { 575 if (!conversion_possible(dstInfo, this->getInfo())) {
554 SkCodecPrintf("Error: cannot convert input type to output type.\n"); 576 SkCodecPrintf("Error: cannot convert input type to output type.\n");
555 return kInvalidConversion; 577 return kInvalidConversion;
556 } 578 }
557 579
580 // Get a color table pointer
581 SkPMColor alternateColorPtr[256];
582 fColorTable = get_color_table_ptr(dstInfo.colorType(), inputColorPtr,
scroggo 2015/04/02 19:20:31 This seems fragile. You are setting a pointer fiel
msarett 2015/04/03 18:01:32 Yeah that concerned me as well. I think the new a
583 inputColorCount, alternateColorPtr);
584
558 // Create the color table if necessary and prepare the stream for decode 585 // Create the color table if necessary and prepare the stream for decode
559 if (!createColorTable(dstInfo.alphaType())) { 586 if (!createColorTable(dstInfo.alphaType())) {
560 SkCodecPrintf("Error: could not create color table.\n"); 587 SkCodecPrintf("Error: could not create color table.\n");
561 return kInvalidInput; 588 return kInvalidInput;
562 } 589 }
563 590
564 // Perform the decode 591 // Perform the decode
565 switch (fInputFormat) { 592 switch (fInputFormat) {
566 case kBitMask_BitmapInputFormat: 593 case kBitMask_BitmapInputFormat:
567 return decodeMask(dstInfo, dst, dstRowBytes); 594 return decodeMask(dstInfo, dst, dstRowBytes);
568 case kRLE_BitmapInputFormat: 595 case kRLE_BitmapInputFormat:
569 return decodeRLE(dstInfo, dst, dstRowBytes); 596 return decodeRLE(dstInfo, dst, dstRowBytes, opts);
570 case kStandard_BitmapInputFormat: 597 case kStandard_BitmapInputFormat:
571 return decode(dstInfo, dst, dstRowBytes); 598 return decode(dstInfo, dst, dstRowBytes);
572 default: 599 default:
573 SkASSERT(false); 600 SkASSERT(false);
574 return kInvalidInput; 601 return kInvalidInput;
575 } 602 }
576 } 603 }
577 604
578 /* 605 /*
579 * 606 *
580 * Process the color table for the bmp input 607 * Process the color table for the bmp input
581 * 608 *
582 */ 609 */
583 bool SkBmpCodec::createColorTable(SkAlphaType alphaType) { 610 bool SkBmpCodec::createColorTable(SkAlphaType alphaType) {
584 // Allocate memory for color table 611 // Allocate memory for color table
585 uint32_t colorBytes = 0; 612 uint32_t colorBytes = 0;
586 uint32_t maxColors = 0; 613 uint32_t maxColors = 0;
587 SkPMColor colorTable[256];
588 if (fBitsPerPixel <= 8) { 614 if (fBitsPerPixel <= 8) {
589 // Zero is a default for maxColors 615 // Zero is a default for maxColors
590 // Also set fNumColors to maxColors when it is too large 616 // Also set fNumColors to maxColors when it is too large
591 maxColors = 1 << fBitsPerPixel; 617 maxColors = 1 << fBitsPerPixel;
592 if (fNumColors == 0 || fNumColors >= maxColors) { 618 if (fNumColors == 0 || fNumColors >= maxColors) {
593 fNumColors = maxColors; 619 fNumColors = maxColors;
594 } 620 }
595 621
596 // Read the color table from the stream 622 // Read the color table from the stream
597 colorBytes = fNumColors * fBytesPerColor; 623 colorBytes = fNumColors * fBytesPerColor;
(...skipping 24 matching lines...) Expand all
622 648
623 // Fill in the color table 649 // Fill in the color table
624 uint32_t i = 0; 650 uint32_t i = 0;
625 for (; i < fNumColors; i++) { 651 for (; i < fNumColors; i++) {
626 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor); 652 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor);
627 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1); 653 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1);
628 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2); 654 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2);
629 uint8_t alpha = kOpaque_SkAlphaType == alphaType ? 0xFF : 655 uint8_t alpha = kOpaque_SkAlphaType == alphaType ? 0xFF :
630 (fMasks->getAlphaMask() >> 24) & 656 (fMasks->getAlphaMask() >> 24) &
631 get_byte(cBuffer.get(), i*fBytesPerColor + 3); 657 get_byte(cBuffer.get(), i*fBytesPerColor + 3);
632 colorTable[i] = packARGB(alpha, red, green, blue); 658 fColorTable[i] = packARGB(alpha, red, green, blue);
633 } 659 }
634 660
635 // To avoid segmentation faults on bad pixel data, fill the end of the 661 // To avoid segmentation faults on bad pixel data, fill the end of the
636 // color table with black. This is the same the behavior as the 662 // color table with black. This is the same the behavior as the
637 // chromium decoder. 663 // chromium decoder.
638 for (; i < maxColors; i++) { 664 for (; i < maxColors; i++) {
639 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); 665 fColorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
640 } 666 }
641 } 667 }
642 668
643 // Bmp-in-Ico files do not use an offset to indicate where the pixel data 669 // Bmp-in-Ico files do not use an offset to indicate where the pixel data
644 // begins. Pixel data always begins immediately after the color table. 670 // begins. Pixel data always begins immediately after the color table.
645 if (!fIsIco) { 671 if (!fIsIco) {
646 // Check that we have not read past the pixel array offset 672 // Check that we have not read past the pixel array offset
647 if(fOffset < colorBytes) { 673 if(fOffset < colorBytes) {
648 // This may occur on OS 2.1 and other old versions where the color 674 // This may occur on OS 2.1 and other old versions where the color
649 // table defaults to max size, and the bmp tries to use a smaller 675 // table defaults to max size, and the bmp tries to use a smaller
650 // color table. This is invalid, and our decision is to indicate 676 // color table. This is invalid, and our decision is to indicate
651 // an error, rather than try to guess the intended size of the 677 // an error, rather than try to guess the intended size of the
652 // color table. 678 // color table.
653 SkCodecPrintf("Error: pixel data offset less than color table size.\ n"); 679 SkCodecPrintf("Error: pixel data offset less than color table size.\ n");
654 return false; 680 return false;
655 } 681 }
656 682
657 // After reading the color table, skip to the start of the pixel array 683 // After reading the color table, skip to the start of the pixel array
658 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { 684 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) {
659 SkCodecPrintf("Error: unable to skip to image data.\n"); 685 SkCodecPrintf("Error: unable to skip to image data.\n");
660 return false; 686 return false;
661 } 687 }
662 } 688 }
663 689
664 // Set the color table and return true on success 690 // Return true on success
665 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors)));
666 return true; 691 return true;
667 } 692 }
668 693
669 /* 694 /*
670 * 695 *
671 * Performs the bitmap decoding for bit masks input format 696 * Performs the bitmap decoding for bit masks input format
672 * 697 *
673 */ 698 */
674 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo, 699 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
675 void* dst, size_t dstRowBytes) { 700 void* dst, size_t dstRowBytes) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 752
728 // Finished decoding the entire image 753 // Finished decoding the entire image
729 return kSuccess; 754 return kSuccess;
730 } 755 }
731 756
732 /* 757 /*
733 * 758 *
734 * Set an RLE pixel using the color table 759 * Set an RLE pixel using the color table
735 * 760 *
736 */ 761 */
737 void SkBmpCodec::setRLEPixel(SkPMColor* dst, size_t dstRowBytes, 762 void SkBmpCodec::setRLEPixel(void* dst, size_t dstRowBytes,
738 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, 763 const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
739 uint8_t index) { 764 uint8_t index) {
740 // Set the row 765 // Set the row
741 int height = dstInfo.height(); 766 int height = dstInfo.height();
742 int row; 767 int row;
743 if (kBottomUp_RowOrder == fRowOrder) { 768 if (kBottomUp_RowOrder == fRowOrder) {
744 row = height - y - 1; 769 row = height - y - 1;
745 } else { 770 } else {
746 row = y; 771 row = y;
747 } 772 }
748 773
749 // Set the pixel based on destination color type 774 // Set the pixel based on destination color type
750 switch (dstInfo.colorType()) { 775 switch (dstInfo.colorType()) {
751 case kN32_SkColorType: { 776 case kN32_SkColorType: {
752 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, 777 SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst,
753 row * (int) dstRowBytes); 778 row * (int) dstRowBytes);
754 dstRow[x] = fColorTable->operator[](index); 779 dstRow[x] = fColorTable[index];
755 break;
756 }
757 case kRGB_565_SkColorType: {
758 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst,
759 row * (int) dstRowBytes);
760 dstRow[x] = SkPixel32ToPixel16(fColorTable->operator[](index));
761 break; 780 break;
762 } 781 }
763 default: 782 default:
764 // This case should not be reached. We should catch an invalid 783 // This case should not be reached. We should catch an invalid
765 // color type when we check that the conversion is possible. 784 // color type when we check that the conversion is possible.
766 SkASSERT(false); 785 SkASSERT(false);
767 break; 786 break;
768 } 787 }
769 } 788 }
770 789
771 /* 790 /*
772 * 791 *
773 * Set an RLE pixel from R, G, B values 792 * Set an RLE pixel from R, G, B values
774 * 793 *
775 */ 794 */
776 void SkBmpCodec::setRLE24Pixel(SkPMColor* dst, size_t dstRowBytes, 795 void SkBmpCodec::setRLE24Pixel(void* dst, size_t dstRowBytes,
777 const SkImageInfo& dstInfo, uint32_t x, 796 const SkImageInfo& dstInfo, uint32_t x,
778 uint32_t y, uint8_t red, uint8_t green, 797 uint32_t y, uint8_t red, uint8_t green,
779 uint8_t blue) { 798 uint8_t blue) {
780 // Set the row 799 // Set the row
781 int height = dstInfo.height(); 800 int height = dstInfo.height();
782 int row; 801 int row;
783 if (kBottomUp_RowOrder == fRowOrder) { 802 if (kBottomUp_RowOrder == fRowOrder) {
784 row = height - y - 1; 803 row = height - y - 1;
785 } else { 804 } else {
786 row = y; 805 row = y;
787 } 806 }
788 807
789 // Set the pixel based on destination color type 808 // Set the pixel based on destination color type
790 switch (dstInfo.colorType()) { 809 switch (dstInfo.colorType()) {
791 case kN32_SkColorType: { 810 case kN32_SkColorType: {
792 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, 811 SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst,
793 row * (int) dstRowBytes); 812 row * (int) dstRowBytes);
794 dstRow[x] = SkPackARGB32NoCheck(0xFF, red, green, blue); 813 dstRow[x] = SkPackARGB32NoCheck(0xFF, red, green, blue);
795 break; 814 break;
796 } 815 }
797 case kRGB_565_SkColorType: {
798 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst,
799 row * (int) dstRowBytes);
800 dstRow[x] = SkPack888ToRGB16(red, green, blue);
801 break;
802 }
803 default: 816 default:
804 // This case should not be reached. We should catch an invalid 817 // This case should not be reached. We should catch an invalid
805 // color type when we check that the conversion is possible. 818 // color type when we check that the conversion is possible.
806 SkASSERT(false); 819 SkASSERT(false);
807 break; 820 break;
808 } 821 }
809 } 822 }
810 823
811 /* 824 /*
812 * 825 *
813 * Performs the bitmap decoding for RLE input format 826 * Performs the bitmap decoding for RLE input format
814 * RLE decoding is performed all at once, rather than a one row at a time 827 * RLE decoding is performed all at once, rather than a one row at a time
815 * 828 *
816 */ 829 */
817 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo, 830 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
818 void* dst, size_t dstRowBytes) { 831 void* dst, size_t dstRowBytes,
832 const Options& opts) {
819 // Set RLE flags 833 // Set RLE flags
820 static const uint8_t RLE_ESCAPE = 0; 834 static const uint8_t RLE_ESCAPE = 0;
821 static const uint8_t RLE_EOL = 0; 835 static const uint8_t RLE_EOL = 0;
822 static const uint8_t RLE_EOF = 1; 836 static const uint8_t RLE_EOF = 1;
823 static const uint8_t RLE_DELTA = 2; 837 static const uint8_t RLE_DELTA = 2;
824 838
825 // Set constant values 839 // Set constant values
826 const int width = dstInfo.width(); 840 const int width = dstInfo.width();
827 const int height = dstInfo.height(); 841 const int height = dstInfo.height();
828 842
829 // Input buffer parameters 843 // Input buffer parameters
830 uint32_t currByte = 0; 844 uint32_t currByte = 0;
831 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes)); 845 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes));
832 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes); 846 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes);
833 if (totalBytes < fRLEBytes) { 847 if (totalBytes < fRLEBytes) {
834 SkCodecPrintf("Warning: incomplete RLE file.\n"); 848 SkCodecPrintf("Warning: incomplete RLE file.\n");
835 } else if (totalBytes <= 0) { 849 } else if (totalBytes <= 0) {
836 SkCodecPrintf("Error: could not read RLE image data.\n"); 850 SkCodecPrintf("Error: could not read RLE image data.\n");
837 return kInvalidInput; 851 return kInvalidInput;
838 } 852 }
839 853
840 // Destination parameters 854 // Destination parameters
841 int x = 0; 855 int x = 0;
842 int y = 0; 856 int y = 0;
843 // If the code skips pixels, remaining pixels are transparent or black 857
844 // TODO: Skip this if memory was already zeroed. 858 // Set the background as transparent. Then, if the RLE code skips pixels,
845 memset(dst, 0, dstRowBytes * height); 859 // the skipped pixels will be transparent.
846 SkPMColor* dstPtr = (SkPMColor*) dst; 860 // Because of the need for transparent pixels, kN32 is the only color
861 // type that makes sense for the destination format.
862 SkASSERT(kN32_SkColorType == dstInfo.colorType());
863 if (kYes_ZeroInitialized == opts.fZeroInitialized) {
scroggo 2015/04/02 19:20:30 kNo_ZeroInitialized. If it's already zero initial
msarett 2015/04/03 18:01:32 Of course!
864 memset(dst, 0, dstRowBytes * height);
scroggo 2015/04/02 19:20:30 Ooh, I missed this on an earlier review. We allow
msarett 2015/04/03 18:01:32 Good to know! I don't think this is the only plac
865 }
847 866
848 while (true) { 867 while (true) {
849 // Every entry takes at least two bytes 868 // Every entry takes at least two bytes
850 if ((int) totalBytes - currByte < 2) { 869 if ((int) totalBytes - currByte < 2) {
851 SkCodecPrintf("Warning: incomplete RLE input.\n"); 870 SkCodecPrintf("Warning: incomplete RLE input.\n");
852 return kIncompleteInput; 871 return kIncompleteInput;
853 } 872 }
854 873
855 // Read the next two bytes. These bytes have different meanings 874 // Read the next two bytes. These bytes have different meanings
856 // depending on their values. In the first interpretation, the first 875 // depending on their values. In the first interpretation, the first
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
907 (int) totalBytes - currByte < SkAlign2(rowBytes)) { 926 (int) totalBytes - currByte < SkAlign2(rowBytes)) {
908 SkCodecPrintf("Warning: invalid RLE input.\n"); 927 SkCodecPrintf("Warning: invalid RLE input.\n");
909 return kIncompleteInput; 928 return kIncompleteInput;
910 } 929 }
911 // Set numPixels number of pixels 930 // Set numPixels number of pixels
912 while (numPixels > 0) { 931 while (numPixels > 0) {
913 switch(fBitsPerPixel) { 932 switch(fBitsPerPixel) {
914 case 4: { 933 case 4: {
915 SkASSERT(currByte < totalBytes); 934 SkASSERT(currByte < totalBytes);
916 uint8_t val = buffer.get()[currByte++]; 935 uint8_t val = buffer.get()[currByte++];
917 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++, 936 setRLEPixel(dst, dstRowBytes, dstInfo, x++,
918 y, val >> 4); 937 y, val >> 4);
919 numPixels--; 938 numPixels--;
920 if (numPixels != 0) { 939 if (numPixels != 0) {
921 setRLEPixel(dstPtr, dstRowBytes, dstInfo, 940 setRLEPixel(dst, dstRowBytes, dstInfo,
922 x++, y, val & 0xF); 941 x++, y, val & 0xF);
923 numPixels--; 942 numPixels--;
924 } 943 }
925 break; 944 break;
926 } 945 }
927 case 8: 946 case 8:
928 SkASSERT(currByte < totalBytes); 947 SkASSERT(currByte < totalBytes);
929 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++, 948 setRLEPixel(dst, dstRowBytes, dstInfo, x++,
930 y, buffer.get()[currByte++]); 949 y, buffer.get()[currByte++]);
931 numPixels--; 950 numPixels--;
932 break; 951 break;
933 case 24: { 952 case 24: {
934 SkASSERT(currByte + 2 < totalBytes); 953 SkASSERT(currByte + 2 < totalBytes);
935 uint8_t blue = buffer.get()[currByte++]; 954 uint8_t blue = buffer.get()[currByte++];
936 uint8_t green = buffer.get()[currByte++]; 955 uint8_t green = buffer.get()[currByte++];
937 uint8_t red = buffer.get()[currByte++]; 956 uint8_t red = buffer.get()[currByte++];
938 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, 957 setRLE24Pixel(dst, dstRowBytes, dstInfo,
939 x++, y, red, green, blue); 958 x++, y, red, green, blue);
940 numPixels--; 959 numPixels--;
941 } 960 }
942 default: 961 default:
943 SkASSERT(false); 962 SkASSERT(false);
944 return kInvalidInput; 963 return kInvalidInput;
945 } 964 }
946 } 965 }
947 // Skip a byte if necessary to maintain alignment 966 // Skip a byte if necessary to maintain alignment
948 if (!SkIsAlign2(rowBytes)) { 967 if (!SkIsAlign2(rowBytes)) {
(...skipping 15 matching lines...) Expand all
964 if ((int) totalBytes - currByte < 2) { 983 if ((int) totalBytes - currByte < 2) {
965 SkCodecPrintf("Warning: incomplete RLE input\n"); 984 SkCodecPrintf("Warning: incomplete RLE input\n");
966 return kIncompleteInput; 985 return kIncompleteInput;
967 } 986 }
968 987
969 // Fill the pixels up to endX with the specified color 988 // Fill the pixels up to endX with the specified color
970 uint8_t blue = task; 989 uint8_t blue = task;
971 uint8_t green = buffer.get()[currByte++]; 990 uint8_t green = buffer.get()[currByte++];
972 uint8_t red = buffer.get()[currByte++]; 991 uint8_t red = buffer.get()[currByte++];
973 while (x < endX) { 992 while (x < endX) {
974 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, x++, y, red, 993 setRLE24Pixel(dst, dstRowBytes, dstInfo, x++, y, red,
975 green, blue); 994 green, blue);
976 } 995 }
977 } else { 996 } else {
978 // In RLE8 or RLE4, the second byte read gives the index in the 997 // In RLE8 or RLE4, the second byte read gives the index in the
979 // color table to look up the pixel color. 998 // color table to look up the pixel color.
980 // RLE8 has one color index that gets repeated 999 // RLE8 has one color index that gets repeated
981 // RLE4 has two color indexes in the upper and lower 4 bits of 1000 // RLE4 has two color indexes in the upper and lower 4 bits of
982 // the bytes, which are alternated 1001 // the bytes, which are alternated
983 uint8_t indices[2] = { task, task }; 1002 uint8_t indices[2] = { task, task };
984 if (4 == fBitsPerPixel) { 1003 if (4 == fBitsPerPixel) {
985 indices[0] >>= 4; 1004 indices[0] >>= 4;
986 indices[1] &= 0xf; 1005 indices[1] &= 0xf;
987 } 1006 }
988 1007
989 // Set the indicated number of pixels 1008 // Set the indicated number of pixels
990 for (int which = 0; x < endX; x++) { 1009 for (int which = 0; x < endX; x++) {
991 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x, y, 1010 setRLEPixel(dst, dstRowBytes, dstInfo, x, y,
992 indices[which]); 1011 indices[which]);
993 which = !which; 1012 which = !which;
994 } 1013 }
995 } 1014 }
996 } 1015 }
997 } 1016 }
998 } 1017 }
999 1018
1000 /* 1019 /*
1001 * 1020 *
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 config = SkSwizzler::kBGRA; 1053 config = SkSwizzler::kBGRA;
1035 } 1054 }
1036 break; 1055 break;
1037 default: 1056 default:
1038 SkASSERT(false); 1057 SkASSERT(false);
1039 return kInvalidInput; 1058 return kInvalidInput;
1040 } 1059 }
1041 1060
1042 // Create swizzler 1061 // Create swizzler
1043 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config, 1062 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config,
1044 fColorTable->readColors(), dstInfo, dst, dstRowBytes, 1063 fColorTable, dstInfo, dst, dstRowBytes,
1045 SkImageGenerator::kNo_ZeroInitialized)); 1064 SkImageGenerator::kNo_ZeroInitialized));
1046 1065
1047 // Allocate space for a row buffer and a source for the swizzler 1066 // Allocate space for a row buffer and a source for the swizzler
1048 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); 1067 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
1049 1068
1050 // Iterate over rows of the image 1069 // Iterate over rows of the image
1051 // FIXME: bool transparent = true; 1070 // FIXME: bool transparent = true;
1052 for (int y = 0; y < height; y++) { 1071 for (int y = 0; y < height; y++) {
1053 // Read a row of the input 1072 // Read a row of the input
1054 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { 1073 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
(...skipping 16 matching lines...) Expand all
1071 } 1090 }
1072 1091
1073 // FIXME: This code exists to match the behavior in the chromium decoder 1092 // FIXME: This code exists to match the behavior in the chromium decoder
1074 // and to follow the bmp specification as it relates to alpha masks. It is 1093 // and to follow the bmp specification as it relates to alpha masks. It is
1075 // commented out because we have yet to discover a test image that provides 1094 // commented out because we have yet to discover a test image that provides
1076 // an alpha mask and uses this decode mode. 1095 // an alpha mask and uses this decode mode.
1077 1096
1078 // Now we adjust the output image with some additional behavior that 1097 // Now we adjust the output image with some additional behavior that
1079 // SkSwizzler does not support. Firstly, all bmp images that contain 1098 // SkSwizzler does not support. Firstly, all bmp images that contain
1080 // alpha are masked by the alpha mask. Secondly, many fully transparent 1099 // alpha are masked by the alpha mask. Secondly, many fully transparent
1081 // bmp images are intended to be opaque. Here, we make those corrections. 1100 // bmp images are intended to be opaque. Here, we make those corrections
1101 // in the kN32 case.
1082 /* 1102 /*
1083 SkPMColor* dstRow = (SkPMColor*) dst; 1103 SkPMColor* dstRow = (SkPMColor*) dst;
1084 if (SkSwizzler::kBGRA == config) { 1104 if (SkSwizzler::kBGRA == config) {
1085 for (int y = 0; y < height; y++) { 1105 for (int y = 0; y < height; y++) {
1086 for (int x = 0; x < width; x++) { 1106 for (int x = 0; x < width; x++) {
1087 if (transparent) { 1107 if (transparent) {
1088 dstRow[x] |= 0xFF000000; 1108 dstRow[x] |= 0xFF000000;
1089 } else { 1109 } else {
1090 dstRow[x] &= alphaMask; 1110 dstRow[x] &= alphaMask;
1091 } 1111 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1126 uint32_t alphaBit = 1146 uint32_t alphaBit =
1127 (srcBuffer.get()[quotient] >> shift) & 0x1; 1147 (srcBuffer.get()[quotient] >> shift) & 0x1;
1128 dstRow[x] &= alphaBit - 1; 1148 dstRow[x] &= alphaBit - 1;
1129 } 1149 }
1130 } 1150 }
1131 } 1151 }
1132 1152
1133 // Finished decoding the entire image 1153 // Finished decoding the entire image
1134 return kSuccess; 1154 return kSuccess;
1135 } 1155 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698