1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkCodec.h" 9 #include "SkColorTable.h" 10 #include "SkImageInfo.h" 11 #include "SkMaskSwizzler.h" 12 #include "SkStream.h" 13 #include "SkSwizzler.h" 14 #include "SkTypes.h" 15 16 // TODO: rename SkCodec_libbmp files to SkBmpCodec 17 /* 18 * 19 * This class implements the decoding for bmp images 20 * 21 */ 22 class SkBmpCodec : public SkCodec { 23 public: 24 25 /* 26 * 27 * Describes if rows of the input start at the top or bottom of the image 28 * 29 */ 30 enum RowOrder { 31 kTopDown_RowOrder, 32 kBottomUp_RowOrder 33 }; 34 35 /* 36 * 37 * Checks the start of the stream to see if the image is a bmp 38 * 39 */ 40 static bool IsBmp(SkStream*); 41 42 /* 43 * 44 * Assumes IsBmp was called and returned true 45 * Creates a bmp decoder 46 * Reads enough of the stream to determine the image format 47 * 48 */ 49 static SkCodec* NewFromStream(SkStream*); 50 51 /* 52 * 53 * Creates a bmp decoder for a bmp embedded in ico 54 * Reads enough of the stream to determine the image format 55 * 56 */ 57 static SkCodec* NewFromIco(SkStream*); 58 59 protected: 60 61 /* 62 * 63 * Initiates the bmp decode 64 * 65 */ 66 Result onGetPixels(const SkImageInfo& dstInfo, void* dst, 67 size_t dstRowBytes, const Options&, SkPMColor*, 68 int*) override; 69 onGetEncodedFormat()70 SkEncodedFormat onGetEncodedFormat() const override { return kBMP_SkEncodedFormat; } 71 72 private: 73 74 /* 75 * 76 * Used to define the input format of the bmp 77 * 78 */ 79 enum BitmapInputFormat { 80 kStandard_BitmapInputFormat, 81 kRLE_BitmapInputFormat, 82 kBitMask_BitmapInputFormat, 83 kUnknown_BitmapInputFormat 84 }; 85 86 /* 87 * 88 * Creates the color table 89 * Sets colorCount to the new color count if it is non-NULL 90 */ 91 bool createColorTable(SkAlphaType alphaType, int* colorCount); 92 93 /* 94 * 95 * Creates a bmp decoder 96 * Reads enough of the stream to determine the image format 97 * 98 */ 99 static SkCodec* NewFromStream(SkStream*, bool isIco); 100 101 /* 102 * 103 * Read enough of the stream to initialize the SkBmpCodec. Returns a bool 104 * representing success or failure. If it returned true, and codecOut was 105 * not NULL, it will be set to a new SkBmpCodec. 106 * Does *not* take ownership of the passed in SkStream. 107 * 108 */ 109 static bool ReadHeader(SkStream*, bool isIco, SkCodec** codecOut); 110 111 /* 112 * 113 * Performs the bitmap decoding for bit masks input format 114 * 115 */ 116 Result decodeMask(const SkImageInfo& dstInfo, void* dst, 117 size_t dstRowBytes, const Options& opts); 118 119 /* 120 * 121 * Set an RLE pixel using the color table 122 * 123 */ 124 void setRLEPixel(void* dst, size_t dstRowBytes, 125 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, 126 uint8_t index); 127 /* 128 * 129 * Set an RLE24 pixel from R, G, B values 130 * 131 */ 132 void setRLE24Pixel(void* dst, size_t dstRowBytes, 133 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, 134 uint8_t red, uint8_t green, uint8_t blue); 135 136 /* 137 * 138 * Performs the bitmap decoding for RLE input format 139 * 140 */ 141 Result decodeRLE(const SkImageInfo& dstInfo, void* dst, 142 size_t dstRowBytes, const Options& opts); 143 144 /* 145 * 146 * Performs the bitmap decoding for standard input format 147 * 148 */ 149 Result decode(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& opts); 150 151 /* 152 * 153 * Creates an instance of the decoder 154 * Called only by NewFromStream 155 * 156 * @param srcInfo contains the source width and height 157 * @param stream the stream of image data 158 * @param bitsPerPixel the number of bits used to store each pixel 159 * @param format the format of the bmp file 160 * @param masks optional color masks for certain bmp formats, passes 161 ownership to SkBmpCodec 162 * @param numColors the number of colors in the color table 163 * @param bytesPerColor the number of bytes in the stream used to represent 164 each color in the color table 165 * @param offset the offset of the image pixel data from the end of the 166 * headers 167 * @param rowOrder indicates whether rows are ordered top-down or bottom-up 168 * @param RLEBytes used only for RLE decodes, as we must decode all 169 * of the data at once rather than row by row 170 * it indicates the amount of data left in the stream 171 * after decoding the headers 172 * 173 */ 174 SkBmpCodec(const SkImageInfo& srcInfo, SkStream* stream, 175 uint16_t bitsPerPixel, BitmapInputFormat format, 176 SkMasks* masks, uint32_t numColors, uint32_t bytesPerColor, 177 uint32_t offset, RowOrder rowOrder, size_t RLEBytes, 178 bool isIco); 179 180 // Fields 181 const uint16_t fBitsPerPixel; 182 const BitmapInputFormat fInputFormat; 183 SkAutoTDelete<SkMasks> fMasks; // owned 184 SkAutoTUnref<SkColorTable> fColorTable; // owned 185 uint32_t fNumColors; 186 const uint32_t fBytesPerColor; 187 const uint32_t fOffset; 188 const RowOrder fRowOrder; 189 const size_t fRLEBytes; 190 const bool fIsIco; 191 192 typedef SkCodec INHERITED; 193 }; 194