]>
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 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler
,wxImageHandler
)
60 #define BI_BITFIELDS 3
63 #define poffset (line * width * 3 + column * 3)
65 bool wxBMPHandler::LoadFile( wxImage
*image
, wxInputStream
& stream
, bool verbose
, int WXUNUSED(index
) )
67 int rshift
= 0, gshift
= 0, bshift
= 0;
70 wxInt32 dbuf
[4], aDword
,
71 rmask
= 0, gmask
= 0, bmask
= 0;
74 unsigned char r
, g
, b
;
77 off_t start_offset
= stream
.TellI();
85 stream
.Read( &bbuf
, 2 );
86 stream
.Read( dbuf
, 4 * 4 );
89 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] );
99 wxLogError( _("BMP: Image width > 32767 pixels for file.") );
105 wxLogError( _("BMP: 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)
119 wxLogError( _("BMP: Unknown bitdepth in file.") );
123 stream
.Read( dbuf
, 4 * 4 );
124 int comp
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
125 if (comp
!= BI_RGB
&& comp
!= BI_RLE4
&& comp
!= BI_RLE8
&& comp
!= BI_BITFIELDS
)
128 wxLogError( _("BMP: Unknown encoding in file.") );
132 stream
.Read( dbuf
, 4 * 2 );
133 int ncolors
= (int)wxINT32_SWAP_ON_BE( dbuf
[0] );
136 /* some more sanity checks */
137 if (((comp
== BI_RLE4
) && (bpp
!= 4)) ||
138 ((comp
== BI_RLE8
) && (bpp
!= 8)) ||
139 ((comp
== BI_BITFIELDS
) && (bpp
!= 16 && bpp
!= 32)))
142 wxLogError( _("BMP: Encoding doesn't match bitdepth.") );
147 cmap
= (struct _cmap
*)malloc(sizeof(struct _cmap
) * ncolors
);
151 wxLogError( _("BMP: Couldn't allocate memory.") );
158 image
->Create( width
, height
);
159 unsigned char *ptr
= image
->GetData();
163 wxLogError( _("BMP: Couldn't allocate memory.") );
170 * Reading the palette, if it exists.
172 if (bpp
< 16 && ncolors
!= 0)
174 for (int j
= 0; j
< ncolors
; j
++)
176 stream
.Read( bbuf
, 4 );
182 else if (bpp
== 16 || bpp
== 32)
184 if (comp
== BI_BITFIELDS
)
187 stream
.Read( dbuf
, 4 * 3 );
188 bmask
= wxINT32_SWAP_ON_BE( dbuf
[0] );
189 gmask
= wxINT32_SWAP_ON_BE( dbuf
[1] );
190 rmask
= wxINT32_SWAP_ON_BE( dbuf
[2] );
191 /* find shift amount.. ugly, but i can't think of a better way */
192 for (bit
= 0; bit
< bpp
; bit
++)
194 if (bmask
& (1 << bit
))
196 if (gmask
& (1 << bit
))
198 if (rmask
& (1 << bit
))
223 * Reading the image data
225 stream
.SeekI( start_offset
+ offset
);
226 unsigned char *data
= ptr
;
228 /* set the whole image to the background color */
229 if (bpp
< 16 && (comp
== BI_RLE4
|| comp
== BI_RLE8
))
231 for (int i
= 0; i
< width
* height
; i
++)
242 int linesize
= ((width
* bpp
+ 31) / 32) * 4;
244 /* BMPs are stored upside down */
245 for (line
= (height
- 1); line
>= 0; line
--)
248 for (column
= 0; column
< width
;)
254 aByte
= stream
.GetC();
258 for (bit
= 0; bit
< 8; bit
++)
260 index
= ((aByte
& (0x80 >> bit
)) ? 1 : 0);
261 ptr
[poffset
] = cmap
[index
].r
;
262 ptr
[poffset
+ 1] = cmap
[index
].g
;
263 ptr
[poffset
+ 2] = cmap
[index
].b
;
272 wxLogError( _("BMP: Cannot deal with 4bit encoded yet.") );
280 for (nibble
= 0; nibble
< 2; nibble
++)
282 index
= ((aByte
& (0xF0 >> nibble
* 4)) >> (!nibble
* 4));
285 ptr
[poffset
] = cmap
[index
].r
;
286 ptr
[poffset
+ 1] = cmap
[index
].g
;
287 ptr
[poffset
+ 2] = cmap
[index
].b
;
298 aByte
= stream
.GetC();
303 /* column = width; */
312 aByte
= stream
.GetC();
314 linepos
= column
* bpp
/ 8;
315 aByte
= stream
.GetC();
320 int absolute
= aByte
;
321 for (int k
= 0; k
< absolute
; k
++)
324 aByte
= stream
.GetC();
325 ptr
[poffset
] = cmap
[aByte
].r
;
326 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
327 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
331 aByte
= stream
.GetC();
336 for (int l
= 0; l
< first
; l
++)
338 ptr
[poffset
] = cmap
[aByte
].r
;
339 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
340 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
348 ptr
[poffset
] = cmap
[aByte
].r
;
349 ptr
[poffset
+ 1] = cmap
[aByte
].g
;
350 ptr
[poffset
+ 2] = cmap
[aByte
].b
;
352 // linepos += size; seems to be wrong, RR
358 stream
.Read( &bbuf
, 3 );
360 ptr
[poffset
] = (unsigned char)bbuf
[2];
361 ptr
[poffset
+ 1] = (unsigned char)bbuf
[1];
362 ptr
[poffset
+ 2] = (unsigned char)bbuf
[0];
368 stream
.Read( &aWord
, 2 );
369 aWord
= wxUINT16_SWAP_ON_BE( aWord
);
371 temp
= (aWord
& rmask
) >> rshift
;
373 temp
= (aWord
& gmask
) >> gshift
;
374 ptr
[poffset
+ 1] = temp
;
375 temp
= (aWord
& bmask
) >> bshift
;
376 ptr
[poffset
+ 2] = temp
;
382 stream
.Read( &aDword
, 4 );
383 aDword
= wxINT32_SWAP_ON_BE( aDword
);
385 temp
= (aDword
& rmask
) >> rshift
;
387 temp
= (aDword
& gmask
) >> gshift
;
388 ptr
[poffset
+ 1] = temp
;
389 temp
= (aDword
& bmask
) >> bshift
;
390 ptr
[poffset
+ 2] = temp
;
394 while ((linepos
< linesize
) && (comp
!= 1) && (comp
!= 2))
396 stream
.Read( &aByte
, 1 );
398 if (stream
.LastError() != wxStream_NOERROR
)
405 image
->SetMask( FALSE
);
410 bool wxBMPHandler::DoCanRead( wxInputStream
& stream
)
412 unsigned char hdr
[2];
414 stream
.Read(&hdr
, 2);
415 stream
.SeekI(-2, wxFromCurrent
);
416 return (hdr
[0] == 'B' && hdr
[1] == 'M');
419 #endif // wxUSE_STREAMS