Bug 1214072 (part 1) - Read BMP bitfields during metadata decoding. r=seth.

Currently we don't read BMP bitfields during metadata decoding. But we'll need
to in order implement alpha, because we need to know during metadata decoding
if alpha is used.

This patch moves code around to achieve this (and adds the required
mMayHaveTransparency field). The change has no noticeable effect for now.

--HG--
extra : rebase_source : 32106149bf064f0e44ec9dcf8f013612dceacbb7
This commit is contained in:
Nicholas Nethercote 2015-10-13 20:01:24 -07:00
Родитель ae1b97a89f
Коммит 6acba8cc1c
2 изменённых файлов: 51 добавлений и 47 удалений

Просмотреть файл

@ -168,6 +168,7 @@ GetBMPLog()
nsBMPDecoder::nsBMPDecoder(RasterImage* aImage)
: Decoder(aImage)
, mLexer(Transition::To(State::FILE_HEADER, FileHeader::LENGTH))
, mMayHaveTransparency(false)
, mNumColors(0)
, mColors(nullptr)
, mBytesPerColor(0)
@ -530,6 +531,7 @@ nsBMPDecoder::ReadInfoHeaderRest(const char* aData, size_t aLength)
// Post our size to the superclass.
uint32_t realHeight = GetHeight();
PostSize(mBIH.width, realHeight);
mCurrentRow = realHeight;
// Round it up to the nearest byte count, then pad to 4-byte boundary.
// Compute this even for a metadate decode because GetCompressedImageSize()
@ -543,58 +545,13 @@ nsBMPDecoder::ReadInfoHeaderRest(const char* aData, size_t aLength)
// We treat BMPs as transparent if they're 32bpp and alpha is enabled, but
// also if they use RLE encoding, because the 'delta' mode can skip pixels
// and cause implicit transparency.
bool hasTransparency = (mBIH.compression == Compression::RLE8) ||
mMayHaveTransparency = (mBIH.compression == Compression::RLE8) ||
(mBIH.compression == Compression::RLE4) ||
(mBIH.bpp == 32 && mUseAlphaData);
if (hasTransparency) {
if (mMayHaveTransparency) {
PostHasTransparency();
}
// If we're doing a metadata decode, we're done.
if (IsMetadataDecode()) {
return Transition::Terminate(State::SUCCESS);
}
// We're doing a real decode.
mCurrentRow = realHeight;
// Set up the color table, if present; it'll be filled in by ReadColorTable().
if (mBIH.bpp <= 8) {
mNumColors = 1 << mBIH.bpp;
if (0 < mBIH.colors && mBIH.colors < mNumColors) {
mNumColors = mBIH.colors;
}
// Always allocate and zero 256 entries, even though mNumColors might be
// smaller, because the file might erroneously index past mNumColors.
mColors = new ColorTableEntry[256];
memset(mColors, 0, 256 * sizeof(ColorTableEntry));
// OS/2 Bitmaps have no padding byte.
mBytesPerColor = (mBIH.bihsize == InfoHeaderLength::WIN_V2) ? 3 : 4;
}
MOZ_ASSERT(!mImageData, "Already have a buffer allocated?");
IntSize targetSize = mDownscaler ? mDownscaler->TargetSize() : GetSize();
nsresult rv = AllocateFrame(/* aFrameNum = */ 0, targetSize,
IntRect(IntPoint(), targetSize),
SurfaceFormat::B8G8R8A8);
if (NS_FAILED(rv)) {
return Transition::Terminate(State::FAILURE);
}
MOZ_ASSERT(mImageData, "Should have a buffer now");
if (mDownscaler) {
// BMPs store their rows in reverse order, so the downscaler needs to
// reverse them again when writing its output.
rv = mDownscaler->BeginFrame(GetSize(), Nothing(),
mImageData, hasTransparency,
/* aFlipVertically = */ true);
if (NS_FAILED(rv)) {
return Transition::Terminate(State::FAILURE);
}
}
size_t bitFieldsLengthStillToRead = 0;
if (mBIH.compression == Compression::BITFIELDS) {
// Need to read bitfields.
@ -634,6 +591,49 @@ nsBMPDecoder::ReadBitfields(const char* aData, size_t aLength)
mBitFields.ReadFromHeader(aData);
}
// We've now read all the headers. If we're doing a metadata decode, we're
// done.
if (IsMetadataDecode()) {
return Transition::Terminate(State::SUCCESS);
}
// Set up the color table, if present; it'll be filled in by ReadColorTable().
if (mBIH.bpp <= 8) {
mNumColors = 1 << mBIH.bpp;
if (0 < mBIH.colors && mBIH.colors < mNumColors) {
mNumColors = mBIH.colors;
}
// Always allocate and zero 256 entries, even though mNumColors might be
// smaller, because the file might erroneously index past mNumColors.
mColors = new ColorTableEntry[256];
memset(mColors, 0, 256 * sizeof(ColorTableEntry));
// OS/2 Bitmaps have no padding byte.
mBytesPerColor = (mBIH.bihsize == InfoHeaderLength::WIN_V2) ? 3 : 4;
}
MOZ_ASSERT(!mImageData, "Already have a buffer allocated?");
IntSize targetSize = mDownscaler ? mDownscaler->TargetSize() : GetSize();
nsresult rv = AllocateFrame(/* aFrameNum = */ 0, targetSize,
IntRect(IntPoint(), targetSize),
SurfaceFormat::B8G8R8A8);
if (NS_FAILED(rv)) {
return Transition::Terminate(State::FAILURE);
}
MOZ_ASSERT(mImageData, "Should have a buffer now");
if (mDownscaler) {
// BMPs store their rows in reverse order, so the downscaler needs to
// reverse them again when writing its output.
rv = mDownscaler->BeginFrame(GetSize(), Nothing(),
mImageData, mMayHaveTransparency,
/* aFlipVertically = */ true);
if (NS_FAILED(rv)) {
return Transition::Terminate(State::FAILURE);
}
}
return Transition::To(State::COLOR_TABLE, mNumColors * mBytesPerColor);
}

Просмотреть файл

@ -153,6 +153,10 @@ private:
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;
uint32_t mNumColors; // The number of used colors, i.e. the number of
// entries in mColors, if it's present.
bmp::ColorTableEntry* mColors; // The color table, if it's present.