author Seth Fowler <>
Wed, 12 Aug 2015 10:41:05 -0700
changeset 257517 fce34ae035239a2014509c8262424dcdccd07e9f
parent 254295 aaf3459a20b5236b81c5d4f243503c9e1eeff3a6
child 261484 4a56f13c2f75442377af49983f414e5ae364a368
permissions -rw-r--r--
Bug 1191114 (Part 2) - Add support for creating an anonymous metadata decoder, for use in tests. r=tn

/* vim:set tw=80 expandtab softtabstop=4 ts=4 sw=4: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at */

#ifndef mozilla_image_decoders_nsBMPDecoder_h
#define mozilla_image_decoders_nsBMPDecoder_h

#include "BMPFileHeaders.h"
#include "Decoder.h"
#include "gfxColor.h"
#include "nsAutoPtr.h"

namespace mozilla {
namespace image {

class RasterImage;

/// Decoder for BMP-Files, as used by Windows and OS/2

class nsBMPDecoder : public Decoder

    // Specifies whether or not the BMP file will contain alpha data
    // If set to true and the BMP is 32BPP, the alpha data will be
    // retrieved from the 4th byte of image data per pixel
    void SetUseAlphaData(bool useAlphaData);

    // Obtains the bits per pixel from the internal BIH header
    int32_t GetBitsPerPixel() const;

    // Obtains the width from the internal BIH header
    int32_t GetWidth() const;

    // Obtains the abs-value of the height from the internal BIH header
    int32_t GetHeight() const;

    // Obtains the internal output image buffer
    uint32_t* GetImageData();

    // Obtains the size of the compressed image resource
    int32_t GetCompressedImageSize() const;

    // Obtains whether or not a BMP file had alpha data in its 4th byte
    // for 32BPP bitmaps.  Only use after the bitmap has been processed.
    bool HasAlphaData() const;

    virtual void WriteInternal(const char* aBuffer,
                               uint32_t aCount) override;
    virtual void FinishInternal() override;

    friend class DecoderFactory;
    friend class nsICODecoder;

    // Decoders should only be instantiated via DecoderFactory.
    // XXX(seth): nsICODecoder is temporarily an exception to this rule.
    explicit nsBMPDecoder(RasterImage* aImage);

    /// Calculates the red-, green- and blueshift in mBitFields using
    /// the bitmasks from mBitFields
    NS_METHOD CalcBitShift();

    uint32_t mPos; //< Number of bytes read from aBuffer in WriteInternal()

    char mRawBuf[BIH_INTERNAL_LENGTH::WIN_V3]; //< If this is changed,
                                               // WriteInternal() MUST be updated

    uint32_t mLOH; //< Length of the header

    uint32_t mNumColors; //< The number of used colors, i.e. the number of
                         // entries in mColors
    colorTable* mColors;

    bitFields mBitFields;

    uint8_t* mRow;      //< Holds one raw line of the image
    uint32_t mRowBytes; //< How many bytes of the row were already received
    int32_t mCurLine;   //< Index of the line of the image that's currently
                        // being decoded: [height,1]
    int32_t mOldLine;   //< Previous index of the line
    int32_t mCurPos;    //< Index in the current line of the image

    ERLEState mState;   //< Maintains the current state of the RLE decoding
    uint32_t mStateData;//< Decoding information that is needed depending
                        // on mState

    /// Set mBFH from the raw data in mRawBuf, converting from little-endian
    /// data to native data as necessary
    void ProcessFileHeader();

    /// Set mBIH from the raw data in mRawBuf, converting from little-endian
    /// data to native data as necessary
    void ProcessInfoHeader();

    /// True if we've already processed the BMP header.
    bool mProcessedHeader;

    // Stores whether the image data may store alpha data, or if
    // the alpha data is unspecified and filled with a padding byte of 0.
    // When a 32BPP bitmap is stored in an ICO or CUR file, its 4th byte
    // is used for alpha transparency.  When it is stored in a BMP, its
    // 4th byte is reserved and is always 0.
    // Reference:
    // Bitmaps where the alpha bytes are all 0 should be fully visible.
    bool mUseAlphaData;

    // Whether the 4th byte alpha data was found to be non zero and hence used.
    bool mHaveAlphaData;

/// Sets the pixel data in aDecoded to the given values.
/// @param aDecoded pointer to pixel to be set, will be incremented to point to
/// the next pixel.
static inline void
SetPixel(uint32_t*& aDecoded, uint8_t aRed, uint8_t aGreen,
         uint8_t aBlue, uint8_t aAlpha = 0xFF)
    *aDecoded++ = gfxPackedPixel(aAlpha, aRed, aGreen, aBlue);

static inline void
SetPixel(uint32_t*& aDecoded, uint8_t idx, colorTable* aColors)
    SetPixel(aDecoded, aColors[idx].red, aColors[idx].green, aColors[idx].blue);

/// Sets two (or one if aCount = 1) pixels
/// @param aDecoded where the data is stored. Will be moved 4 resp 8 bytes
/// depending on whether one or two pixels are written.
/// @param aData The values for the two pixels
/// @param aCount Current count. Is decremented by one or two.
inline void
Set4BitPixel(uint32_t*& aDecoded, uint8_t aData, uint32_t& aCount,
             colorTable* aColors)
    uint8_t idx = aData >> 4;
    SetPixel(aDecoded, idx, aColors);
    if (--aCount > 0) {
        idx = aData & 0xF;
        SetPixel(aDecoded, idx, aColors);

} // namespace image
} // namespace mozilla

#endif // mozilla_image_decoders_nsBMPDecoder_h