// Returns a buffer filled with the bitmap file header in little endian: // Signature 2 bytes 'BM' // FileSize 4 bytes File size in bytes // reserved 4 bytes unused (=0) // DataOffset 4 bytes File offset to Raster Data // Returns true if successful bool nsICODecoder::FillBitmapFileHeaderBuffer(PRInt8 *bfh) { memset(bfh, 0, 14); bfh[0] = 'B'; bfh[1] = 'M'; PRInt32 dataOffset = 0; PRInt32 fileSize = 0; dataOffset = BFH_LENGTH + BITMAPINFOSIZE; // The color table is present only if BPP is <= 8 if (mDirEntry.mBitCount <= 8) { PRUint16 numColors = GetNumColors(); if (numColors == (PRUint16)-1) { return false; } dataOffset += 4 * numColors; fileSize = dataOffset + GetRealWidth() * GetRealHeight(); } else { fileSize = dataOffset + (mDirEntry.mBitCount * GetRealWidth() * GetRealHeight()) / 8; } fileSize = NATIVE32_TO_LITTLE(fileSize); memcpy(bfh + 2, &fileSize, sizeof(fileSize)); dataOffset = NATIVE32_TO_LITTLE(dataOffset); memcpy(bfh + 10, &dataOffset, sizeof(dataOffset)); return true; }
// A BMP inside of an ICO has *2 height because of the AND mask // that follows the actual bitmap. The BMP shouldn't know about // this difference though. bool nsICODecoder::FixBitmapHeight(PRInt8 *bih) { // Get the height from the BMP file information header PRInt32 height; memcpy(&height, bih + 8, sizeof(height)); height = LITTLE_TO_NATIVE32(height); // The bitmap height is by definition * 2 what it should be to account for // the 'AND mask'. It is * 2 even if the `AND mask` is not present. height /= 2; if (height > 256) { return false; } // We should always trust the height from the bitmap itself instead of // the ICO height. So fix the ICO height. if (height == 256) { mDirEntry.mHeight = 0; } else { mDirEntry.mHeight = (PRInt8)height; } // Fix the BMP height in the BIH so that the BMP decoder can work properly height = NATIVE32_TO_LITTLE(height); memcpy(bih + 8, &height, sizeof(height)); return true; }
// A BMP inside of an ICO has *2 height because of the AND mask // that follows the actual bitmap. The BMP shouldn't know about // this difference though. void nsICODecoder::FillBitmapInformationBufferHeight(PRInt8 *bih) { PRInt32 height = GetRealHeight(); height = NATIVE32_TO_LITTLE(height); memcpy(bih + 8, &height, sizeof(height)); }