1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
38 //-------------------------------
40 //-------------------------------
45 #include "OSGConfig.h"
47 #include "OSGBMPImageFileType.h"
54 /*! \class BMPImageFileType
56 Image File Type to read/write and store/restore Image objects as
59 All the type specific code is included in the class. Does
60 not depend on external libs.
62 @author Patrick Dähne
68 UInt32
parseUInt32(char *&ptr
)
71 (static_cast<UInt32
>(static_cast<UInt8
>(ptr
[0])) << 0) |
72 (static_cast<UInt32
>(static_cast<UInt8
>(ptr
[1])) << 8) |
73 (static_cast<UInt32
>(static_cast<UInt8
>(ptr
[2])) << 16) |
74 (static_cast<UInt32
>(static_cast<UInt8
>(ptr
[3])) << 24);
79 UInt16
parseUInt16(char *&ptr
)
82 (static_cast<UInt32
>(static_cast<UInt8
>(ptr
[0])) << 0) |
83 (static_cast<UInt32
>(static_cast<UInt8
>(ptr
[1])) << 8);
88 struct OSGBITMAPFILEHEADER
97 struct OSGBITMAPINFOHEADER
101 Int32 biHeight
; // Not a typo - height can be negative
104 UInt32 biCompression
;
106 UInt32 biXPelsPerMeter
;
107 UInt32 biYPelsPerMeter
;
109 UInt32 biClrImportant
;
121 bool readBitmapFileHeader(std::istream
&is
, OSGBITMAPFILEHEADER
&header
)
126 if (is
.gcount() != 14)
131 memcpy(header
.bfType
, ptr
, 2);
133 header
.bfSize
= parseUInt32(ptr
);
134 header
.bfReserved1
= parseUInt16(ptr
);
135 header
.bfReserved2
= parseUInt16(ptr
);
136 header
.bfOffBits
= parseUInt32(ptr
);
139 if (memcmp(header
.bfType
, "BM", 2) != 0)
145 bool readBitmapInfoHeader(std::istream
&is
, OSGBITMAPINFOHEADER
&infoHeader
)
147 // Determine size of the header
150 if (is
.gcount() != 4)
153 infoHeader
.biSize
= parseUInt32(ptr
);
155 infoHeader
.redMask
= 0;
156 infoHeader
.greenMask
= 0;
157 infoHeader
.blueMask
= 0;
158 infoHeader
.alphaMask
= 0;
161 if (infoHeader
.biSize
>= 40)
163 // Read the remaining header
164 int size
= infoHeader
.biSize
>= 56 ? 56 - 4 : 40 - 4;
165 is
.read(&(buffer
[4]), size
);
166 if (is
.gcount() != size
)
169 infoHeader
.biWidth
= parseUInt32(ptr
);
170 infoHeader
.biHeight
= parseUInt32(ptr
);
171 infoHeader
.biPlanes
= parseUInt16(ptr
);
172 infoHeader
.biBitCount
= parseUInt16(ptr
);
173 infoHeader
.biCompression
= parseUInt32(ptr
);
174 infoHeader
.biSizeImage
= parseUInt32(ptr
);
175 infoHeader
.biXPelsPerMeter
= parseUInt32(ptr
);
176 infoHeader
.biYPelsPerMeter
= parseUInt32(ptr
);
177 infoHeader
.biClrUsed
= parseUInt32(ptr
);
178 infoHeader
.biClrImportant
= parseUInt32(ptr
);
180 if ((infoHeader
.biSize
>= 56) && (infoHeader
.biCompression
== 3 /*BI_BITFIELDS*/))
182 infoHeader
.redMask
= parseUInt32(ptr
);
183 infoHeader
.greenMask
= parseUInt32(ptr
);
184 infoHeader
.blueMask
= parseUInt32(ptr
);
185 infoHeader
.alphaMask
= parseUInt32(ptr
);
188 infoHeader
.alphaMask
= 0;
190 is
.ignore(infoHeader
.biSize
- size
- 4);
192 else if (infoHeader
.biSize
>= 12)
194 // Read the remaining header
195 is
.read(&(buffer
[4]), 12 - 4);
196 if (is
.gcount() != 12 - 4)
199 infoHeader
.biWidth
= parseUInt16(ptr
);
200 infoHeader
.biHeight
= parseUInt16(ptr
);
201 infoHeader
.biPlanes
= parseUInt16(ptr
);
202 infoHeader
.biBitCount
= parseUInt16(ptr
);
203 infoHeader
.biCompression
= 0;
204 infoHeader
.biSizeImage
= 0;
205 infoHeader
.biXPelsPerMeter
= 0;
206 infoHeader
.biYPelsPerMeter
= 0;
207 infoHeader
.biClrUsed
= 0;
208 infoHeader
.biClrImportant
= 0;
210 is
.ignore(infoHeader
.biSize
- 12);
216 if ((infoHeader
.biBitCount
!= 1) &&
217 (infoHeader
.biBitCount
!= 4) &&
218 (infoHeader
.biBitCount
!= 8) &&
219 (infoHeader
.biBitCount
!= 16) &&
220 (infoHeader
.biBitCount
!= 24) &&
221 (infoHeader
.biBitCount
!= 32))
223 if (infoHeader
.biPlanes
!= 1)
225 if ((infoHeader
.biBitCount
== 1) && (infoHeader
.biCompression
!= 0 /*BI_RGB*/))
227 if ((infoHeader
.biBitCount
== 4) && (infoHeader
.biCompression
!= 0 /*BI_RGB*/) &&
228 (infoHeader
.biCompression
!= 2 /*BI_RLE4*/))
230 if ((infoHeader
.biBitCount
== 8) && (infoHeader
.biCompression
!= 0 /*BI_RGB*/) &&
231 (infoHeader
.biCompression
!= 1 /*BI_RLE8*/))
233 if ((infoHeader
.biBitCount
== 16) && (infoHeader
.biCompression
!= 0 /*BI_RGB*/) &&
234 (infoHeader
.biCompression
!= 3 /*BI_BITFIELDS*/))
236 if ((infoHeader
.biBitCount
== 24) && (infoHeader
.biCompression
!= 0 /*BI_RGB*/))
238 if ((infoHeader
.biBitCount
== 32) && (infoHeader
.biCompression
!= 0 /*BI_RGB*/) &&
239 (infoHeader
.biCompression
!= 3 /*BI_BITFIELDS*/))
242 if (infoHeader
.biSize
< 56)
244 if (infoHeader
.biCompression
== 3 /*BI_BITFIELDS*/)
247 if (is
.gcount() != 12)
250 infoHeader
.redMask
= parseUInt32(ptr
);
251 infoHeader
.greenMask
= parseUInt32(ptr
);
252 infoHeader
.blueMask
= parseUInt32(ptr
);
253 infoHeader
.alphaMask
= 0;
254 infoHeader
.biSize
+= 12;
256 else if (infoHeader
.biBitCount
== 16)
258 infoHeader
.redMask
= 0x7c00;
259 infoHeader
.greenMask
= 0x03e0;
260 infoHeader
.blueMask
= 0x001f;
261 infoHeader
.alphaMask
= 0;
263 else if (infoHeader
.biBitCount
== 32)
265 infoHeader
.redMask
= 0x00ff0000;
266 infoHeader
.greenMask
= 0x0000ff00;
267 infoHeader
.blueMask
= 0x000000ff;
268 infoHeader
.alphaMask
= 0xff000000;
273 std::cout
<< "infoHeader.biSize = " << infoHeader
.biSize
<< std::endl
;
274 std::cout
<< "infoHeader.biWidth = " << infoHeader
.biWidth
<< std::endl
;
275 std::cout
<< "infoHeader.biHeight = " << infoHeader
.biHeight
<< std::endl
;
276 std::cout
<< "infoHeader.biPlanes = " << infoHeader
.biPlanes
<< std::endl
;
277 std::cout
<< "infoHeader.biBitCount = " << infoHeader
.biBitCount
<< std::endl
;
278 std::cout
<< "infoHeader.biCompression = " << infoHeader
.biCompression
<< std::endl
;
284 bool readColorMap(std::istream
&is
, const OSGBITMAPFILEHEADER
&fileHeader
,
285 const OSGBITMAPINFOHEADER
&infoHeader
, RGB colorMap
[256])
287 if (infoHeader
.biBitCount
<= 8)
289 UInt32 nCols
= 1 << infoHeader
.biBitCount
;
290 if (infoHeader
.biClrUsed
> 0)
292 if (infoHeader
.biClrUsed
> nCols
)
294 nCols
= infoHeader
.biClrUsed
;
296 int bytesPerColor
= (infoHeader
.biSize
< 40) || (infoHeader
.biSize
+ 14 + 4 * nCols
> fileHeader
.bfOffBits
)
298 char buffer
[256 * 4];
299 is
.read(buffer
, nCols
* bytesPerColor
);
300 if (static_cast<UInt32
>(is
.gcount()) != nCols
* bytesPerColor
)
303 for (UInt32 i
= 0; i
< nCols
; ++i
)
305 colorMap
[i
].r
= ptr
[2];
306 colorMap
[i
].g
= ptr
[1];
307 colorMap
[i
].b
= ptr
[0];
308 ptr
+= bytesPerColor
;
315 bool parseUncompressedPaletteImage(std::istream
&is
, const OSGBITMAPINFOHEADER
&infoHeader
,
316 const RGB colorMap
[256], Image
* image
)
318 unsigned long mask
= (1 << infoHeader
.biBitCount
) - 1;
322 if (infoHeader
.biHeight
>= 0)
324 height
= infoHeader
.biHeight
;
325 bytesPerLine
= infoHeader
.biWidth
* 3;
326 data
= image
->editData();
330 height
= -infoHeader
.biHeight
;
331 bytesPerLine
= infoHeader
.biWidth
* -3;
332 data
= image
->editData() + image
->getSize() + bytesPerLine
;
335 for (int y
= 0; y
< height
; ++y
)
338 unsigned long bits
= 0;
340 for (unsigned int x
= 0; x
< infoHeader
.biWidth
; ++x
)
346 if (is
.gcount() != 4)
348 bits
= (static_cast<UInt32
>(static_cast<UInt8
>(buffer
[0])) << 24) |
349 (static_cast<UInt32
>(static_cast<UInt8
>(buffer
[1])) << 16) |
350 (static_cast<UInt32
>(static_cast<UInt8
>(buffer
[2])) << 8) |
351 (static_cast<UInt32
>(static_cast<UInt8
>(buffer
[3])) << 0);
352 shift
= 32 - infoHeader
.biBitCount
;
355 shift
-= infoHeader
.biBitCount
;
356 unsigned long index
= (bits
>> shift
) & mask
;
357 *ptr
++ = colorMap
[index
].r
;
358 *ptr
++ = colorMap
[index
].g
;
359 *ptr
++ = colorMap
[index
].b
;
361 data
+= bytesPerLine
;
367 bool parseRLEImage(std::istream
&is
, const OSGBITMAPINFOHEADER
&infoHeader
, const RGB colorMap
[256], Image
* image
)
372 if (infoHeader
.biHeight
>= 0)
374 height
= infoHeader
.biHeight
;
375 bytesPerLine
= infoHeader
.biWidth
* 3;
376 data
= image
->editData();
380 height
= -infoHeader
.biHeight
;
381 bytesPerLine
= infoHeader
.biWidth
* -3;
382 data
= image
->editData() + image
->getSize() + bytesPerLine
;
387 for (unsigned int y
= 0; y
< height
; )
391 if ((c1
== EOF
) || (c2
== EOF
))
393 if (c1
== 0) // Escape
397 case 0: // End of line
400 data
+= bytesPerLine
;
403 case 1: // End of bitmap
408 int xOffset
= is
.get();
409 int yOffset
= is
.get();
410 if ((xOffset
== EOF
) || (yOffset
== EOF
))
414 if ((x
>= infoHeader
.biWidth
) || (y
>= height
))
416 data
+= bytesPerLine
* yOffset
;
417 ptr
+= bytesPerLine
* yOffset
+ 3 * xOffset
;
420 default: // Absolute mode
421 if (infoHeader
.biWidth
- x
< static_cast<unsigned int>(c2
))
422 c2
= infoHeader
.biWidth
- x
;
424 if (infoHeader
.biBitCount
== 4)
427 for (int i
= 0; i
< n
; ++i
)
435 if ((c1
== EOF
) || (c2
== EOF
))
449 index
= 0; // Just to get rid of compiler warnings...
452 *ptr
++ = colorMap
[index
].r
;
453 *ptr
++ = colorMap
[index
].g
;
454 *ptr
++ = colorMap
[index
].b
;
458 for (int i
= 0; i
< c2
; ++i
)
465 if ((index
== EOF
) || (c1
== EOF
))
470 *ptr
++ = colorMap
[index
].r
;
471 *ptr
++ = colorMap
[index
].g
;
472 *ptr
++ = colorMap
[index
].b
;
479 if (infoHeader
.biWidth
- x
< static_cast<unsigned int>(c1
))
480 c1
= infoHeader
.biWidth
- x
;
482 if (infoHeader
.biBitCount
== 4)
483 for (int i
= 0; i
< c1
; ++i
)
485 int index
= (i
& 1) == 0 ? c2
>> 4 : c2
& 0xf;
486 *ptr
++ = colorMap
[index
].r
;
487 *ptr
++ = colorMap
[index
].g
;
488 *ptr
++ = colorMap
[index
].b
;
491 for (int i
= 0; i
< c1
; ++i
)
493 *ptr
++ = colorMap
[c2
].r
;
494 *ptr
++ = colorMap
[c2
].g
;
495 *ptr
++ = colorMap
[c2
].b
;
503 int calcShift(UInt32 mask
)
516 bool parseTrueColorImage(std::istream
&is
, const OSGBITMAPINFOHEADER
&infoHeader
, Image
* image
)
518 int redShift
= calcShift(infoHeader
.redMask
);
519 int redScale
= infoHeader
.redMask
== 0 ? 0 : 255 / (infoHeader
.redMask
>> redShift
);
520 int greenShift
= calcShift(infoHeader
.greenMask
);
521 int greenScale
= infoHeader
.greenMask
== 0 ? 0 : 255 / (infoHeader
.greenMask
>> greenShift
);
522 int blueShift
= calcShift(infoHeader
.blueMask
);
523 int blueScale
= infoHeader
.blueMask
== 0 ? 0 : 255 / (infoHeader
.blueMask
>> blueShift
);
524 int alphaShift
= calcShift(infoHeader
.alphaMask
);
525 int alphaScale
= infoHeader
.alphaMask
== 0 ? 0 : 255 / (infoHeader
.alphaMask
>> alphaShift
);
528 long bytesPerLine
= infoHeader
.biWidth
* (infoHeader
.alphaMask
!= 0 ? 4 : 3);
530 if (infoHeader
.biHeight
>= 0)
532 height
= infoHeader
.biHeight
;
533 data
= image
->editData();
537 height
= -infoHeader
.biHeight
;
538 bytesPerLine
= -bytesPerLine
;
539 data
= image
->editData() + image
->getSize() + bytesPerLine
;
542 for (int y
= 0; y
< height
; ++y
)
545 unsigned long bits
= 0;
547 for (unsigned int x
= 0; x
< infoHeader
.biWidth
; ++x
)
553 if (is
.gcount() != 4)
555 bits
= (static_cast<UInt32
>(static_cast<UInt8
>(buffer
[0])) << 0) |
556 (static_cast<UInt32
>(static_cast<UInt8
>(buffer
[1])) << 8) |
557 (static_cast<UInt32
>(static_cast<UInt8
>(buffer
[2])) << 16) |
558 (static_cast<UInt32
>(static_cast<UInt8
>(buffer
[3])) << 24);
561 unsigned long color
= bits
>> shift
;
562 *ptr
++ = static_cast<UChar8
>(((color
& infoHeader
.redMask
) >> redShift
) * redScale
);
563 *ptr
++ = static_cast<UChar8
>(((color
& infoHeader
.greenMask
) >> greenShift
) * greenScale
);
564 *ptr
++ = static_cast<UChar8
>(((color
& infoHeader
.blueMask
) >> blueShift
) * blueScale
);
565 if (infoHeader
.alphaMask
!= 0)
566 *ptr
++ = static_cast<UChar8
>(((color
& infoHeader
.alphaMask
) >> alphaShift
) * alphaScale
);
567 shift
+= infoHeader
.biBitCount
;
569 data
+= bytesPerLine
;
575 bool parse24bitImage(std::istream
&is
, const OSGBITMAPINFOHEADER
&infoHeader
, Image
* image
)
580 if (infoHeader
.biHeight
>= 0)
582 height
= infoHeader
.biHeight
;
583 bytesPerLine
= infoHeader
.biWidth
* 3;
584 data
= image
->editData();
588 height
= -infoHeader
.biHeight
;
589 bytesPerLine
= infoHeader
.biWidth
* -3;
590 data
= image
->editData() + image
->getSize() + bytesPerLine
;
592 int padding
= (infoHeader
.biWidth
* 3) & 3;
594 padding
= 4 - padding
;
596 for (int y
= 0; y
< height
; ++y
)
599 for (unsigned int x
= 0; x
< infoHeader
.biWidth
; ++x
)
603 if (is
.gcount() != 3)
610 data
+= bytesPerLine
;
616 // -----------------------------------------
618 // -----------------------------------------
620 void u_short_int_write(unsigned short int u_short_int_val
,
624 bool _bmp_byte_swap
= true;
626 void long_int_write ( long int long_int_val
, std::ostream
&os
)
629 unsigned short int u_short_int_val_hi
;
630 unsigned short int u_short_int_val_lo
;
632 temp
= long_int_val
/ 65536;
636 u_short_int_val_hi
= static_cast<unsigned short>(temp
);
638 temp
= long_int_val
% 65536;
642 u_short_int_val_lo
= static_cast<unsigned short>(temp
);
646 u_short_int_write ( u_short_int_val_lo
, os
);
647 u_short_int_write ( u_short_int_val_hi
, os
);
651 u_short_int_write ( u_short_int_val_hi
, os
);
652 u_short_int_write ( u_short_int_val_lo
, os
);
657 void u_long_int_write(unsigned long int u_long_int_val
,
660 unsigned short int u_short_int_val_hi
;
661 unsigned short int u_short_int_val_lo
;
663 u_short_int_val_hi
= static_cast<unsigned short>( u_long_int_val
/ 65536 );
664 u_short_int_val_lo
= static_cast<unsigned short>( u_long_int_val
% 65536 );
668 u_short_int_write ( u_short_int_val_lo
, os
);
669 u_short_int_write ( u_short_int_val_hi
, os
);
673 u_short_int_write ( u_short_int_val_hi
, os
);
674 u_short_int_write ( u_short_int_val_lo
, os
);
680 void u_short_int_write(unsigned short int u_short_int_val
,
686 chi
= static_cast<unsigned char>( u_short_int_val
/ 256 );
687 clo
= static_cast<unsigned char>( u_short_int_val
% 256 );
697 void bmp_header1_write(std::ostream
&os
, unsigned short int filetype
,
698 unsigned long int filesize
, unsigned short int reserved1
,
699 unsigned short int reserved2
, unsigned long int bitmapoffset
)
701 u_short_int_write(filetype
, os
);
702 u_long_int_write(filesize
, os
);
703 u_short_int_write(reserved1
, os
);
704 u_short_int_write(reserved2
, os
);
705 u_long_int_write(bitmapoffset
, os
);
709 void bmp_header2_write(std::ostream
&os
, unsigned long int size
,
710 unsigned long int width
, long int height
,
711 unsigned short int planes
, unsigned short int bitsperpixel
,
712 unsigned long int compression
, unsigned long int sizeofbitmap
,
713 unsigned long int horzresolution
, unsigned long int vertresolution
,
714 unsigned long int colorsused
, unsigned long int colorsimportant
)
716 //****************************************************************************
718 // 4 bytes SIZE; Size of this header, in bytes.
719 // 4 bytes WIDTH; Image width, in pixels.
720 // 4 bytes HEIGHT; Image height, in pixels.
721 // (Pos/Neg, origin at bottom, top)
722 // 2 bytes PLANES; Number of color planes (always 1).
723 // 2 bytes BITSPERPIXEL; 1 to 24. 1, 4, 8, 16, 24 or 32.
724 // 4 bytes COMPRESSION; 0, uncompressed; 1, 8 bit RLE;
725 // 2, 4 bit RLE; 3, bitfields.
726 // 4 bytes SIZEOFBITMAP; Size of bitmap in bytes. (0 if uncompressed).
727 // 4 bytes HORZRESOLUTION; Pixels per meter. (Can be zero)
728 // 4 bytes VERTRESOLUTION; Pixels per meter. (Can be zero)
729 // 4 bytes COLORSUSED; Number of colors in palette. (Can be zero).
730 // 4 bytes COLORSIMPORTANT. Minimum number of important colors. (Can be zero).
734 // Input, ofstream &FILE_OUT, a reference to the output file.
736 // Input, unsigned long int SIZE, the size of this header in bytes.
738 // Input, unsigned long int WIDTH, the X dimensions of the image.
740 // Input, long int HEIGHT, the Y dimensions of the image.
742 // Input, unsigned short int PLANES, the number of color planes.
744 // Input, unsigned short int BITSPERPIXEL, color bits per pixel.
746 // Input, unsigned long int COMPRESSION, the compression option.
748 // Input, unsigned long int SIZEOFBITMAP, the size of the bitmap.
750 // Input, unsigned long int HORZRESOLUTION, the horizontal resolution.
752 // Input, unsigned long int VERTRESOLUTION, the vertical resolution.
754 // Input, unsigned long int COLORSUSED, the number of colors in the palette.
756 // Input, unsigned long int COLORSIMPORTANT, the minimum number of colors.
759 u_long_int_write(size
, os
);
760 u_long_int_write(width
, os
);
761 long_int_write(height
, os
);
762 u_short_int_write(planes
, os
);
763 u_short_int_write(bitsperpixel
, os
);
764 u_long_int_write(compression
, os
);
765 u_long_int_write(sizeofbitmap
, os
);
766 u_long_int_write(horzresolution
, os
);
767 u_long_int_write(vertresolution
, os
);
768 u_long_int_write(colorsused
, os
);
769 u_long_int_write(colorsimportant
, os
);
773 void bmp_24_data_write(std::ostream
&os
, unsigned long int width
,
774 long int height
, const unsigned char *data
)
779 padding
= ( 4 - ( ( 3 * width
) % 4 ) ) % 4;
781 for(long j
= 0; j
< abs ( height
); ++j
)
783 for(unsigned long i
= 0; i
< width
; ++i
)
791 for(int i
= 0; i
< padding
; ++i
)
801 // Static Class Variable implementations:
802 const Char8
*suffixArray
[] =
809 BMPImageFileType
BMPImageFileType:: _the("image/bmp",
812 (OSG_READ_SUPPORTED
|
813 OSG_WRITE_SUPPORTED
));
816 //-------------------------------------------------------------------------
817 /*! Tries to fill the image object with the data read from
818 the given fileName. Returns true on success.
821 bool BMPImageFileType::read( Image
*pImage
,
823 const std::string
&mimetype
)
825 // Parse bitmap file header
826 OSGBITMAPFILEHEADER fileHeader
;
827 if (readBitmapFileHeader(is
, fileHeader
) == false)
830 // Parse bitmap info header
831 OSGBITMAPINFOHEADER infoHeader
;
832 if (readBitmapInfoHeader(is
, infoHeader
) == false)
837 if (readColorMap(is
, fileHeader
, infoHeader
, colorMap
) == false)
840 // Parse the image data
841 UInt32 pixelFormat
= infoHeader
.alphaMask
!= 0 ? Image::OSG_RGBA_PF
: Image::OSG_RGB_PF
;
842 Int32 height
= infoHeader
.biHeight
>= 0 ? infoHeader
.biHeight
: -infoHeader
.biHeight
;
843 pImage
->set(pixelFormat
, infoHeader
.biWidth
, height
);
844 switch (infoHeader
.biBitCount
)
849 if (infoHeader
.biCompression
== 0 /*BI_RGB*/)
851 if (parseUncompressedPaletteImage(is
, infoHeader
, colorMap
, pImage
) == false)
856 if (parseRLEImage(is
, infoHeader
, colorMap
, pImage
) == false)
862 if (parseTrueColorImage(is
, infoHeader
, pImage
) == false)
866 if (parse24bitImage(is
, infoHeader
, pImage
) == false)
877 //-------------------------------------------------------------------------
878 /*! Tries to write the image object to the given output stream.
879 Returns true on success.
882 bool BMPImageFileType::write(const Image
*pImage
,
884 const std::string
&mimetype
)
889 int bpp
= pImage
->getBpp();
892 FWARNING(("Writing of bmp files is only supported for 24 bit RGB images!\n"));
899 int width
= pImage
->getWidth();
900 int height
= pImage
->getHeight();
901 const unsigned char *data
=
902 static_cast<const unsigned char *>(pImage
->getData());
904 unsigned long int bitmapoffset
;
905 unsigned short int bitsperpixel
;
906 unsigned long int colorsimportant
;
907 unsigned long int colorsused
;
908 unsigned long int compression
;
909 unsigned long int filesize
;
910 unsigned short int filetype
;
911 unsigned long int horzresolution
;
913 unsigned short int planes
;
914 unsigned short int reserved1
= 0;
915 unsigned short int reserved2
= 0;
916 unsigned long int size
= 40;
917 unsigned long int sizeofbitmap
;
918 unsigned long int vertresolution
;
922 filetype
= 'M' * 256 + 'B';
924 filetype
= 'B' * 256 + 'M';
926 // Determine the padding needed when WIDTH is not a multiple of 4.
927 padding
= ( 4 - ( ( 3 * width
) % 4 ) ) % 4;
929 filesize
= 54 + ( ( 3 * width
) + padding
) * abs ( height
);
932 bmp_header1_write(os
, filetype
, filesize
, reserved1
,
933 reserved2
, bitmapoffset
);
946 bmp_header2_write(os
, size
, width
, height
, planes
, bitsperpixel
,
947 compression
, sizeofbitmap
, horzresolution
, vertresolution
,
948 colorsused
, colorsimportant
);
951 bmp_24_data_write(os
, width
, height
, data
);
956 //-------------------------------------------------------------------------
958 Tries to determine the mime type of the data provided by an input stream
959 by searching for magic bytes. Returns the mime type or an empty string
960 when the function could not determine the mime type.
963 std::string
BMPImageFileType::determineMimetypeFromStream(std::istream
&is
)
967 is
.read(filecode
, 2);
968 is
.seekg(-2, std::ios::cur
);
970 return strncmp(filecode
, "BM", 2) == 0 ?
971 std::string(getMimeType()) : std::string();
974 //-------------------------------------------------------------------------
975 /*! Constructor used for the singleton object
978 BMPImageFileType::BMPImageFileType(const Char8
*mimeType
,
979 const Char8
*suffixArray
[],
980 UInt16 suffixByteCount
,
989 //-------------------------------------------------------------------------
993 BMPImageFileType::~BMPImageFileType(void)