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

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: Redesign of Fill() 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"
(...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 *
734 * Performs the bitmap decoding for bit masks input format 736 * Performs the bitmap decoding for bit masks input format
735 * 737 *
736 */ 738 */
737 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo, 739 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
738 void* dst, size_t dstRowBytes) { 740 void* dst, size_t dstRowBytes,
741 const Options& opts) {
739 // Set constant values 742 // Set constant values
740 const int width = dstInfo.width(); 743 const int width = dstInfo.width();
741 const int height = dstInfo.height(); 744 const int height = dstInfo.height();
742 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); 745 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
743 746
744 // Allocate a buffer large enough to hold the full image 747 // Allocate a buffer large enough to hold the full image
745 SkAutoTDeleteArray<uint8_t> 748 SkAutoTDeleteArray<uint8_t>
746 srcBuffer(SkNEW_ARRAY(uint8_t, height*rowBytes)); 749 srcBuffer(SkNEW_ARRAY(uint8_t, height*rowBytes));
747 uint8_t* srcRow = srcBuffer.get(); 750 uint8_t* srcRow = srcBuffer.get();
748 751
749 // Create the swizzler 752 // Create the swizzler
750 SkAutoTDelete<SkMaskSwizzler> maskSwizzler( 753 SkAutoTDelete<SkMaskSwizzler> maskSwizzler(
751 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes, 754 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes,
752 fMasks, fBitsPerPixel)); 755 fMasks, fBitsPerPixel));
753 756
754 // Iterate over rows of the image 757 // Iterate over rows of the image
755 bool transparent = true; 758 bool transparent = true;
756 for (int y = 0; y < height; y++) { 759 for (int y = 0; y < height; y++) {
757 // Read a row of the input 760 // Read a row of the input
758 if (stream()->read(srcRow, rowBytes) != rowBytes) { 761 if (stream()->read(srcRow, rowBytes) != rowBytes) {
759 SkCodecPrintf("Warning: incomplete input stream.\n"); 762 SkCodecPrintf("Warning: incomplete input stream.\n");
763 // Fill the destination image on failure
764 // By using zero as the fill value, we will fill with transparent
765 // pixels for non-opaque images and white for opaque images.
766 // These are arbitrary choices but allow for consistent behavior.
767 if (kNo_ZeroInitialized == opts.fZeroInitialized) {
768 void* dstStart = (kTopDown_RowOrder == fRowOrder) ?
769 SkTAddOffset<void*>(dst, y * dstRowBytes) : dst;
770 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, 0, NULL);
771 }
760 return kIncompleteInput; 772 return kIncompleteInput;
761 } 773 }
762 774
763 // Decode the row in destination format 775 // Decode the row in destination format
764 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y; 776 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y;
765 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row); 777 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row);
766 transparent &= SkSwizzler::IsTransparent(r); 778 transparent &= SkSwizzler::IsTransparent(r);
767 779
768 // Move to the next row 780 // Move to the next row
769 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes); 781 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 // Destination parameters 904 // Destination parameters
893 int x = 0; 905 int x = 0;
894 int y = 0; 906 int y = 0;
895 907
896 // Set the background as transparent. Then, if the RLE code skips pixels, 908 // Set the background as transparent. Then, if the RLE code skips pixels,
897 // the skipped pixels will be transparent. 909 // the skipped pixels will be transparent.
898 // Because of the need for transparent pixels, kN32 is the only color 910 // Because of the need for transparent pixels, kN32 is the only color
899 // type that makes sense for the destination format. 911 // type that makes sense for the destination format.
900 SkASSERT(kN32_SkColorType == dstInfo.colorType()); 912 SkASSERT(kN32_SkColorType == dstInfo.colorType());
901 if (kNo_ZeroInitialized == opts.fZeroInitialized) { 913 if (kNo_ZeroInitialized == opts.fZeroInitialized) {
902 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, 0, SK_ColorTRANSPARENT, NULL ); 914 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, SK_ColorTRANSPARENT, NULL);
903 } 915 }
904 916
905 while (true) { 917 while (true) {
906 // Every entry takes at least two bytes 918 // Every entry takes at least two bytes
907 if ((int) totalBytes - currByte < 2) { 919 if ((int) totalBytes - currByte < 2) {
908 SkCodecPrintf("Warning: incomplete RLE input.\n"); 920 SkCodecPrintf("Warning: incomplete RLE input.\n");
909 return kIncompleteInput; 921 return kIncompleteInput;
910 } 922 }
911 923
912 // Read the next two bytes. These bytes have different meanings 924 // Read the next two bytes. These bytes have different meanings
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1053 } 1065 }
1054 } 1066 }
1055 } 1067 }
1056 1068
1057 /* 1069 /*
1058 * 1070 *
1059 * Performs the bitmap decoding for standard input format 1071 * Performs the bitmap decoding for standard input format
1060 * 1072 *
1061 */ 1073 */
1062 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo, 1074 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
1063 void* dst, size_t dstRowBytes) { 1075 void* dst, size_t dstRowBytes,
1076 const Options& opts) {
1064 // Set constant values 1077 // Set constant values
1065 const int width = dstInfo.width(); 1078 const int width = dstInfo.width();
1066 const int height = dstInfo.height(); 1079 const int height = dstInfo.height();
1067 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); 1080 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
1068 1081
1069 // Get swizzler configuration 1082 // Get swizzler configuration
1070 SkSwizzler::SrcConfig config; 1083 SkSwizzler::SrcConfig config;
1071 switch (fBitsPerPixel) { 1084 switch (fBitsPerPixel) {
1072 case 1: 1085 case 1:
1073 config = SkSwizzler::kIndex1; 1086 config = SkSwizzler::kIndex1;
(...skipping 15 matching lines...) Expand all
1089 config = SkSwizzler::kBGRX; 1102 config = SkSwizzler::kBGRX;
1090 } else { 1103 } else {
1091 config = SkSwizzler::kBGRA; 1104 config = SkSwizzler::kBGRA;
1092 } 1105 }
1093 break; 1106 break;
1094 default: 1107 default:
1095 SkASSERT(false); 1108 SkASSERT(false);
1096 return kInvalidInput; 1109 return kInvalidInput;
1097 } 1110 }
1098 1111
1112 // Get a pointer to the color table if it exists
1113 const SkPMColor* colorPtr = NULL != fColorTable.get() ? fColorTable->readCol ors() : NULL;
1114
1099 // Create swizzler 1115 // Create swizzler
1100 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config, 1116 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config,
1101 fColorTable->readColors(), dstInfo, dst, dstRowBytes, 1117 colorPtr, dstInfo, dst, dstRowBytes,
1102 SkImageGenerator::kNo_ZeroInitialized)); 1118 SkImageGenerator::kNo_ZeroInitialized));
1103 1119
1104 // Allocate space for a row buffer and a source for the swizzler 1120 // Allocate space for a row buffer and a source for the swizzler
1105 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); 1121 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
1106 1122
1107 // Iterate over rows of the image 1123 // Iterate over rows of the image
1108 // FIXME: bool transparent = true; 1124 // FIXME: bool transparent = true;
1109 for (int y = 0; y < height; y++) { 1125 for (int y = 0; y < height; y++) {
1110 // Read a row of the input 1126 // Read a row of the input
1111 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { 1127 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
1112 SkCodecPrintf("Warning: incomplete input stream.\n"); 1128 SkCodecPrintf("Warning: incomplete input stream.\n");
1129 // Fill the destination image on failure
1130 // By using zero as the fill value, we will fill with the first
1131 // color in the color table for palette images, transparent
1132 // pixels for non-opaque images, and white for opaque images.
1133 // These are arbitrary choices but allow for consistent behavior.
1134 if (kNo_ZeroInitialized == opts.fZeroInitialized) {
1135 void* dstStart = (kTopDown_RowOrder == fRowOrder) ?
scroggo 2015/04/10 21:08:32 nit: It seems like you could use a macro/static fu
msarett 2015/04/10 21:22:32 Done.
1136 SkTAddOffset<void*>(dst, y * dstRowBytes) : dst;
1137 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, 0,
1138 colorPtr);
1139 }
1113 return kIncompleteInput; 1140 return kIncompleteInput;
1114 } 1141 }
1115 1142
1116 // Decode the row in destination format 1143 // Decode the row in destination format
1117 uint32_t row; 1144 uint32_t row;
1118 if (kTopDown_RowOrder == fRowOrder) { 1145 if (kTopDown_RowOrder == fRowOrder) {
1119 row = y; 1146 row = y;
1120 } else { 1147 } else {
1121 row = height - 1 - y; 1148 row = height - 1 - y;
1122 } 1149 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1184 uint32_t alphaBit = 1211 uint32_t alphaBit =
1185 (srcBuffer.get()[quotient] >> shift) & 0x1; 1212 (srcBuffer.get()[quotient] >> shift) & 0x1;
1186 dstRow[x] &= alphaBit - 1; 1213 dstRow[x] &= alphaBit - 1;
1187 } 1214 }
1188 } 1215 }
1189 } 1216 }
1190 1217
1191 // Finished decoding the entire image 1218 // Finished decoding the entire image
1192 return kSuccess; 1219 return kSuccess;
1193 } 1220 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | src/codec/SkCodec_libgif.cpp » ('j') | src/codec/SkSwizzler.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698