]>
git.saurik.com Git - wxWidgets.git/blob - src/common/imagbmp.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxImage BMP handler
4 // Author: Robert Roebling
6 // Copyright: (c) Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 We don't put pragma implement in this file because it is already present in
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
23 #include "wx/bitmap.h"
27 #include "wx/filefn.h"
28 #include "wx/wfstream.h"
30 #include "wx/module.h"
45 //-----------------------------------------------------------------------------
47 //-----------------------------------------------------------------------------
49 #if !USE_SHARED_LIBRARIES
50 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler
,wxImageHandler
)
62 #define BI_BITFIELDS 3
65 #define poffset (line * width * 3 + column * 3)
67 bool wxBMPHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
)
69 int rshift
= 0, gshift
= 0, bshift
= 0;
72 wxInt32 dbuf
[4], aDword
,
73 rmask
= 0, gmask
= 0, bmask
= 0;
76 unsigned char r
, g
, b
;
79 off_t start_offset
= stream
.TellI();
87 stream
.Read( &bbuf
, 2 );
88 stream
.Read( dbuf
, 4 * 4 );
90 wxInt32 size
= wxINT32_SWAP_ON_BE( dbuf
[0] );
91 wxInt32 offset
= wxINT32_SWAP_ON_BE( dbuf
[2] );
93 stream
.Read(dbuf
, 4 * 2);
94 int width
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
95 int height
= (int)wxINT32_SWAP_ON_BE( dbuf
[1] );
98 wxLogError( _T("Image width > 32767 pixels for file.") );
103 wxLogError( _T("Image height > 32767 pixels for file.") );
107 stream
.Read( &aWord
, 2 );
110 int planes = (int)wxUINT16_SWAP_ON_BE( aWord );
112 stream
.Read( &aWord
, 2 );
113 int bpp
= (int)wxUINT16_SWAP_ON_BE( aWord
);
114 if (bpp
!= 1 && bpp
!= 4 && bpp
!= 8 && bpp
!= 16 && bpp
!= 24 && bpp
!= 32)
116 wxLogError( _T("unknown bitdepth in file.") );
120 stream
.Read( dbuf
, 4 * 4 );
121 int comp
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
122 if (comp
!= BI_RGB
&& comp
!= BI_RLE4
&& comp
!= BI_RLE8
&& comp
!= BI_BITFIELDS
)
124 wxLogError( _T("unknown encoding in Windows BMP file.") );
128 stream
.Read( dbuf
, 4 * 2 );
129 int ncolors
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
132 /* some more sanity checks */
133 if (((comp
== BI_RLE4
) && (bpp
!= 4)) ||
134 ((comp
== BI_RLE8
) && (bpp
!= 8)) ||
135 ((comp
== BI_BITFIELDS
) && (bpp
!= 16 && bpp
!= 32)))
137 wxLogError( _T("encoding of BMP doesn't match bitdepth.") );
142 cmap
= (struct _cmap
*)malloc(sizeof(struct _cmap
) * ncolors
);
145 wxLogError( _T("Cannot allocate RAM for color map in BMP file.") );
152 image
->Create( width
, height
);
153 unsigned char *ptr
= image
->GetData();
156 wxLogError( _T("Cannot allocate RAM for RGB data in file.") );
163 * Reading the palette, if it exists.
165 if (bpp
< 16 && ncolors
!= 0)
167 for (int j
= 0; j
< ncolors
; j
++)
169 stream
.Read( bbuf
, 4 );
175 else if (bpp
== 16 || bpp
== 32)
177 if (comp
== BI_BITFIELDS
)
180 stream
.Read( dbuf
, 4 * 3 );
181 bmask
= wxINT32_SWAP_ON_BE( dbuf
[0] );
182 gmask
= wxINT32_SWAP_ON_BE( dbuf
[1] );
183 rmask
= wxINT32_SWAP_ON_BE( dbuf
[2] );
184 /* find shift amount.. ugly, but i can't think of a better way */
185 for (bit
= 0; bit
< bpp
; bit
++)
187 if (bmask
& (1 << bit
))
189 if (gmask
& (1 << bit
))
191 if (rmask
& (1 << bit
))
216 * Reading the image data
218 stream
.SeekI( start_offset
+ offset
);
219 unsigned char *data
= ptr
;
221 /* set the whole image to the background color */
222 if (bpp
< 16 && (comp
== BI_RLE4
|| comp
== BI_RLE8
))
224 for (int i
= 0; i
< width
* height
; i
++)
235 int linesize
= ((width
* bpp
+ 31) / 32) * 4;
237 /* BMPs are stored upside down */
238 for (line
= (height
- 1); line
>= 0; line
--)
241 for (column
= 0; column
< width
;)
247 aByte
= stream
.GetC();
251 for (bit
= 0; bit
< 8; bit
++)
253 index
= ((aByte
& (0x80 >> bit
)) ? 1 : 0);
254 ptr
[poffset
] = cmap
[index
].r
;
255 ptr
[poffset
+ 1] = cmap
[index
].g
;
256 ptr
[poffset
+ 2] = cmap
[index
].b
;
264 wxLogError( _T("Can't deal with 4bit encoded yet.") );
272 for (nibble
= 0; nibble
< 2; nibble
++)
274 index
= ((aByte
& (0xF0 >> nibble
* 4)) >> (!nibble
* 4));
277 ptr
[poffset
] = cmap
[index
].r
;
278 ptr
[poffset
+ 1] = cmap
[index
].g
;
279 ptr
[poffset
+ 2] = cmap
[index
].b
;
290 aByte
= stream
.GetC();
295 /* column = width; */
304 aByte
= stream
.GetC();
306 linepos
= column
* bpp
/ 8;
307 aByte
= stream
.GetC();
312 int absolute
= aByte
;
313 for (int k
= 0; k
< absolute
; k
++)
316 aByte
= stream
.GetC();
317 ptr
[poffset
] = cmap
[aByte
].r
;
318 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
319 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
323 aByte
= stream
.GetC();
328 for (int l
= 0; l
< first
; l
++)
330 ptr
[poffset
] = cmap
[aByte
].r
;
331 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
332 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
340 ptr
[poffset
] = cmap
[aByte
].r
;
341 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
342 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
344 // linepos += size; seems to be wrong, RR
350 stream
.Read( &bbuf
, 3 );
352 ptr
[poffset
] = (unsigned char)bbuf
[2];
353 ptr
[poffset
+ 1] = (unsigned char)bbuf
[1];
354 ptr
[poffset
+ 2] = (unsigned char)bbuf
[0];
360 stream
.Read( &aWord
, 2 );
361 aWord
= wxUINT16_SWAP_ON_BE( aWord
);
363 temp
= (aWord
& rmask
) >> rshift
;
365 temp
= (aWord
& gmask
) >> gshift
;
366 ptr
[poffset
+ 1] = temp
;
367 temp
= (aWord
& bmask
) >> gshift
;
368 ptr
[poffset
+ 2] = temp
;
374 stream
.Read( &aDword
, 4 );
375 aDword
= wxINT32_SWAP_ON_BE( aDword
);
377 temp
= (aDword
& rmask
) >> rshift
;
379 temp
= (aDword
& gmask
) >> gshift
;
380 ptr
[poffset
+ 1] = temp
;
381 temp
= (aDword
& bmask
) >> bshift
;
382 ptr
[poffset
+ 2] = temp
;
386 while ((linepos
< linesize
) && (comp
!= 1) && (comp
!= 2))
388 stream
.Read( &aByte
, 1 );
390 if (stream
.LastError() != wxStream_NOERROR
)
397 image
->SetMask( FALSE
);
402 #endif // wxUSE_STREAMS