]>
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
, bool WXUNUSED(verbose
) )
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 );
91 wxInt32 size
= wxINT32_SWAP_ON_BE( dbuf
[0] );
93 wxInt32 offset
= wxINT32_SWAP_ON_BE( dbuf
[2] );
95 stream
.Read(dbuf
, 4 * 2);
96 int width
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
97 int height
= (int)wxINT32_SWAP_ON_BE( dbuf
[1] );
100 wxLogError( wxT("Image width > 32767 pixels for file.") );
105 wxLogError( wxT("Image height > 32767 pixels for file.") );
109 stream
.Read( &aWord
, 2 );
112 int planes = (int)wxUINT16_SWAP_ON_BE( aWord );
114 stream
.Read( &aWord
, 2 );
115 int bpp
= (int)wxUINT16_SWAP_ON_BE( aWord
);
116 if (bpp
!= 1 && bpp
!= 4 && bpp
!= 8 && bpp
!= 16 && bpp
!= 24 && bpp
!= 32)
118 wxLogError( wxT("unknown bitdepth in file.") );
122 stream
.Read( dbuf
, 4 * 4 );
123 int comp
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
124 if (comp
!= BI_RGB
&& comp
!= BI_RLE4
&& comp
!= BI_RLE8
&& comp
!= BI_BITFIELDS
)
126 wxLogError( wxT("unknown encoding in Windows BMP file.") );
130 stream
.Read( dbuf
, 4 * 2 );
131 int ncolors
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
134 /* some more sanity checks */
135 if (((comp
== BI_RLE4
) && (bpp
!= 4)) ||
136 ((comp
== BI_RLE8
) && (bpp
!= 8)) ||
137 ((comp
== BI_BITFIELDS
) && (bpp
!= 16 && bpp
!= 32)))
139 wxLogError( wxT("encoding of BMP doesn't match bitdepth.") );
144 cmap
= (struct _cmap
*)malloc(sizeof(struct _cmap
) * ncolors
);
147 wxLogError( wxT("Cannot allocate RAM for color map in BMP file.") );
154 image
->Create( width
, height
);
155 unsigned char *ptr
= image
->GetData();
158 wxLogError( wxT("Cannot allocate RAM for RGB data in file.") );
165 * Reading the palette, if it exists.
167 if (bpp
< 16 && ncolors
!= 0)
169 for (int j
= 0; j
< ncolors
; j
++)
171 stream
.Read( bbuf
, 4 );
177 else if (bpp
== 16 || bpp
== 32)
179 if (comp
== BI_BITFIELDS
)
182 stream
.Read( dbuf
, 4 * 3 );
183 bmask
= wxINT32_SWAP_ON_BE( dbuf
[0] );
184 gmask
= wxINT32_SWAP_ON_BE( dbuf
[1] );
185 rmask
= wxINT32_SWAP_ON_BE( dbuf
[2] );
186 /* find shift amount.. ugly, but i can't think of a better way */
187 for (bit
= 0; bit
< bpp
; bit
++)
189 if (bmask
& (1 << bit
))
191 if (gmask
& (1 << bit
))
193 if (rmask
& (1 << bit
))
218 * Reading the image data
220 stream
.SeekI( start_offset
+ offset
);
221 unsigned char *data
= ptr
;
223 /* set the whole image to the background color */
224 if (bpp
< 16 && (comp
== BI_RLE4
|| comp
== BI_RLE8
))
226 for (int i
= 0; i
< width
* height
; i
++)
237 int linesize
= ((width
* bpp
+ 31) / 32) * 4;
239 /* BMPs are stored upside down */
240 for (line
= (height
- 1); line
>= 0; line
--)
243 for (column
= 0; column
< width
;)
249 aByte
= stream
.GetC();
253 for (bit
= 0; bit
< 8; bit
++)
255 index
= ((aByte
& (0x80 >> bit
)) ? 1 : 0);
256 ptr
[poffset
] = cmap
[index
].r
;
257 ptr
[poffset
+ 1] = cmap
[index
].g
;
258 ptr
[poffset
+ 2] = cmap
[index
].b
;
266 wxLogError( wxT("Can't deal with 4bit encoded yet.") );
274 for (nibble
= 0; nibble
< 2; nibble
++)
276 index
= ((aByte
& (0xF0 >> nibble
* 4)) >> (!nibble
* 4));
279 ptr
[poffset
] = cmap
[index
].r
;
280 ptr
[poffset
+ 1] = cmap
[index
].g
;
281 ptr
[poffset
+ 2] = cmap
[index
].b
;
292 aByte
= stream
.GetC();
297 /* column = width; */
306 aByte
= stream
.GetC();
308 linepos
= column
* bpp
/ 8;
309 aByte
= stream
.GetC();
314 int absolute
= aByte
;
315 for (int k
= 0; k
< absolute
; k
++)
318 aByte
= stream
.GetC();
319 ptr
[poffset
] = cmap
[aByte
].r
;
320 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
321 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
325 aByte
= stream
.GetC();
330 for (int l
= 0; l
< first
; l
++)
332 ptr
[poffset
] = cmap
[aByte
].r
;
333 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
334 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
342 ptr
[poffset
] = cmap
[aByte
].r
;
343 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
344 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
346 // linepos += size; seems to be wrong, RR
352 stream
.Read( &bbuf
, 3 );
354 ptr
[poffset
] = (unsigned char)bbuf
[2];
355 ptr
[poffset
+ 1] = (unsigned char)bbuf
[1];
356 ptr
[poffset
+ 2] = (unsigned char)bbuf
[0];
362 stream
.Read( &aWord
, 2 );
363 aWord
= wxUINT16_SWAP_ON_BE( aWord
);
365 temp
= (aWord
& rmask
) >> rshift
;
367 temp
= (aWord
& gmask
) >> gshift
;
368 ptr
[poffset
+ 1] = temp
;
369 temp
= (aWord
& bmask
) >> bshift
;
370 ptr
[poffset
+ 2] = temp
;
376 stream
.Read( &aDword
, 4 );
377 aDword
= wxINT32_SWAP_ON_BE( aDword
);
379 temp
= (aDword
& rmask
) >> rshift
;
381 temp
= (aDword
& gmask
) >> gshift
;
382 ptr
[poffset
+ 1] = temp
;
383 temp
= (aDword
& bmask
) >> bshift
;
384 ptr
[poffset
+ 2] = temp
;
388 while ((linepos
< linesize
) && (comp
!= 1) && (comp
!= 2))
390 stream
.Read( &aByte
, 1 );
392 if (stream
.LastError() != wxStream_NOERROR
)
399 image
->SetMask( FALSE
);
404 bool wxBMPHandler::CanRead( wxInputStream
& stream
)
406 unsigned char hdr
[2];
408 stream
.Read(&hdr
, 2);
409 stream
.SeekI(-2, wxFromCurrent
);
410 return (hdr
[0] == 'B' && hdr
[1] == 'M');
413 #endif // wxUSE_STREAMS