1 /* vim:set tw=80 expandtab softtabstop=4 ts=4 sw=4: */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /* I got the format description from http://www.daubnet.com/formats/BMP.html */
7 /* This is a Cross-Platform BMP Decoder, which should work everywhere, including
8 * Big-Endian machines like the PowerPC. */
12 #include "EndianMacros.h"
13 #include "nsBMPDecoder.h"
15 #include "nsIInputStream.h"
16 #include "RasterImage.h"
17 #include "imgIContainerObserver.h"
18 #include "ImageLogging.h"
24 PRLogModuleInfo
*gBMPLog
= PR_NewLogModule("BMPDecoder");
27 // Convert from row (1..height) to absolute line (0..height-1)
28 #define LINE(row) ((mBIH.height < 0) ? (-mBIH.height - (row)) : ((row) - 1))
29 #define PIXEL_OFFSET(row, col) (LINE(row) * mBIH.width + col)
31 nsBMPDecoder::nsBMPDecoder(RasterImage
&aImage
, imgIDecoderObserver
* aObserver
)
32 : Decoder(aImage
, aObserver
)
37 mCurPos
= mPos
= mNumColors
= mRowBytes
= 0;
38 mOldLine
= mCurLine
= 1; // Otherwise decoder will never start
39 mState
= eRLEStateInitial
;
41 mLOH
= WIN_V3_HEADER_LENGTH
;
42 mUseAlphaData
= mHaveAlphaData
= false;
45 nsBMPDecoder::~nsBMPDecoder()
53 // Sets whether or not the BMP will use alpha data
55 nsBMPDecoder::SetUseAlphaData(bool useAlphaData
)
57 mUseAlphaData
= useAlphaData
;
60 // Obtains the bits per pixel from the internal BIH header
62 nsBMPDecoder::GetBitsPerPixel() const
67 // Obtains the width from the internal BIH header
69 nsBMPDecoder::GetWidth() const
74 // Obtains the abs-value of the height from the internal BIH header
76 nsBMPDecoder::GetHeight() const
78 return abs(mBIH
.height
);
81 // Obtains the internal output image buffer
83 nsBMPDecoder::GetImageData()
88 // Obtains the size of the compressed image resource
90 nsBMPDecoder::GetCompressedImageSize() const
92 // For everything except BI_RGB the header field must be defined
93 if (mBIH
.compression
!= BI_RGB
) {
94 return mBIH
.image_size
;
97 // mBIH.image_size isn't always filled for BI_RGB so calculate it manually
98 // The pixel array size is calculated based on extra 4 byte boundary padding
99 uint32_t rowSize
= (mBIH
.bpp
* mBIH
.width
+ 7) / 8; // + 7 to round up
100 // Pad to DWORD Boundary
102 rowSize
+= (4 - (rowSize
% 4));
105 // The height should be the absolute value of what the height is in the BIH.
106 // If positive the bitmap is stored bottom to top, otherwise top to bottom
107 int32_t pixelArraySize
= rowSize
* GetHeight();
108 return pixelArraySize
;
111 // Obtains whether or not a BMP file had alpha data in its 4th byte
112 // for 32BPP bitmaps. Only use after the bitmap has been processed.
114 nsBMPDecoder::HasAlphaData() const
116 return mHaveAlphaData
;
121 nsBMPDecoder::FinishInternal()
123 // We shouldn't be called in error cases
124 NS_ABORT_IF_FALSE(!HasError(), "Can't call FinishInternal on error!");
126 // We should never make multiple frames
127 NS_ABORT_IF_FALSE(GetFrameCount() <= 1, "Multiple BMP frames?");
129 // Send notifications if appropriate
130 if (!IsSizeDecode() && (GetFrameCount() == 1)) {
133 nsIntRect
r(0, 0, mBIH
.width
, GetHeight());
141 // ----------------------------------------
142 // Actual Data Processing
143 // ----------------------------------------
145 static void calcBitmask(uint32_t aMask
, uint8_t& aBegin
, uint8_t& aLength
)
147 // find the rightmost 1
149 bool started
= false;
150 aBegin
= aLength
= 0;
151 for (pos
= 0; pos
<= 31; pos
++) {
152 if (!started
&& (aMask
& (1 << pos
))) {
156 else if (started
&& !(aMask
& (1 << pos
))) {
157 aLength
= pos
- aBegin
;
163 NS_METHOD
nsBMPDecoder::CalcBitShift()
165 uint8_t begin
, length
;
167 calcBitmask(mBitFields
.red
, begin
, length
);
168 mBitFields
.redRightShift
= begin
;
169 mBitFields
.redLeftShift
= 8 - length
;
171 calcBitmask(mBitFields
.green
, begin
, length
);
172 mBitFields
.greenRightShift
= begin
;
173 mBitFields
.greenLeftShift
= 8 - length
;
175 calcBitmask(mBitFields
.blue
, begin
, length
);
176 mBitFields
.blueRightShift
= begin
;
177 mBitFields
.blueLeftShift
= 8 - length
;
182 nsBMPDecoder::WriteInternal(const char* aBuffer
, uint32_t aCount
)
184 NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");
186 // aCount=0 means EOF, mCurLine=0 means we're past end of image
187 if (!aCount
|| !mCurLine
)
191 if (mPos
< BFH_INTERNAL_LENGTH
) { /* In BITMAPFILEHEADER */
192 uint32_t toCopy
= BFH_INTERNAL_LENGTH
- mPos
;
195 memcpy(mRawBuf
+ mPos
, aBuffer
, toCopy
);
200 if (mPos
== BFH_INTERNAL_LENGTH
) {
202 if (mBFH
.signature
[0] != 'B' || mBFH
.signature
[1] != 'M') {
206 if (mBFH
.bihsize
== OS2_BIH_LENGTH
)
207 mLOH
= OS2_HEADER_LENGTH
;
209 if (mPos
>= BFH_INTERNAL_LENGTH
&& mPos
< mLOH
) { /* In BITMAPINFOHEADER */
210 uint32_t toCopy
= mLOH
- mPos
;
213 memcpy(mRawBuf
+ (mPos
- BFH_INTERNAL_LENGTH
), aBuffer
, toCopy
);
219 // GetNumFrames is called to ensure that if at this point mPos == mLOH but
220 // we have no data left to process, the next time WriteInternal is called
221 // we won't enter this condition again.
222 if (mPos
== mLOH
&& GetFrameCount() == 0) {
224 PR_LOG(gBMPLog
, PR_LOG_DEBUG
, ("BMP is %lix%lix%lu. compression=%lu\n",
225 mBIH
.width
, mBIH
.height
, mBIH
.bpp
, mBIH
.compression
));
226 // Verify we support this bit depth
227 if (mBIH
.bpp
!= 1 && mBIH
.bpp
!= 4 && mBIH
.bpp
!= 8 &&
228 mBIH
.bpp
!= 16 && mBIH
.bpp
!= 24 && mBIH
.bpp
!= 32) {
233 // BMPs with negative width are invalid
234 // Reject extremely wide images to keep the math sane
235 const int32_t k64KWidth
= 0x0000FFFF;
236 if (mBIH
.width
< 0 || mBIH
.width
> k64KWidth
) {
241 uint32_t real_height
= GetHeight();
243 // Post our size to the superclass
244 PostSize(mBIH
.width
, real_height
);
246 // Setting the size led to an error.
250 // We have the size. If we're doing a size decode, we got what
255 // We're doing a real decode.
256 mOldLine
= mCurLine
= real_height
;
259 mNumColors
= 1 << mBIH
.bpp
;
260 if (mBIH
.colors
&& mBIH
.colors
< mNumColors
)
261 mNumColors
= mBIH
.colors
;
263 // Always allocate 256 even though mNumColors might be smaller
264 mColors
= new colorTable
[256];
265 memset(mColors
, 0, 256 * sizeof(colorTable
));
267 else if (mBIH
.compression
!= BI_BITFIELDS
&& mBIH
.bpp
== 16) {
268 // Use default 5-5-5 format
269 mBitFields
.red
= 0x7C00;
270 mBitFields
.green
= 0x03E0;
271 mBitFields
.blue
= 0x001F;
275 // Make sure we have a valid value for our supported compression modes
276 // before adding the frame
277 if (mBIH
.compression
!= BI_RGB
&& mBIH
.compression
!= BI_RLE8
&&
278 mBIH
.compression
!= BI_RLE4
&& mBIH
.compression
!= BI_BITFIELDS
) {
283 // If we have RLE4 or RLE8 or BI_ALPHABITFIELDS, then ensure we
284 // have valid BPP values before adding the frame
285 if (mBIH
.compression
== BI_RLE8
&& mBIH
.bpp
!= 8) {
286 PR_LOG(gBMPLog
, PR_LOG_DEBUG
,
287 ("BMP RLE8 compression only supports 8 bits per pixel\n"));
291 if (mBIH
.compression
== BI_RLE4
&& mBIH
.bpp
!= 4 && mBIH
.bpp
!= 1) {
292 PR_LOG(gBMPLog
, PR_LOG_DEBUG
,
293 ("BMP RLE4 compression only supports 4 bits per pixel\n"));
297 if (mBIH
.compression
== BI_ALPHABITFIELDS
&&
298 mBIH
.bpp
!= 16 && mBIH
.bpp
!= 32) {
299 PR_LOG(gBMPLog
, PR_LOG_DEBUG
,
300 ("BMP ALPHABITFIELDS only supports 16 or 32 bits per pixel\n"));
305 uint32_t imageLength
;
306 if (mBIH
.compression
== BI_RLE8
|| mBIH
.compression
== BI_RLE4
||
307 mBIH
.compression
== BI_ALPHABITFIELDS
) {
308 rv
= mImage
.EnsureFrame(0, 0, 0, mBIH
.width
, real_height
,
309 gfxASurface::ImageFormatARGB32
,
310 (uint8_t**)&mImageData
, &imageLength
);
312 // mRow is not used for RLE encoded images
313 mRow
= (uint8_t*)moz_malloc((mBIH
.width
* mBIH
.bpp
) / 8 + 4);
314 // + 4 because the line is padded to a 4 bit boundary, but I don't want
315 // to make exact calculations here, that's unnecessary.
316 // Also, it compensates rounding error.
318 PostDecoderError(NS_ERROR_OUT_OF_MEMORY
);
323 rv
= mImage
.EnsureFrame(0, 0, 0, mBIH
.width
, real_height
,
324 gfxASurface::ImageFormatARGB32
,
325 (uint8_t**)&mImageData
, &imageLength
);
327 rv
= mImage
.EnsureFrame(0, 0, 0, mBIH
.width
, real_height
,
328 gfxASurface::ImageFormatRGB24
,
329 (uint8_t**)&mImageData
, &imageLength
);
332 if (NS_FAILED(rv
) || !mImageData
) {
333 PostDecoderError(NS_ERROR_FAILURE
);
337 // Prepare for transparency
338 if ((mBIH
.compression
== BI_RLE8
) || (mBIH
.compression
== BI_RLE4
)) {
339 // Clear the image, as the RLE may jump over areas
340 memset(mImageData
, 0, imageLength
);
343 // Tell the superclass we're starting a frame
347 if (mColors
&& mPos
>= mLOH
) {
348 // OS/2 Bitmaps have no padding byte
349 uint8_t bytesPerColor
= (mBFH
.bihsize
== OS2_BIH_LENGTH
) ? 3 : 4;
350 if (mPos
< (mLOH
+ mNumColors
* bytesPerColor
)) {
351 // Number of bytes already received
352 uint32_t colorBytes
= mPos
- mLOH
;
353 // Color which is currently received
354 uint8_t colorNum
= colorBytes
/ bytesPerColor
;
355 uint8_t at
= colorBytes
% bytesPerColor
;
356 while (aCount
&& (mPos
< (mLOH
+ mNumColors
* bytesPerColor
))) {
359 mColors
[colorNum
].blue
= *aBuffer
;
362 mColors
[colorNum
].green
= *aBuffer
;
365 mColors
[colorNum
].red
= *aBuffer
;
366 // If there is no padding byte, increment the color index
367 // since we're done with the current color.
368 if (bytesPerColor
== 3)
372 // This is a padding byte only in Windows BMPs. Increment
373 // the color index since we're done with the current color.
377 mPos
++; aBuffer
++; aCount
--;
378 at
= (at
+ 1) % bytesPerColor
;
382 else if (aCount
&& mBIH
.compression
== BI_BITFIELDS
&& mPos
< (WIN_V3_HEADER_LENGTH
+ BITFIELD_LENGTH
)) {
383 // If compression is used, this is a windows bitmap, hence we can
384 // use WIN_HEADER_LENGTH instead of mLOH
385 uint32_t toCopy
= (WIN_V3_HEADER_LENGTH
+ BITFIELD_LENGTH
) - mPos
;
388 memcpy(mRawBuf
+ (mPos
- WIN_V3_HEADER_LENGTH
), aBuffer
, toCopy
);
393 if (mPos
== WIN_V3_HEADER_LENGTH
+ BITFIELD_LENGTH
&&
394 mBIH
.compression
== BI_BITFIELDS
) {
395 mBitFields
.red
= LITTLE_TO_NATIVE32(*(uint32_t*)mRawBuf
);
396 mBitFields
.green
= LITTLE_TO_NATIVE32(*(uint32_t*)(mRawBuf
+ 4));
397 mBitFields
.blue
= LITTLE_TO_NATIVE32(*(uint32_t*)(mRawBuf
+ 8));
400 while (aCount
&& (mPos
< mBFH
.dataoffset
)) { // Skip whatever is between header and data
401 mPos
++; aBuffer
++; aCount
--;
403 if (aCount
&& ++mPos
>= mBFH
.dataoffset
) {
404 // Need to increment mPos, else we might get to mPos==mLOH again
405 // From now on, mPos is irrelevant
406 if (!mBIH
.compression
|| mBIH
.compression
== BI_BITFIELDS
) {
407 uint32_t rowSize
= (mBIH
.bpp
* mBIH
.width
+ 7) / 8; // + 7 to round up
409 rowSize
+= (4 - (rowSize
% 4)); // Pad to DWORD Boundary
413 toCopy
= rowSize
- mRowBytes
;
417 memcpy(mRow
+ mRowBytes
, aBuffer
, toCopy
);
422 if (rowSize
== mRowBytes
) {
423 // Collected a whole row into mRow, process it
425 uint32_t* d
= mImageData
+ PIXEL_OFFSET(mCurLine
, 0);
426 uint32_t lpos
= mBIH
.width
;
432 for (bit
= 7; bit
>= 0 && lpos
> 0; bit
--) {
433 idx
= (*p
>> bit
) & 1;
434 SetPixel(d
, idx
, mColors
);
442 Set4BitPixel(d
, *p
, lpos
, mColors
);
448 SetPixel(d
, *p
, mColors
);
455 uint16_t val
= LITTLE_TO_NATIVE16(*(uint16_t*)p
);
457 (val
& mBitFields
.red
) >> mBitFields
.redRightShift
<< mBitFields
.redLeftShift
,
458 (val
& mBitFields
.green
) >> mBitFields
.greenRightShift
<< mBitFields
.greenLeftShift
,
459 (val
& mBitFields
.blue
) >> mBitFields
.blueRightShift
<< mBitFields
.blueLeftShift
);
466 SetPixel(d
, p
[2], p
[1], p
[0]);
475 if (!mHaveAlphaData
&& p
[3]) {
476 // Non-zero alpha byte detected! Clear previous
477 // pixels that we have already processed.
478 // This works because we know that if we
479 // are reaching here then the alpha data in byte
480 // 4 has been right all along. And we know it
481 // has been set to 0 the whole time, so that
482 // means that everything is transparent so far.
483 uint32_t* start
= mImageData
+ GetWidth() * (mCurLine
- 1);
484 uint32_t heightDifference
= GetHeight() - mCurLine
+ 1;
485 uint32_t pixelCount
= GetWidth() * heightDifference
;
487 memset(start
, 0, pixelCount
* sizeof(uint32_t));
489 mHaveAlphaData
= true;
491 SetPixel(d
, p
[2], p
[1], p
[0], mHaveAlphaData
? p
[3] : 0xFF);
493 SetPixel(d
, p
[2], p
[1], p
[0]);
500 NS_NOTREACHED("Unsupported color depth, but earlier check didn't catch it");
503 if (mCurLine
== 0) { // Finished last line
509 } while (aCount
> 0);
511 else if ((mBIH
.compression
== BI_RLE8
) || (mBIH
.compression
== BI_RLE4
)) {
512 if (((mBIH
.compression
== BI_RLE8
) && (mBIH
.bpp
!= 8)) ||
513 ((mBIH
.compression
== BI_RLE4
) && (mBIH
.bpp
!= 4) && (mBIH
.bpp
!= 1))) {
514 PR_LOG(gBMPLog
, PR_LOG_DEBUG
, ("BMP RLE8/RLE4 compression only supports 8/4 bits per pixel\n"));
523 case eRLEStateInitial
:
524 mStateData
= (uint8_t)*aBuffer
++;
527 mState
= eRLEStateNeedSecondEscapeByte
;
530 case eRLEStateNeedSecondEscapeByte
:
533 if (mStateData
!= RLE_ESCAPE
) { // encoded mode
534 // Encoded mode consists of two bytes:
535 // the first byte (mStateData) specifies the
536 // number of consecutive pixels to be drawn
537 // using the color index contained in
539 // Work around bitmaps that specify too many pixels
540 mState
= eRLEStateInitial
;
541 uint32_t pixelsNeeded
= NS_MIN
<uint32_t>(mBIH
.width
- mCurPos
, mStateData
);
543 uint32_t* d
= mImageData
+ PIXEL_OFFSET(mCurLine
, mCurPos
);
544 mCurPos
+= pixelsNeeded
;
545 if (mBIH
.compression
== BI_RLE8
) {
547 SetPixel(d
, byte
, mColors
);
549 } while (pixelsNeeded
);
552 Set4BitPixel(d
, byte
, pixelsNeeded
, mColors
);
553 } while (pixelsNeeded
);
561 // End of Line: Go to next row
564 mState
= eRLEStateInitial
;
567 case RLE_ESCAPE_EOF
: // EndOfFile
568 mCurPos
= mCurLine
= 0;
571 case RLE_ESCAPE_DELTA
:
572 mState
= eRLEStateNeedXDelta
;
575 default : // absolute mode
576 // Save the number of pixels to read
578 if (mCurPos
+ mStateData
> (uint32_t)mBIH
.width
) {
579 // We can work around bitmaps that specify one
580 // pixel too many, but only if their width is odd.
581 mStateData
-= mBIH
.width
& 1;
582 if (mCurPos
+ mStateData
> (uint32_t)mBIH
.width
) {
588 // See if we will need to skip a byte
589 // to word align the pixel data
590 // mStateData is a number of pixels
591 // so allow for the RLE compression type
592 // Pixels RLE8=1 RLE4=2
597 if (((mStateData
- 1) & mBIH
.compression
) != 0)
598 mState
= eRLEStateAbsoluteMode
;
600 mState
= eRLEStateAbsoluteModePadded
;
605 case eRLEStateNeedXDelta
:
606 // Handle the XDelta and proceed to get Y Delta
610 if (mCurPos
> mBIH
.width
)
611 mCurPos
= mBIH
.width
;
613 mState
= eRLEStateNeedYDelta
;
616 case eRLEStateNeedYDelta
:
617 // Get the Y Delta and then "handle" the move
620 mState
= eRLEStateInitial
;
621 mCurLine
-= NS_MIN
<int32_t>(byte
, mCurLine
);
624 case eRLEStateAbsoluteMode
: // Absolute Mode
625 case eRLEStateAbsoluteModePadded
:
627 // In absolute mode, the second byte (mStateData)
628 // represents the number of pixels
629 // that follow, each of which contains
630 // the color index of a single pixel.
631 uint32_t* d
= mImageData
+ PIXEL_OFFSET(mCurLine
, mCurPos
);
632 uint32_t* oldPos
= d
;
633 if (mBIH
.compression
== BI_RLE8
) {
634 while (aCount
> 0 && mStateData
> 0) {
637 SetPixel(d
, byte
, mColors
);
641 while (aCount
> 0 && mStateData
> 0) {
644 Set4BitPixel(d
, byte
, mStateData
, mColors
);
647 mCurPos
+= d
- oldPos
;
650 if (mStateData
== 0) {
651 // In absolute mode, each run must
652 // be aligned on a word boundary
654 if (mState
== eRLEStateAbsoluteMode
) { // Word Aligned
655 mState
= eRLEStateInitial
;
656 } else if (aCount
> 0) { // Not word Aligned
657 // "next" byte is just a padding byte
658 // so "move" past it and we can continue
661 mState
= eRLEStateInitial
;
664 // else state is still eRLEStateAbsoluteMode
668 NS_ABORT_IF_FALSE(0, "BMP RLE decompression: unknown state!");
669 PostDecoderError(NS_ERROR_UNEXPECTED
);
672 // Because of the use of the continue statement
673 // we only get here for eol, eof or y delta
674 if (mCurLine
== 0) { // Finished last line
681 const uint32_t rows
= mOldLine
- mCurLine
;
685 nsIntRect
r(0, mBIH
.height
< 0 ? -mBIH
.height
- mOldLine
: mCurLine
,
695 void nsBMPDecoder::ProcessFileHeader()
697 memset(&mBFH
, 0, sizeof(mBFH
));
698 memcpy(&mBFH
.signature
, mRawBuf
, sizeof(mBFH
.signature
));
699 memcpy(&mBFH
.filesize
, mRawBuf
+ 2, sizeof(mBFH
.filesize
));
700 memcpy(&mBFH
.reserved
, mRawBuf
+ 6, sizeof(mBFH
.reserved
));
701 memcpy(&mBFH
.dataoffset
, mRawBuf
+ 10, sizeof(mBFH
.dataoffset
));
702 memcpy(&mBFH
.bihsize
, mRawBuf
+ 14, sizeof(mBFH
.bihsize
));
704 // Now correct the endianness of the header
705 mBFH
.filesize
= LITTLE_TO_NATIVE32(mBFH
.filesize
);
706 mBFH
.dataoffset
= LITTLE_TO_NATIVE32(mBFH
.dataoffset
);
707 mBFH
.bihsize
= LITTLE_TO_NATIVE32(mBFH
.bihsize
);
710 void nsBMPDecoder::ProcessInfoHeader()
712 memset(&mBIH
, 0, sizeof(mBIH
));
713 if (mBFH
.bihsize
== 12) { // OS/2 Bitmap
714 memcpy(&mBIH
.width
, mRawBuf
, 2);
715 memcpy(&mBIH
.height
, mRawBuf
+ 2, 2);
716 memcpy(&mBIH
.planes
, mRawBuf
+ 4, sizeof(mBIH
.planes
));
717 memcpy(&mBIH
.bpp
, mRawBuf
+ 6, sizeof(mBIH
.bpp
));
720 memcpy(&mBIH
.width
, mRawBuf
, sizeof(mBIH
.width
));
721 memcpy(&mBIH
.height
, mRawBuf
+ 4, sizeof(mBIH
.height
));
722 memcpy(&mBIH
.planes
, mRawBuf
+ 8, sizeof(mBIH
.planes
));
723 memcpy(&mBIH
.bpp
, mRawBuf
+ 10, sizeof(mBIH
.bpp
));
724 memcpy(&mBIH
.compression
, mRawBuf
+ 12, sizeof(mBIH
.compression
));
725 memcpy(&mBIH
.image_size
, mRawBuf
+ 16, sizeof(mBIH
.image_size
));
726 memcpy(&mBIH
.xppm
, mRawBuf
+ 20, sizeof(mBIH
.xppm
));
727 memcpy(&mBIH
.yppm
, mRawBuf
+ 24, sizeof(mBIH
.yppm
));
728 memcpy(&mBIH
.colors
, mRawBuf
+ 28, sizeof(mBIH
.colors
));
729 memcpy(&mBIH
.important_colors
, mRawBuf
+ 32, sizeof(mBIH
.important_colors
));
732 // Convert endianness
733 mBIH
.width
= LITTLE_TO_NATIVE32(mBIH
.width
);
734 mBIH
.height
= LITTLE_TO_NATIVE32(mBIH
.height
);
735 mBIH
.planes
= LITTLE_TO_NATIVE16(mBIH
.planes
);
736 mBIH
.bpp
= LITTLE_TO_NATIVE16(mBIH
.bpp
);
738 mBIH
.compression
= LITTLE_TO_NATIVE32(mBIH
.compression
);
739 mBIH
.image_size
= LITTLE_TO_NATIVE32(mBIH
.image_size
);
740 mBIH
.xppm
= LITTLE_TO_NATIVE32(mBIH
.xppm
);
741 mBIH
.yppm
= LITTLE_TO_NATIVE32(mBIH
.yppm
);
742 mBIH
.colors
= LITTLE_TO_NATIVE32(mBIH
.colors
);
743 mBIH
.important_colors
= LITTLE_TO_NATIVE32(mBIH
.important_colors
);
747 } // namespace mozilla