108271 r=paper sr=tor

support all bitfields in the bmp decoder


git-svn-id: svn://10.0.0.236/trunk@133511 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
cbiesinger%web.de 2002-11-09 23:06:25 +00:00
parent 4bd8bf317a
commit aac3a6ac3a
2 changed files with 51 additions and 31 deletions

View File

@ -38,7 +38,6 @@
/* This does not yet work in this version:
* o) Compressed Bitmaps
* o) Bitfields which are not 5-5-5 or 5-6-5
* This decoder was tested on Windows, Linux and Mac. */
/* This is a Cross-Platform BMP Decoder, which should work everywhere, including
@ -159,6 +158,42 @@ nsresult nsBMPDecoder::SetData(PRUint8* aData)
return NS_OK;
}
static void calcBitmask(PRUint32 aMask, PRUint8& aBegin, PRUint8& aLength)
{
// find the rightmost 1
PRUint8 pos;
PRBool started = PR_FALSE;
aBegin = aLength = 0;
for (pos = 0; pos <= 31; pos++) {
if (!started && (aMask & (1 << pos))) {
aBegin = pos;
started = PR_TRUE;
}
else if (started && !(aMask & (1 << pos))) {
aLength = pos - aBegin;
break;
}
}
}
NS_METHOD nsBMPDecoder::CalcBitShift()
{
PRUint8 begin, length;
// red
calcBitmask(mBitFields.red, begin, length);
mBitFields.redRightShift = begin;
mBitFields.redLeftShift = 8 - length;
// green
calcBitmask(mBitFields.green, begin, length);
mBitFields.greenRightShift = begin;
mBitFields.greenLeftShift = 8 - length;
// blue
calcBitmask(mBitFields.blue, begin, length);
mBitFields.blueRightShift = begin;
mBitFields.blueLeftShift = 8 - length;
return NS_OK;
}
NS_METHOD nsBMPDecoder::ProcessData(const char* aBuffer, PRUint32 aCount)
{
if (!aCount || (mCurLine < 0)) // aCount=0 means EOF, mCurLine < 0 means we're past end of image
@ -225,11 +260,9 @@ NS_METHOD nsBMPDecoder::ProcessData(const char* aBuffer, PRUint32 aCount)
else if (mBIH.compression != BI_BITFIELDS && mBIH.bpp == 16) {
// Use default 5-5-5 format
mBitFields.red = 0x7C00;
mBitFields.redshift = 7;
mBitFields.green = 0x03E0;
mBitFields.greenshift = 2;
mBitFields.blue = 0x001F;
mBitFields.blueshift = 3; // is treated as -3
CalcBitShift();
}
rv = mImage->Init(mBIH.width, mBIH.height, mObserver);
@ -292,26 +325,7 @@ NS_METHOD nsBMPDecoder::ProcessData(const char* aBuffer, PRUint32 aCount)
mBitFields.red = LITTLE_TO_NATIVE32(*(PRUint32*)mRawBuf);
mBitFields.green = LITTLE_TO_NATIVE32(*(PRUint32*)(mRawBuf + 4));
mBitFields.blue = LITTLE_TO_NATIVE32(*(PRUint32*)(mRawBuf + 8));
if (mBIH.bpp == 16) {
if (mBitFields.red == 0x7C00 && mBitFields.green == 0x03E0 && mBitFields.blue == 0x1F) {
// 5-5-5
mBitFields.redshift = 7;
mBitFields.greenshift = 2;
mBitFields.blueshift = 3;
}
else if (mBitFields.red == 0xF800 && mBitFields.green == 0x7E0 && mBitFields.blue == 0x1F) {
// 5-6-5
mBitFields.redshift = 8;
mBitFields.greenshift = 3;
mBitFields.blueshift = 3;
}
else
return NS_ERROR_FAILURE;
}
else if (mBIH.bpp == 32 && (mBitFields.red != 0xFF0000 || mBitFields.green != 0xFF00
|| mBitFields.blue != 0xFF))
// We only support 8-8-8 32 bit BMPs
return NS_ERROR_FAILURE;
CalcBitShift();
}
while (aCount && (mPos < mBFH.dataoffset)) { // Skip whatever is between header and data
mPos++; aBuffer++; aCount--;
@ -377,10 +391,9 @@ NS_METHOD nsBMPDecoder::ProcessData(const char* aBuffer, PRUint32 aCount)
while (lpos < mBIH.width) {
PRUint16 val = LITTLE_TO_NATIVE16(*(PRUint16*)p);
SetPixel(d,
(val & mBitFields.red) >> mBitFields.redshift,
(val & mBitFields.green) >> mBitFields.greenshift,
(val & mBitFields.blue) << mBitFields.blueshift);
// Blue shift is always negative
(val & mBitFields.red) >> mBitFields.redRightShift << mBitFields.redLeftShift,
(val & mBitFields.green) >> mBitFields.greenRightShift << mBitFields.greenLeftShift,
(val & mBitFields.blue) >> mBitFields.blueRightShift << mBitFields.blueLeftShift);
++lpos;
p+=2;
}

View File

@ -86,9 +86,12 @@ struct bitFields {
PRUint32 red;
PRUint32 green;
PRUint32 blue;
PRInt8 redshift;
PRInt8 greenshift;
PRInt8 blueshift;
PRUint8 redLeftShift;
PRUint8 redRightShift;
PRUint8 greenLeftShift;
PRUint8 greenRightShift;
PRUint8 blueLeftShift;
PRUint8 blueRightShift;
};
#if defined WORDS_BIGENDIAN || defined IS_BIG_ENDIAN
@ -133,6 +136,10 @@ private:
* @oaram count Number of bytes in mBuffer */
NS_METHOD ProcessData(const char* aBuffer, PRUint32 aCount);
/** Calculates the red-, green- and blueshift in mBitFields using
* the bitmasks from mBitFields */
NS_METHOD CalcBitShift();
/** Sets the image data at specified position. mCurLine is used
* to get the row
* @param aData The data */