1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_image_decoders_nsBMPDecoder_h 8 #define mozilla_image_decoders_nsBMPDecoder_h 9 10 #include "BMPHeaders.h" 11 #include "Decoder.h" 12 #include "gfxColor.h" 13 #include "StreamingLexer.h" 14 #include "SurfacePipe.h" 15 #include "mozilla/UniquePtr.h" 16 17 namespace mozilla { 18 namespace image { 19 20 namespace bmp { 21 22 struct CalRgbEndpoint { 23 uint32_t mGamma; 24 uint32_t mX; 25 uint32_t mY; 26 uint32_t mZ; 27 }; 28 29 /// This struct contains the fields from the file header and info header that 30 /// we use during decoding. (Excluding bitfields fields, which are kept in 31 /// BitFields.) 32 struct Header { 33 uint32_t mDataOffset; // Offset to raster data. 34 uint32_t mBIHSize; // Header size. 35 int32_t mWidth; // Image width. 36 int32_t mHeight; // Image height. 37 uint16_t mBpp; // Bits per pixel. 38 uint32_t mCompression; // See struct Compression for valid values. 39 uint32_t mImageSize; // (compressed) image size. Can be 0 if 40 // mCompression==0. 41 uint32_t mNumColors; // Used colors. 42 InfoColorSpace mCsType; // Color space type. 43 InfoColorIntent mCsIntent; // Color space intent. 44 45 union { 46 struct { 47 CalRgbEndpoint mRed; 48 CalRgbEndpoint mGreen; 49 CalRgbEndpoint mBlue; 50 } mCalibrated; 51 52 struct { 53 uint32_t mOffset; 54 uint32_t mLength; 55 } mProfile; 56 } mColorSpace; 57 HeaderHeader58 Header() 59 : mDataOffset(0), 60 mBIHSize(0), 61 mWidth(0), 62 mHeight(0), 63 mBpp(0), 64 mCompression(0), 65 mImageSize(0), 66 mNumColors(0), 67 mCsType(InfoColorSpace::SRGB), 68 mCsIntent(InfoColorIntent::IMAGES) {} 69 }; 70 71 /// An entry in the color table. 72 struct ColorTableEntry { 73 uint8_t mRed; 74 uint8_t mGreen; 75 uint8_t mBlue; 76 }; 77 78 /// All the color-related bitfields for 16bpp and 32bpp images. We use this 79 /// even for older format BMPs that don't have explicit bitfields. 80 class BitFields { 81 class Value { 82 friend class BitFields; 83 84 uint32_t mMask; // The mask for the value. 85 uint8_t mRightShift; // The amount to right-shift after masking. 86 uint8_t mBitWidth; // The width (in bits) of the value. 87 88 /// Sets the mask (and thus the right-shift and bit-width as well). 89 void Set(uint32_t aMask); 90 91 public: Value()92 Value() { 93 mMask = 0; 94 mRightShift = 0; 95 mBitWidth = 0; 96 } 97 98 /// Returns true if this channel is used. Only used for alpha. IsPresent()99 bool IsPresent() const { return mMask != 0x0; } 100 101 /// Extracts the single color value from the multi-color value. 102 uint8_t Get(uint32_t aVal) const; 103 104 /// Like Get(), but specially for alpha. 105 uint8_t GetAlpha(uint32_t aVal, bool& aHasAlphaOut) const; 106 107 /// Specialized versions of Get() for when the bit-width is 5 or 8. 108 /// (They will assert if called and the bit-width is not 5 or 8.) 109 uint8_t Get5(uint32_t aVal) const; 110 uint8_t Get8(uint32_t aVal) const; 111 }; 112 113 public: 114 /// The individual color channels. 115 Value mRed; 116 Value mGreen; 117 Value mBlue; 118 Value mAlpha; 119 120 /// Set bitfields to the standard 5-5-5 16bpp values. 121 void SetR5G5B5(); 122 123 /// Set bitfields to the standard 8-8-8 32bpp values. 124 void SetR8G8B8(); 125 126 /// Test if bitfields have the standard 5-5-5 16bpp values. 127 bool IsR5G5B5() const; 128 129 /// Test if bitfields have the standard 8-8-8 32bpp values. 130 bool IsR8G8B8() const; 131 132 /// Read the bitfields from a header. The reading of the alpha mask is 133 /// optional. 134 void ReadFromHeader(const char* aData, bool aReadAlpha); 135 136 /// Length of the bitfields structure in the BMP file. 137 static const size_t LENGTH = 12; 138 }; 139 140 } // namespace bmp 141 142 class RasterImage; 143 144 /// Decoder for BMP-Files, as used by Windows and OS/2. 145 146 class nsBMPDecoder : public Decoder { 147 public: 148 ~nsBMPDecoder(); 149 GetType()150 DecoderType GetType() const override { return DecoderType::BMP; } 151 152 /// @return true if this BMP is a valid ICO resource. IsValidICOResource()153 bool IsValidICOResource() const override { return true; } 154 155 /// Obtains the internal output image buffer. GetImageData()156 uint32_t* GetImageData() { return reinterpret_cast<uint32_t*>(mImageData); } 157 158 /// Obtains the length of the internal output image buffer. GetImageDataLength()159 size_t GetImageDataLength() const { return mImageDataLength; } 160 161 /// Obtains the size of the compressed image resource. 162 int32_t GetCompressedImageSize() const; 163 164 /// Mark this BMP as being within an ICO file. Only used for testing purposes 165 /// because the ICO-specific constructor does this marking automatically. SetIsWithinICO()166 void SetIsWithinICO() { mIsWithinICO = true; } 167 168 /// Did the BMP file have alpha data of any kind? (Only use this after the 169 /// bitmap has been fully decoded.) HasTransparency()170 bool HasTransparency() const { return mDoesHaveTransparency; } 171 172 LexerResult DoDecode(SourceBufferIterator& aIterator, 173 IResumable* aOnResume) override; 174 nsresult BeforeFinishInternal() override; 175 nsresult FinishInternal() override; 176 177 private: 178 friend class DecoderFactory; 179 180 enum class State { 181 FILE_HEADER, 182 INFO_HEADER_SIZE, 183 INFO_HEADER_REST, 184 BITFIELDS, 185 SKIP_TO_COLOR_PROFILE, 186 FOUND_COLOR_PROFILE, 187 COLOR_PROFILE, 188 ALLOCATE_SURFACE, 189 COLOR_TABLE, 190 GAP, 191 AFTER_GAP, 192 PIXEL_ROW, 193 RLE_SEGMENT, 194 RLE_DELTA, 195 RLE_ABSOLUTE 196 }; 197 198 // This is the constructor used for normal and clipboard BMP images. 199 explicit nsBMPDecoder(RasterImage* aImage, bool aForClipboard = false); 200 201 // This is the constructor used for BMP resources in ICO images. 202 nsBMPDecoder(RasterImage* aImage, uint32_t aDataOffset); 203 204 // Helper constructor called by the other two. 205 nsBMPDecoder(RasterImage* aImage, State aState, size_t aLength, 206 bool aForClipboard); 207 AbsoluteHeight()208 int32_t AbsoluteHeight() const { return abs(mH.mHeight); } 209 210 uint32_t* RowBuffer(); 211 void ClearRowBufferRemainder(); 212 213 void FinishRow(); 214 215 void PrepareCalibratedColorProfile(); 216 void PrepareColorProfileTransform(); 217 218 LexerTransition<State> ReadFileHeader(const char* aData, size_t aLength); 219 LexerTransition<State> ReadInfoHeaderSize(const char* aData, size_t aLength); 220 LexerTransition<State> ReadInfoHeaderRest(const char* aData, size_t aLength); 221 LexerTransition<State> ReadBitfields(const char* aData, size_t aLength); 222 LexerTransition<State> SeekColorProfile(size_t aLength); 223 LexerTransition<State> ReadColorProfile(const char* aData, size_t aLength); 224 LexerTransition<State> AllocateSurface(); 225 LexerTransition<State> ReadColorTable(const char* aData, size_t aLength); 226 LexerTransition<State> SkipGap(); 227 LexerTransition<State> AfterGap(); 228 LexerTransition<State> ReadPixelRow(const char* aData); 229 LexerTransition<State> ReadRLESegment(const char* aData); 230 LexerTransition<State> ReadRLEDelta(const char* aData); 231 LexerTransition<State> ReadRLEAbsolute(const char* aData, size_t aLength); 232 233 SurfacePipe mPipe; 234 235 StreamingLexer<State> mLexer; 236 237 // Iterator to save return point. 238 Maybe<SourceBufferIterator> mReturnIterator; 239 240 UniquePtr<uint32_t[]> mRowBuffer; 241 242 bmp::Header mH; 243 244 // If the BMP is within an ICO file our treatment of it differs slightly. 245 bool mIsWithinICO; 246 247 // If the BMP decoded from the clipboard, we don't start with a data offset. 248 bool mIsForClipboard; 249 250 bmp::BitFields mBitFields; 251 252 // Might the image have transparency? Determined from the headers during 253 // metadata decode. (Does not guarantee the image actually has transparency.) 254 bool mMayHaveTransparency; 255 256 // Does the image have transparency? Determined during full decoding, so only 257 // use this after that has been completed. 258 bool mDoesHaveTransparency; 259 260 uint32_t mNumColors; // The number of used colors, i.e. the number of 261 // entries in mColors, if it's present. 262 UniquePtr<bmp::ColorTableEntry[]> 263 mColors; // The color table, if it's present. 264 uint32_t mBytesPerColor; // 3 or 4, depending on the format 265 266 // The number of bytes prior to the optional gap that have been read. This 267 // is used to find the start of the pixel data. 268 uint32_t mPreGapLength; 269 270 uint32_t mPixelRowSize; // The number of bytes per pixel row. 271 272 int32_t mCurrentRow; // Index of the row of the image that's currently 273 // being decoded: [height,1]. 274 int32_t mCurrentPos; // Index into the current line. Used when 275 // doing RLE decoding and when filling in pixels 276 // for truncated files. 277 278 // Only used in RLE_ABSOLUTE state: the number of pixels to read. 279 uint32_t mAbsoluteModeNumPixels; 280 }; 281 282 } // namespace image 283 } // namespace mozilla 284 285 #endif // mozilla_image_decoders_nsBMPDecoder_h 286