]>
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 #pragma implementation "imagbmp.h"
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
21 #include "wx/imagbmp.h"
22 #include "wx/bitmap.h"
26 #include "wx/filefn.h"
27 #include "wx/wfstream.h"
29 #include "wx/module.h"
44 //-----------------------------------------------------------------------------
46 //-----------------------------------------------------------------------------
48 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler
,wxImageHandler
)
59 #define BI_BITFIELDS 3
62 #define poffset (line * width * 3 + column * 3)
64 bool wxBMPHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
, bool verbose
, int WXUNUSED(index
) )
66 int rshift
= 0, gshift
= 0, bshift
= 0;
69 wxInt32 dbuf
[4], aDword
,
70 rmask
= 0, gmask
= 0, bmask
= 0;
73 unsigned char r
, g
, b
;
76 off_t start_offset
= stream
.TellI();
84 stream
.Read( &bbuf
, 2 );
85 stream
.Read( dbuf
, 4 * 4 );
88 wxInt32 size
= wxINT32_SWAP_ON_BE( dbuf
[0] );
90 wxInt32 offset
= wxINT32_SWAP_ON_BE( dbuf
[2] );
92 stream
.Read(dbuf
, 4 * 2);
93 int width
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
94 int height
= (int)wxINT32_SWAP_ON_BE( dbuf
[1] );
98 wxLogError( _("BMP: Image width > 32767 pixels for file.") );
104 wxLogError( _("BMP: Image height > 32767 pixels for file.") );
108 stream
.Read( &aWord
, 2 );
111 int planes = (int)wxUINT16_SWAP_ON_BE( aWord );
113 stream
.Read( &aWord
, 2 );
114 int bpp
= (int)wxUINT16_SWAP_ON_BE( aWord
);
115 if (bpp
!= 1 && bpp
!= 4 && bpp
!= 8 && bpp
!= 16 && bpp
!= 24 && bpp
!= 32)
118 wxLogError( _("BMP: 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
)
127 wxLogError( _("BMP: Unknown encoding in file.") );
131 stream
.Read( dbuf
, 4 * 2 );
132 int ncolors
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
135 /* some more sanity checks */
136 if (((comp
== BI_RLE4
) && (bpp
!= 4)) ||
137 ((comp
== BI_RLE8
) && (bpp
!= 8)) ||
138 ((comp
== BI_BITFIELDS
) && (bpp
!= 16 && bpp
!= 32)))
141 wxLogError( _("BMP: Encoding doesn't match bitdepth.") );
146 cmap
= (struct _cmap
*)malloc(sizeof(struct _cmap
) * ncolors
);
150 wxLogError( _("BMP: Couldn't allocate memory.") );
157 image
->Create( width
, height
);
158 unsigned char *ptr
= image
->GetData();
162 wxLogError( _("BMP: Couldn't allocate memory.") );
169 * Reading the palette, if it exists.
171 if (bpp
< 16 && ncolors
!= 0)
173 for (int j
= 0; j
< ncolors
; j
++)
175 stream
.Read( bbuf
, 4 );
181 else if (bpp
== 16 || bpp
== 32)
183 if (comp
== BI_BITFIELDS
)
186 stream
.Read( dbuf
, 4 * 3 );
187 bmask
= wxINT32_SWAP_ON_BE( dbuf
[0] );
188 gmask
= wxINT32_SWAP_ON_BE( dbuf
[1] );
189 rmask
= wxINT32_SWAP_ON_BE( dbuf
[2] );
190 /* find shift amount.. ugly, but i can't think of a better way */
191 for (bit
= 0; bit
< bpp
; bit
++)
193 if (bmask
& (1 << bit
))
195 if (gmask
& (1 << bit
))
197 if (rmask
& (1 << bit
))
222 * Reading the image data
224 stream
.SeekI( start_offset
+ offset
);
225 unsigned char *data
= ptr
;
227 /* set the whole image to the background color */
228 if (bpp
< 16 && (comp
== BI_RLE4
|| comp
== BI_RLE8
))
230 for (int i
= 0; i
< width
* height
; i
++)
241 int linesize
= ((width
* bpp
+ 31) / 32) * 4;
243 /* BMPs are stored upside down */
244 for (line
= (height
- 1); line
>= 0; line
--)
247 for (column
= 0; column
< width
;)
253 aByte
= stream
.GetC();
257 for (bit
= 0; bit
< 8; bit
++)
259 index
= ((aByte
& (0x80 >> bit
)) ? 1 : 0);
260 ptr
[poffset
] = cmap
[index
].r
;
261 ptr
[poffset
+ 1] = cmap
[index
].g
;
262 ptr
[poffset
+ 2] = cmap
[index
].b
;
271 wxLogError( _("BMP: Cannot deal with 4bit encoded yet.") );
279 for (nibble
= 0; nibble
< 2; nibble
++)
281 index
= ((aByte
& (0xF0 >> nibble
* 4)) >> (!nibble
* 4));
284 ptr
[poffset
] = cmap
[index
].r
;
285 ptr
[poffset
+ 1] = cmap
[index
].g
;
286 ptr
[poffset
+ 2] = cmap
[index
].b
;
297 aByte
= stream
.GetC();
302 /* column = width; */
311 aByte
= stream
.GetC();
313 linepos
= column
* bpp
/ 8;
314 aByte
= stream
.GetC();
319 int absolute
= aByte
;
320 for (int k
= 0; k
< absolute
; k
++)
323 aByte
= stream
.GetC();
324 ptr
[poffset
] = cmap
[aByte
].r
;
325 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
326 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
330 aByte
= stream
.GetC();
335 for (int l
= 0; l
< first
; l
++)
337 ptr
[poffset
] = cmap
[aByte
].r
;
338 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
339 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
347 ptr
[poffset
] = cmap
[aByte
].r
;
348 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
349 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
351 // linepos += size; seems to be wrong, RR
357 stream
.Read( &bbuf
, 3 );
359 ptr
[poffset
] = (unsigned char)bbuf
[2];
360 ptr
[poffset
+ 1] = (unsigned char)bbuf
[1];
361 ptr
[poffset
+ 2] = (unsigned char)bbuf
[0];
367 stream
.Read( &aWord
, 2 );
368 aWord
= wxUINT16_SWAP_ON_BE( aWord
);
370 temp
= (aWord
& rmask
) >> rshift
;
372 temp
= (aWord
& gmask
) >> gshift
;
373 ptr
[poffset
+ 1] = temp
;
374 temp
= (aWord
& bmask
) >> bshift
;
375 ptr
[poffset
+ 2] = temp
;
381 stream
.Read( &aDword
, 4 );
382 aDword
= wxINT32_SWAP_ON_BE( aDword
);
384 temp
= (aDword
& rmask
) >> rshift
;
386 temp
= (aDword
& gmask
) >> gshift
;
387 ptr
[poffset
+ 1] = temp
;
388 temp
= (aDword
& bmask
) >> bshift
;
389 ptr
[poffset
+ 2] = temp
;
393 while ((linepos
< linesize
) && (comp
!= 1) && (comp
!= 2))
395 stream
.Read( &aByte
, 1 );
397 if (stream
.LastError() != wxStream_NOERROR
)
404 image
->SetMask( FALSE
);
409 bool wxBMPHandler::DoCanRead( wxInputStream
& stream
)
411 unsigned char hdr
[2];
413 stream
.Read(&hdr
, 2);
414 stream
.SeekI(-2, wxFromCurrent
);
415 return (hdr
[0] == 'B' && hdr
[1] == 'M');
418 #endif // wxUSE_STREAMS