summaryrefslogtreecommitdiffstats
path: root/image/decoders/nsBMPDecoder.h
diff options
context:
space:
mode:
Diffstat (limited to 'image/decoders/nsBMPDecoder.h')
-rw-r--r--image/decoders/nsBMPDecoder.h285
1 files changed, 285 insertions, 0 deletions
diff --git a/image/decoders/nsBMPDecoder.h b/image/decoders/nsBMPDecoder.h
new file mode 100644
index 0000000000..c7990834b9
--- /dev/null
+++ b/image/decoders/nsBMPDecoder.h
@@ -0,0 +1,285 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_image_decoders_nsBMPDecoder_h
+#define mozilla_image_decoders_nsBMPDecoder_h
+
+#include "BMPHeaders.h"
+#include "Decoder.h"
+#include "gfxColor.h"
+#include "StreamingLexer.h"
+#include "SurfacePipe.h"
+#include "mozilla/UniquePtr.h"
+
+namespace mozilla {
+namespace image {
+
+namespace bmp {
+
+struct CalRgbEndpoint {
+ uint32_t mGamma;
+ uint32_t mX;
+ uint32_t mY;
+ uint32_t mZ;
+};
+
+/// This struct contains the fields from the file header and info header that
+/// we use during decoding. (Excluding bitfields fields, which are kept in
+/// BitFields.)
+struct Header {
+ uint32_t mDataOffset; // Offset to raster data.
+ uint32_t mBIHSize; // Header size.
+ int32_t mWidth; // Image width.
+ int32_t mHeight; // Image height.
+ uint16_t mBpp; // Bits per pixel.
+ uint32_t mCompression; // See struct Compression for valid values.
+ uint32_t mImageSize; // (compressed) image size. Can be 0 if
+ // mCompression==0.
+ uint32_t mNumColors; // Used colors.
+ InfoColorSpace mCsType; // Color space type.
+ InfoColorIntent mCsIntent; // Color space intent.
+
+ union {
+ struct {
+ CalRgbEndpoint mRed;
+ CalRgbEndpoint mGreen;
+ CalRgbEndpoint mBlue;
+ } mCalibrated;
+
+ struct {
+ uint32_t mOffset;
+ uint32_t mLength;
+ } mProfile;
+ } mColorSpace;
+
+ Header()
+ : mDataOffset(0),
+ mBIHSize(0),
+ mWidth(0),
+ mHeight(0),
+ mBpp(0),
+ mCompression(0),
+ mImageSize(0),
+ mNumColors(0),
+ mCsType(InfoColorSpace::SRGB),
+ mCsIntent(InfoColorIntent::IMAGES) {}
+};
+
+/// An entry in the color table.
+struct ColorTableEntry {
+ uint8_t mRed;
+ uint8_t mGreen;
+ uint8_t mBlue;
+};
+
+/// All the color-related bitfields for 16bpp and 32bpp images. We use this
+/// even for older format BMPs that don't have explicit bitfields.
+class BitFields {
+ class Value {
+ friend class BitFields;
+
+ uint32_t mMask; // The mask for the value.
+ uint8_t mRightShift; // The amount to right-shift after masking.
+ uint8_t mBitWidth; // The width (in bits) of the value.
+
+ /// Sets the mask (and thus the right-shift and bit-width as well).
+ void Set(uint32_t aMask);
+
+ public:
+ Value() {
+ mMask = 0;
+ mRightShift = 0;
+ mBitWidth = 0;
+ }
+
+ /// Returns true if this channel is used. Only used for alpha.
+ bool IsPresent() const { return mMask != 0x0; }
+
+ /// Extracts the single color value from the multi-color value.
+ uint8_t Get(uint32_t aVal) const;
+
+ /// Like Get(), but specially for alpha.
+ uint8_t GetAlpha(uint32_t aVal, bool& aHasAlphaOut) const;
+
+ /// Specialized versions of Get() for when the bit-width is 5 or 8.
+ /// (They will assert if called and the bit-width is not 5 or 8.)
+ uint8_t Get5(uint32_t aVal) const;
+ uint8_t Get8(uint32_t aVal) const;
+ };
+
+ public:
+ /// The individual color channels.
+ Value mRed;
+ Value mGreen;
+ Value mBlue;
+ Value mAlpha;
+
+ /// Set bitfields to the standard 5-5-5 16bpp values.
+ void SetR5G5B5();
+
+ /// Set bitfields to the standard 8-8-8 32bpp values.
+ void SetR8G8B8();
+
+ /// Test if bitfields have the standard 5-5-5 16bpp values.
+ bool IsR5G5B5() const;
+
+ /// Test if bitfields have the standard 8-8-8 32bpp values.
+ bool IsR8G8B8() const;
+
+ /// Read the bitfields from a header. The reading of the alpha mask is
+ /// optional.
+ void ReadFromHeader(const char* aData, bool aReadAlpha);
+
+ /// Length of the bitfields structure in the BMP file.
+ static const size_t LENGTH = 12;
+};
+
+} // namespace bmp
+
+class RasterImage;
+
+/// Decoder for BMP-Files, as used by Windows and OS/2.
+
+class nsBMPDecoder : public Decoder {
+ public:
+ ~nsBMPDecoder();
+
+ DecoderType GetType() const override { return DecoderType::BMP; }
+
+ /// @return true if this BMP is a valid ICO resource.
+ bool IsValidICOResource() const override { return true; }
+
+ /// Obtains the internal output image buffer.
+ uint32_t* GetImageData() { return reinterpret_cast<uint32_t*>(mImageData); }
+
+ /// Obtains the length of the internal output image buffer.
+ size_t GetImageDataLength() const { return mImageDataLength; }
+
+ /// Obtains the size of the compressed image resource.
+ int32_t GetCompressedImageSize() const;
+
+ /// Mark this BMP as being within an ICO file. Only used for testing purposes
+ /// because the ICO-specific constructor does this marking automatically.
+ void SetIsWithinICO() { mIsWithinICO = true; }
+
+ /// Did the BMP file have alpha data of any kind? (Only use this after the
+ /// bitmap has been fully decoded.)
+ bool HasTransparency() const { return mDoesHaveTransparency; }
+
+ LexerResult DoDecode(SourceBufferIterator& aIterator,
+ IResumable* aOnResume) override;
+ nsresult BeforeFinishInternal() override;
+ nsresult FinishInternal() override;
+
+ private:
+ friend class DecoderFactory;
+
+ enum class State {
+ FILE_HEADER,
+ INFO_HEADER_SIZE,
+ INFO_HEADER_REST,
+ BITFIELDS,
+ SKIP_TO_COLOR_PROFILE,
+ FOUND_COLOR_PROFILE,
+ COLOR_PROFILE,
+ ALLOCATE_SURFACE,
+ COLOR_TABLE,
+ GAP,
+ AFTER_GAP,
+ PIXEL_ROW,
+ RLE_SEGMENT,
+ RLE_DELTA,
+ RLE_ABSOLUTE
+ };
+
+ // This is the constructor used for normal and clipboard BMP images.
+ explicit nsBMPDecoder(RasterImage* aImage, bool aForClipboard = false);
+
+ // This is the constructor used for BMP resources in ICO images.
+ nsBMPDecoder(RasterImage* aImage, uint32_t aDataOffset);
+
+ // Helper constructor called by the other two.
+ nsBMPDecoder(RasterImage* aImage, State aState, size_t aLength,
+ bool aForClipboard);
+
+ int32_t AbsoluteHeight() const { return abs(mH.mHeight); }
+
+ uint32_t* RowBuffer();
+ void ClearRowBufferRemainder();
+
+ void FinishRow();
+
+ void PrepareCalibratedColorProfile();
+ void PrepareColorProfileTransform();
+
+ LexerTransition<State> ReadFileHeader(const char* aData, size_t aLength);
+ LexerTransition<State> ReadInfoHeaderSize(const char* aData, size_t aLength);
+ LexerTransition<State> ReadInfoHeaderRest(const char* aData, size_t aLength);
+ LexerTransition<State> ReadBitfields(const char* aData, size_t aLength);
+ LexerTransition<State> SeekColorProfile(size_t aLength);
+ LexerTransition<State> ReadColorProfile(const char* aData, size_t aLength);
+ LexerTransition<State> AllocateSurface();
+ LexerTransition<State> ReadColorTable(const char* aData, size_t aLength);
+ LexerTransition<State> SkipGap();
+ LexerTransition<State> AfterGap();
+ LexerTransition<State> ReadPixelRow(const char* aData);
+ LexerTransition<State> ReadRLESegment(const char* aData);
+ LexerTransition<State> ReadRLEDelta(const char* aData);
+ LexerTransition<State> ReadRLEAbsolute(const char* aData, size_t aLength);
+
+ SurfacePipe mPipe;
+
+ StreamingLexer<State> mLexer;
+
+ // Iterator to save return point.
+ Maybe<SourceBufferIterator> mReturnIterator;
+
+ UniquePtr<uint32_t[]> mRowBuffer;
+
+ bmp::Header mH;
+
+ // If the BMP is within an ICO file our treatment of it differs slightly.
+ bool mIsWithinICO;
+
+ // If the BMP decoded from the clipboard, we don't start with a data offset.
+ bool mIsForClipboard;
+
+ bmp::BitFields mBitFields;
+
+ // Might the image have transparency? Determined from the headers during
+ // metadata decode. (Does not guarantee the image actually has transparency.)
+ bool mMayHaveTransparency;
+
+ // Does the image have transparency? Determined during full decoding, so only
+ // use this after that has been completed.
+ bool mDoesHaveTransparency;
+
+ uint32_t mNumColors; // The number of used colors, i.e. the number of
+ // entries in mColors, if it's present.
+ UniquePtr<bmp::ColorTableEntry[]>
+ mColors; // The color table, if it's present.
+ uint32_t mBytesPerColor; // 3 or 4, depending on the format
+
+ // The number of bytes prior to the optional gap that have been read. This
+ // is used to find the start of the pixel data.
+ uint32_t mPreGapLength;
+
+ uint32_t mPixelRowSize; // The number of bytes per pixel row.
+
+ int32_t mCurrentRow; // Index of the row of the image that's currently
+ // being decoded: [height,1].
+ int32_t mCurrentPos; // Index into the current line. Used when
+ // doing RLE decoding and when filling in pixels
+ // for truncated files.
+
+ // Only used in RLE_ABSOLUTE state: the number of pixels to read.
+ uint32_t mAbsoluteModeNumPixels;
+};
+
+} // namespace image
+} // namespace mozilla
+
+#endif // mozilla_image_decoders_nsBMPDecoder_h