]>
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 verbose
, int WXUNUSED(index
) )
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] );
101 wxLogError( _("BMP: Image width > 32767 pixels for file.") );
107 wxLogError( _("BMP: Image height > 32767 pixels for file.") );
111 stream
.Read( &aWord
, 2 );
114 int planes = (int)wxUINT16_SWAP_ON_BE( aWord );
116 stream
.Read( &aWord
, 2 );
117 int bpp
= (int)wxUINT16_SWAP_ON_BE( aWord
);
118 if (bpp
!= 1 && bpp
!= 4 && bpp
!= 8 && bpp
!= 16 && bpp
!= 24 && bpp
!= 32)
121 wxLogError( _("BMP: Unknown bitdepth in file.") );
125 stream
.Read( dbuf
, 4 * 4 );
126 int comp
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
127 if (comp
!= BI_RGB
&& comp
!= BI_RLE4
&& comp
!= BI_RLE8
&& comp
!= BI_BITFIELDS
)
130 wxLogError( _("BMP: Unknown encoding in file.") );
134 stream
.Read( dbuf
, 4 * 2 );
135 int ncolors
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
138 /* some more sanity checks */
139 if (((comp
== BI_RLE4
) && (bpp
!= 4)) ||
140 ((comp
== BI_RLE8
) && (bpp
!= 8)) ||
141 ((comp
== BI_BITFIELDS
) && (bpp
!= 16 && bpp
!= 32)))
144 wxLogError( _("BMP: Encoding doesn't match bitdepth.") );
149 cmap
= (struct _cmap
*)malloc(sizeof(struct _cmap
) * ncolors
);
153 wxLogError( _("BMP: Couldn't allocate memory.") );
160 image
->Create( width
, height
);
161 unsigned char *ptr
= image
->GetData();
165 wxLogError( _("BMP: Couldn't allocate memory.") );
172 * Reading the palette, if it exists.
174 if (bpp
< 16 && ncolors
!= 0)
176 for (int j
= 0; j
< ncolors
; j
++)
178 stream
.Read( bbuf
, 4 );
184 else if (bpp
== 16 || bpp
== 32)
186 if (comp
== BI_BITFIELDS
)
189 stream
.Read( dbuf
, 4 * 3 );
190 bmask
= wxINT32_SWAP_ON_BE( dbuf
[0] );
191 gmask
= wxINT32_SWAP_ON_BE( dbuf
[1] );
192 rmask
= wxINT32_SWAP_ON_BE( dbuf
[2] );
193 /* find shift amount.. ugly, but i can't think of a better way */
194 for (bit
= 0; bit
< bpp
; bit
++)
196 if (bmask
& (1 << bit
))
198 if (gmask
& (1 << bit
))
200 if (rmask
& (1 << bit
))
225 * Reading the image data
227 stream
.SeekI( start_offset
+ offset
);
228 unsigned char *data
= ptr
;
230 /* set the whole image to the background color */
231 if (bpp
< 16 && (comp
== BI_RLE4
|| comp
== BI_RLE8
))
233 for (int i
= 0; i
< width
* height
; i
++)
244 int linesize
= ((width
* bpp
+ 31) / 32) * 4;
246 /* BMPs are stored upside down */
247 for (line
= (height
- 1); line
>= 0; line
--)
250 for (column
= 0; column
< width
;)
256 aByte
= stream
.GetC();
260 for (bit
= 0; bit
< 8; bit
++)
262 index
= ((aByte
& (0x80 >> bit
)) ? 1 : 0);
263 ptr
[poffset
] = cmap
[index
].r
;
264 ptr
[poffset
+ 1] = cmap
[index
].g
;
265 ptr
[poffset
+ 2] = cmap
[index
].b
;
274 wxLogError( _("BMP: Cannot deal with 4bit encoded yet.") );
282 for (nibble
= 0; nibble
< 2; nibble
++)
284 index
= ((aByte
& (0xF0 >> nibble
* 4)) >> (!nibble
* 4));
287 ptr
[poffset
] = cmap
[index
].r
;
288 ptr
[poffset
+ 1] = cmap
[index
].g
;
289 ptr
[poffset
+ 2] = cmap
[index
].b
;
300 aByte
= stream
.GetC();
305 /* column = width; */
314 aByte
= stream
.GetC();
316 linepos
= column
* bpp
/ 8;
317 aByte
= stream
.GetC();
322 int absolute
= aByte
;
323 for (int k
= 0; k
< absolute
; k
++)
326 aByte
= stream
.GetC();
327 ptr
[poffset
] = cmap
[aByte
].r
;
328 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
329 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
333 aByte
= stream
.GetC();
338 for (int l
= 0; l
< first
; l
++)
340 ptr
[poffset
] = cmap
[aByte
].r
;
341 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
342 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
350 ptr
[poffset
] = cmap
[aByte
].r
;
351 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
352 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
354 // linepos += size; seems to be wrong, RR
360 stream
.Read( &bbuf
, 3 );
362 ptr
[poffset
] = (unsigned char)bbuf
[2];
363 ptr
[poffset
+ 1] = (unsigned char)bbuf
[1];
364 ptr
[poffset
+ 2] = (unsigned char)bbuf
[0];
370 stream
.Read( &aWord
, 2 );
371 aWord
= wxUINT16_SWAP_ON_BE( aWord
);
373 temp
= (aWord
& rmask
) >> rshift
;
375 temp
= (aWord
& gmask
) >> gshift
;
376 ptr
[poffset
+ 1] = temp
;
377 temp
= (aWord
& bmask
) >> bshift
;
378 ptr
[poffset
+ 2] = temp
;
384 stream
.Read( &aDword
, 4 );
385 aDword
= wxINT32_SWAP_ON_BE( aDword
);
387 temp
= (aDword
& rmask
) >> rshift
;
389 temp
= (aDword
& gmask
) >> gshift
;
390 ptr
[poffset
+ 1] = temp
;
391 temp
= (aDword
& bmask
) >> bshift
;
392 ptr
[poffset
+ 2] = temp
;
396 while ((linepos
< linesize
) && (comp
!= 1) && (comp
!= 2))
398 stream
.Read( &aByte
, 1 );
400 if (stream
.LastError() != wxStream_NOERROR
)
407 image
->SetMask( FALSE
);
412 bool wxBMPHandler::DoCanRead( wxInputStream
& stream
)
414 unsigned char hdr
[2];
416 stream
.Read(&hdr
, 2);
417 stream
.SeekI(-2, wxFromCurrent
);
418 return (hdr
[0] == 'B' && hdr
[1] == 'M');
421 #endif // wxUSE_STREAMS