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

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

Issue 1075243003: Implementing filling for SkBmpCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Sharing code in static helper 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
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | src/codec/SkCodec_libgif.cpp » ('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_libbmp.h" 8 #include "SkCodec_libbmp.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 if (kIndex_8_SkColorType == dstInfo.colorType()) { 607 if (kIndex_8_SkColorType == dstInfo.colorType()) {
608 SkASSERT(NULL != inputColorPtr); 608 SkASSERT(NULL != inputColorPtr);
609 SkASSERT(NULL != inputColorCount); 609 SkASSERT(NULL != inputColorCount);
610 SkASSERT(NULL != fColorTable.get()); 610 SkASSERT(NULL != fColorTable.get());
611 sk_memcpy32(inputColorPtr, fColorTable->readColors(), *inputColorCount); 611 sk_memcpy32(inputColorPtr, fColorTable->readColors(), *inputColorCount);
612 } 612 }
613 613
614 // Perform the decode 614 // Perform the decode
615 switch (fInputFormat) { 615 switch (fInputFormat) {
616 case kBitMask_BitmapInputFormat: 616 case kBitMask_BitmapInputFormat:
617 return decodeMask(dstInfo, dst, dstRowBytes); 617 return decodeMask(dstInfo, dst, dstRowBytes, opts);
618 case kRLE_BitmapInputFormat: 618 case kRLE_BitmapInputFormat:
619 return decodeRLE(dstInfo, dst, dstRowBytes, opts); 619 return decodeRLE(dstInfo, dst, dstRowBytes, opts);
620 case kStandard_BitmapInputFormat: 620 case kStandard_BitmapInputFormat:
621 return decode(dstInfo, dst, dstRowBytes); 621 return decode(dstInfo, dst, dstRowBytes, opts);
622 default: 622 default:
623 SkASSERT(false); 623 SkASSERT(false);
624 return kInvalidInput; 624 return kInvalidInput;
625 } 625 }
626 } 626 }
627 627
628 /* 628 /*
629 * 629 *
630 * Process the color table for the bmp input 630 * Process the color table for the bmp input
631 * 631 *
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 } 694 }
695 colorTable[i] = packARGB(alpha, red, green, blue); 695 colorTable[i] = packARGB(alpha, red, green, blue);
696 } 696 }
697 697
698 // To avoid segmentation faults on bad pixel data, fill the end of the 698 // To avoid segmentation faults on bad pixel data, fill the end of the
699 // color table with black. This is the same the behavior as the 699 // color table with black. This is the same the behavior as the
700 // chromium decoder. 700 // chromium decoder.
701 for (; i < maxColors; i++) { 701 for (; i < maxColors; i++) {
702 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); 702 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
703 } 703 }
704
705 // Set the color table
706 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors)));
704 } 707 }
705 708
706 // Bmp-in-Ico files do not use an offset to indicate where the pixel data 709 // Bmp-in-Ico files do not use an offset to indicate where the pixel data
707 // begins. Pixel data always begins immediately after the color table. 710 // begins. Pixel data always begins immediately after the color table.
708 if (!fIsIco) { 711 if (!fIsIco) {
709 // Check that we have not read past the pixel array offset 712 // Check that we have not read past the pixel array offset
710 if(fOffset < colorBytes) { 713 if(fOffset < colorBytes) {
711 // This may occur on OS 2.1 and other old versions where the color 714 // This may occur on OS 2.1 and other old versions where the color
712 // table defaults to max size, and the bmp tries to use a smaller 715 // table defaults to max size, and the bmp tries to use a smaller
713 // color table. This is invalid, and our decision is to indicate 716 // color table. This is invalid, and our decision is to indicate
714 // an error, rather than try to guess the intended size of the 717 // an error, rather than try to guess the intended size of the
715 // color table. 718 // color table.
716 SkCodecPrintf("Error: pixel data offset less than color table size.\ n"); 719 SkCodecPrintf("Error: pixel data offset less than color table size.\ n");
717 return false; 720 return false;
718 } 721 }
719 722
720 // After reading the color table, skip to the start of the pixel array 723 // After reading the color table, skip to the start of the pixel array
721 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { 724 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) {
722 SkCodecPrintf("Error: unable to skip to image data.\n"); 725 SkCodecPrintf("Error: unable to skip to image data.\n");
723 return false; 726 return false;
724 } 727 }
725 } 728 }
726 729
727 // Set the color table and return true on success 730 // Return true on success
728 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors)));
729 return true; 731 return true;
730 } 732 }
731 733
732 /* 734 /*
733 * 735 *
736 * Get the destination row to start filling from
737 * Used to fill the remainder of the image on incomplete input
738 *
739 */
740 static inline void* get_dst_start_row(void* dst, size_t dstRowBytes, int32_t y,
741 SkBmpCodec::RowOrder rowOrder) {
742 return (SkBmpCodec::kTopDown_RowOrder == rowOrder) ?
743 SkTAddOffset<void*>(dst, y * dstRowBytes) : dst;
744 }
745
746 /*
747 *
734 * Performs the bitmap decoding for bit masks input format 748 * Performs the bitmap decoding for bit masks input format
735 * 749 *
736 */ 750 */
737 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo, 751 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
738 void* dst, size_t dstRowBytes) { 752 void* dst, size_t dstRowBytes,
753 const Options& opts) {
739 // Set constant values 754 // Set constant values
740 const int width = dstInfo.width(); 755 const int width = dstInfo.width();
741 const int height = dstInfo.height(); 756 const int height = dstInfo.height();
742 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); 757 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
743 758
744 // Allocate a buffer large enough to hold the full image 759 // Allocate a buffer large enough to hold the full image
745 SkAutoTDeleteArray<uint8_t> 760 SkAutoTDeleteArray<uint8_t>
746 srcBuffer(SkNEW_ARRAY(uint8_t, height*rowBytes)); 761 srcBuffer(SkNEW_ARRAY(uint8_t, height*rowBytes));
747 uint8_t* srcRow = srcBuffer.get(); 762 uint8_t* srcRow = srcBuffer.get();
748 763
749 // Create the swizzler 764 // Create the swizzler
750 SkAutoTDelete<SkMaskSwizzler> maskSwizzler( 765 SkAutoTDelete<SkMaskSwizzler> maskSwizzler(
751 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes, 766 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes,
752 fMasks, fBitsPerPixel)); 767 fMasks, fBitsPerPixel));
753 768
754 // Iterate over rows of the image 769 // Iterate over rows of the image
755 bool transparent = true; 770 bool transparent = true;
756 for (int y = 0; y < height; y++) { 771 for (int y = 0; y < height; y++) {
757 // Read a row of the input 772 // Read a row of the input
758 if (stream()->read(srcRow, rowBytes) != rowBytes) { 773 if (stream()->read(srcRow, rowBytes) != rowBytes) {
759 SkCodecPrintf("Warning: incomplete input stream.\n"); 774 SkCodecPrintf("Warning: incomplete input stream.\n");
775 // Fill the destination image on failure
776 // By using zero as the fill value, we will fill with transparent
777 // pixels for non-opaque images and white for opaque images.
778 // These are arbitrary choices but allow for consistent behavior.
779 if (kNo_ZeroInitialized == opts.fZeroInitialized) {
780 void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrde r);
781 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, 0, NULL);
782 }
760 return kIncompleteInput; 783 return kIncompleteInput;
761 } 784 }
762 785
763 // Decode the row in destination format 786 // Decode the row in destination format
764 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y; 787 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y;
765 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row); 788 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row);
766 transparent &= SkSwizzler::IsTransparent(r); 789 transparent &= SkSwizzler::IsTransparent(r);
767 790
768 // Move to the next row 791 // Move to the next row
769 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes); 792 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 // Destination parameters 915 // Destination parameters
893 int x = 0; 916 int x = 0;
894 int y = 0; 917 int y = 0;
895 918
896 // Set the background as transparent. Then, if the RLE code skips pixels, 919 // Set the background as transparent. Then, if the RLE code skips pixels,
897 // the skipped pixels will be transparent. 920 // the skipped pixels will be transparent.
898 // Because of the need for transparent pixels, kN32 is the only color 921 // Because of the need for transparent pixels, kN32 is the only color
899 // type that makes sense for the destination format. 922 // type that makes sense for the destination format.
900 SkASSERT(kN32_SkColorType == dstInfo.colorType()); 923 SkASSERT(kN32_SkColorType == dstInfo.colorType());
901 if (kNo_ZeroInitialized == opts.fZeroInitialized) { 924 if (kNo_ZeroInitialized == opts.fZeroInitialized) {
902 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, 0, SK_ColorTRANSPARENT, NULL ); 925 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, SK_ColorTRANSPARENT, NULL);
903 } 926 }
904 927
905 while (true) { 928 while (true) {
906 // Every entry takes at least two bytes 929 // Every entry takes at least two bytes
907 if ((int) totalBytes - currByte < 2) { 930 if ((int) totalBytes - currByte < 2) {
908 SkCodecPrintf("Warning: incomplete RLE input.\n"); 931 SkCodecPrintf("Warning: incomplete RLE input.\n");
909 return kIncompleteInput; 932 return kIncompleteInput;
910 } 933 }
911 934
912 // Read the next two bytes. These bytes have different meanings 935 // Read the next two bytes. These bytes have different meanings
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1053 } 1076 }
1054 } 1077 }
1055 } 1078 }
1056 1079
1057 /* 1080 /*
1058 * 1081 *
1059 * Performs the bitmap decoding for standard input format 1082 * Performs the bitmap decoding for standard input format
1060 * 1083 *
1061 */ 1084 */
1062 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo, 1085 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
1063 void* dst, size_t dstRowBytes) { 1086 void* dst, size_t dstRowBytes,
1087 const Options& opts) {
1064 // Set constant values 1088 // Set constant values
1065 const int width = dstInfo.width(); 1089 const int width = dstInfo.width();
1066 const int height = dstInfo.height(); 1090 const int height = dstInfo.height();
1067 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); 1091 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
1068 1092
1069 // Get swizzler configuration 1093 // Get swizzler configuration
1070 SkSwizzler::SrcConfig config; 1094 SkSwizzler::SrcConfig config;
1071 switch (fBitsPerPixel) { 1095 switch (fBitsPerPixel) {
1072 case 1: 1096 case 1:
1073 config = SkSwizzler::kIndex1; 1097 config = SkSwizzler::kIndex1;
(...skipping 15 matching lines...) Expand all
1089 config = SkSwizzler::kBGRX; 1113 config = SkSwizzler::kBGRX;
1090 } else { 1114 } else {
1091 config = SkSwizzler::kBGRA; 1115 config = SkSwizzler::kBGRA;
1092 } 1116 }
1093 break; 1117 break;
1094 default: 1118 default:
1095 SkASSERT(false); 1119 SkASSERT(false);
1096 return kInvalidInput; 1120 return kInvalidInput;
1097 } 1121 }
1098 1122
1123 // Get a pointer to the color table if it exists
1124 const SkPMColor* colorPtr = NULL != fColorTable.get() ? fColorTable->readCol ors() : NULL;
1125
1099 // Create swizzler 1126 // Create swizzler
1100 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config, 1127 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config,
1101 fColorTable->readColors(), dstInfo, dst, dstRowBytes, 1128 colorPtr, dstInfo, dst, dstRowBytes,
1102 SkImageGenerator::kNo_ZeroInitialized)); 1129 SkImageGenerator::kNo_ZeroInitialized));
1103 1130
1104 // Allocate space for a row buffer and a source for the swizzler 1131 // Allocate space for a row buffer and a source for the swizzler
1105 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); 1132 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
1106 1133
1107 // Iterate over rows of the image 1134 // Iterate over rows of the image
1108 // FIXME: bool transparent = true; 1135 // FIXME: bool transparent = true;
1109 for (int y = 0; y < height; y++) { 1136 for (int y = 0; y < height; y++) {
1110 // Read a row of the input 1137 // Read a row of the input
1111 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { 1138 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
1112 SkCodecPrintf("Warning: incomplete input stream.\n"); 1139 SkCodecPrintf("Warning: incomplete input stream.\n");
1140 // Fill the destination image on failure
1141 // By using zero as the fill value, we will fill with the first
1142 // color in the color table for palette images, transparent
1143 // pixels for non-opaque images, and white for opaque images.
1144 // These are arbitrary choices but allow for consistent behavior.
1145 if (kNo_ZeroInitialized == opts.fZeroInitialized) {
1146 void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrde r);
1147 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, 0,
1148 colorPtr);
1149 }
1113 return kIncompleteInput; 1150 return kIncompleteInput;
1114 } 1151 }
1115 1152
1116 // Decode the row in destination format 1153 // Decode the row in destination format
1117 uint32_t row; 1154 uint32_t row;
1118 if (kTopDown_RowOrder == fRowOrder) { 1155 if (kTopDown_RowOrder == fRowOrder) {
1119 row = y; 1156 row = y;
1120 } else { 1157 } else {
1121 row = height - 1 - y; 1158 row = height - 1 - y;
1122 } 1159 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1184 uint32_t alphaBit = 1221 uint32_t alphaBit =
1185 (srcBuffer.get()[quotient] >> shift) & 0x1; 1222 (srcBuffer.get()[quotient] >> shift) & 0x1;
1186 dstRow[x] &= alphaBit - 1; 1223 dstRow[x] &= alphaBit - 1;
1187 } 1224 }
1188 } 1225 }
1189 } 1226 }
1190 1227
1191 // Finished decoding the entire image 1228 // Finished decoding the entire image
1192 return kSuccess; 1229 return kSuccess;
1193 } 1230 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | src/codec/SkCodec_libgif.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698