diff options
Diffstat (limited to 'image')
-rw-r--r-- | image/DecoderFactory.cpp | 7 | ||||
-rw-r--r-- | image/DecoderFactory.h | 1 | ||||
-rw-r--r-- | image/decoders/nsBMPDecoder.cpp | 40 | ||||
-rw-r--r-- | image/decoders/nsBMPDecoder.h | 9 | ||||
-rw-r--r-- | image/imgFrame.cpp | 2 |
5 files changed, 50 insertions, 9 deletions
diff --git a/image/DecoderFactory.cpp b/image/DecoderFactory.cpp index 2085fb7c4..dffe4dc21 100644 --- a/image/DecoderFactory.cpp +++ b/image/DecoderFactory.cpp @@ -58,6 +58,10 @@ DecoderFactory::GetDecoderType(const char* aMimeType) } else if (!strcmp(aMimeType, IMAGE_BMP_MS)) { type = DecoderType::BMP; + // BMP_CLIPBOARD + } else if (!strcmp(aMimeType, IMAGE_BMP_MS_CLIPBOARD)) { + type = DecoderType::BMP_CLIPBOARD; + // ICO } else if (!strcmp(aMimeType, IMAGE_ICO)) { type = DecoderType::ICO; @@ -100,6 +104,9 @@ DecoderFactory::GetDecoder(DecoderType aType, case DecoderType::BMP: decoder = new nsBMPDecoder(aImage); break; + case DecoderType::BMP_CLIPBOARD: + decoder = new nsBMPDecoder(aImage, /* aForClipboard */ true); + break; case DecoderType::ICO: decoder = new nsICODecoder(aImage); break; diff --git a/image/DecoderFactory.h b/image/DecoderFactory.h index f8cf64cc6..5638789ff 100644 --- a/image/DecoderFactory.h +++ b/image/DecoderFactory.h @@ -34,6 +34,7 @@ enum class DecoderType GIF, JPEG, BMP, + BMP_CLIPBOARD, ICO, ICON, WEBP, diff --git a/image/decoders/nsBMPDecoder.cpp b/image/decoders/nsBMPDecoder.cpp index 42bb3486a..b93eb42b6 100644 --- a/image/decoders/nsBMPDecoder.cpp +++ b/image/decoders/nsBMPDecoder.cpp @@ -66,6 +66,17 @@ // compression, then instead of treating the pixel data as 0RGB it is treated // as ARGB, but only if one or more of the A values are non-zero. // +// Clipboard variants. +// - It's the BMP format used for BMP images captured from the clipboard. +// - It is missing the file header, containing the BM signature and the data +// offset. Instead the data begins after the header. +// - If it uses BITFIELDS compression, then there is always an additional 12 +// bytes of data after the header that must be read. In WinBMPv4+, the masks +// are supposed to be included in the header size, which are the values we use +// for decoding purposes, but there is additional three masks following the +// header which must be skipped to get to the pixel data. +// +// // OS/2 VERSIONS OF THE BMP FORMAT // ------------------------------- // OS2-BMPv1. @@ -168,10 +179,12 @@ static mozilla::LazyLogModule sBMPLog("BMPDecoder"); // The length of the mBIHSize field in the info header. static const uint32_t BIHSIZE_FIELD_LENGTH = 4; -nsBMPDecoder::nsBMPDecoder(RasterImage* aImage, State aState, size_t aLength) +nsBMPDecoder::nsBMPDecoder(RasterImage* aImage, State aState, size_t aLength, + bool aForClipboard) : Decoder(aImage) , mLexer(Transition::To(aState, aLength), Transition::TerminateSuccess()) , mIsWithinICO(false) + , mIsForClipboard(aForClipboard) , mMayHaveTransparency(false) , mDoesHaveTransparency(false) , mNumColors(0) @@ -185,15 +198,19 @@ nsBMPDecoder::nsBMPDecoder(RasterImage* aImage, State aState, size_t aLength) { } -// Constructor for normal BMP files. -nsBMPDecoder::nsBMPDecoder(RasterImage* aImage) - : nsBMPDecoder(aImage, State::FILE_HEADER, FILE_HEADER_LENGTH) +// Constructor for normal BMP files or from the clipboard. +nsBMPDecoder::nsBMPDecoder(RasterImage* aImage, bool aForClipboard) + : nsBMPDecoder(aImage, + aForClipboard ? State::INFO_HEADER_SIZE : State::FILE_HEADER, + aForClipboard ? BIHSIZE_FIELD_LENGTH : FILE_HEADER_LENGTH, + aForClipboard) { } // Constructor used for WinBMPv3-ICO files, which lack a file header. nsBMPDecoder::nsBMPDecoder(RasterImage* aImage, uint32_t aDataOffset) - : nsBMPDecoder(aImage, State::INFO_HEADER_SIZE, BIHSIZE_FIELD_LENGTH) + : nsBMPDecoder(aImage, State::INFO_HEADER_SIZE, BIHSIZE_FIELD_LENGTH, + /* aForClipboard */ false) { SetIsWithinICO(); @@ -598,6 +615,13 @@ nsBMPDecoder::ReadInfoHeaderRest(const char* aData, size_t aLength) // Bitfields are present in the info header, so we can read them // immediately. mBitFields.ReadFromHeader(aData + 36, /* aReadAlpha = */ true); + + // If this came from the clipboard, then we know that even if the header + // explicitly includes the bitfield masks, we need to add an additional + // offset for the start of the RGB data. + if (mIsForClipboard) { + mH.mDataOffset += BitFields::LENGTH; + } } else { // Bitfields are present after the info header, so we will read them in // ReadBitfields(). @@ -712,6 +736,12 @@ nsBMPDecoder::ReadColorTable(const char* aData, size_t aLength) aData += mBytesPerColor; } + // If we are decoding a BMP from the clipboard, we did not know the data + // offset in advance. It is defined as just after the header and color table. + if (mIsForClipboard) { + mH.mDataOffset += mPreGapLength; + } + // We know how many bytes we've read so far (mPreGapLength) and we know the // offset of the pixel data (mH.mDataOffset), so we can determine the length // of the gap (possibly zero) between the color table and the pixel data. diff --git a/image/decoders/nsBMPDecoder.h b/image/decoders/nsBMPDecoder.h index 0cf2af689..4b9568487 100644 --- a/image/decoders/nsBMPDecoder.h +++ b/image/decoders/nsBMPDecoder.h @@ -164,14 +164,14 @@ private: RLE_ABSOLUTE }; - // This is the constructor used for normal BMP images. - explicit nsBMPDecoder(RasterImage* aImage); + // 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); + nsBMPDecoder(RasterImage* aImage, State aState, size_t aLength, bool aForClipboard); int32_t AbsoluteHeight() const { return abs(mH.mHeight); } @@ -198,6 +198,9 @@ private: // If the BMP is within an ICO file our treatment of it differs slightly. bool mIsWithinICO; + // If the BMP is decoded from the clipboard, we start with a data offset. + bool mIsForClipboard; + bmp::BitFields mBitFields; // Might the image have transparency? Determined from the headers during diff --git a/image/imgFrame.cpp b/image/imgFrame.cpp index c9f44181d..d982c17c4 100644 --- a/image/imgFrame.cpp +++ b/image/imgFrame.cpp @@ -161,13 +161,13 @@ imgFrame::imgFrame() : mMonitor("imgFrame") , mDecoded(0, 0, 0, 0) , mLockCount(0) + , mHasNoAlpha(false) , mAborted(false) , mFinished(false) , mOptimizable(false) , mTimeout(FrameTimeout::FromRawMilliseconds(100)) , mDisposalMethod(DisposalMethod::NOT_SPECIFIED) , mBlendMethod(BlendMethod::OVER) - , mHasNoAlpha(false) , mPalettedImageData(nullptr) , mPaletteDepth(0) , mNonPremult(false) |