]> git.saurik.com Git - wxWidgets.git/blob - src/common/imagbmp.cpp
added stat.h include
[wxWidgets.git] / src / common / imagbmp.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: imagbmp.cpp
3 // Purpose: wxImage BMP handler
4 // Author: Robert Roebling
5 // RCS-ID: $Id$
6 // Copyright: (c) Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "imagbmp.h"
12 #endif
13
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16
17 #ifdef __BORLANDC__
18 #pragma hdrstop
19 #endif
20
21 #include "wx/defs.h"
22
23 #if wxUSE_IMAGE
24
25 #include "wx/imagbmp.h"
26 #include "wx/bitmap.h"
27 #include "wx/debug.h"
28 #include "wx/log.h"
29 #include "wx/app.h"
30 #include "wx/filefn.h"
31 #include "wx/wfstream.h"
32 #include "wx/intl.h"
33 #include "wx/module.h"
34 #include "wx/quantize.h"
35
36 // For memcpy
37 #include <string.h>
38
39 #ifdef __SALFORDC__
40 #ifdef FAR
41 #undef FAR
42 #endif
43 #endif
44
45 #ifdef __WXMSW__
46 #include <windows.h>
47 #endif
48
49 //-----------------------------------------------------------------------------
50 // wxBMPHandler
51 //-----------------------------------------------------------------------------
52
53 IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler)
54
55
56 #if wxUSE_STREAMS
57
58
59 bool wxBMPHandler::SaveFile(wxImage *image,
60 wxOutputStream& stream,
61 bool verbose)
62 {
63 wxCHECK_MSG( image, FALSE, _T("invalid pointer in wxBMPHandler::SaveFile") );
64
65 if (!image->Ok())
66 {
67 if (verbose) wxLogError(_("BMP: Couldn't save invalid image."));
68 return FALSE;
69 }
70
71 // get the format of the BMP file to save, else use 24bpp
72 unsigned format = wxBMP_24BPP;
73 if (image->HasOption(wxBMP_FORMAT))
74 format = image->GetOptionInt(wxBMP_FORMAT);
75
76 unsigned bpp; // # of bits per pixel
77 int palette_size; // # of color map entries, ie. 2^bpp colors
78
79 // set the bpp and appropriate palette_size, and do additional checks
80 if ((format == wxBMP_1BPP) || (format == wxBMP_1BPP_BW))
81 {
82 bpp = 1;
83 palette_size = 2;
84 }
85 else if (format == wxBMP_4BPP)
86 {
87 bpp = 4;
88 palette_size = 16;
89 }
90 else if ((format == wxBMP_8BPP) || (format == wxBMP_8BPP_GREY) ||
91 (format == wxBMP_8BPP_RED) || (format == wxBMP_8BPP_PALETTE))
92 {
93 // need to set a wxPalette to use this, HOW TO CHECK IF VALID, SIZE?
94 if ((format == wxBMP_8BPP_PALETTE)
95 #if wxUSE_PALETTE
96 && !image->HasPalette()
97 #endif // wxUSE_PALETTE
98 )
99 {
100 if (verbose)
101 wxLogError(_("BMP: wImage doesn't have own wxPalette."));
102 return FALSE;
103 }
104 bpp = 8;
105 palette_size = 256;
106 }
107 else // you get 24bpp
108 {
109 format = wxBMP_24BPP;
110 bpp = 24;
111 palette_size = 0;
112 }
113
114 unsigned width = image->GetWidth();
115 unsigned row_padding = (4 - int(width*bpp/8.0) % 4) % 4; // # bytes to pad to dword
116 unsigned row_width = int(width * bpp/8.0) + row_padding; // # of bytes per row
117
118 struct
119 {
120 // BitmapHeader:
121 wxUint16 magic; // format magic, always 'BM'
122 wxUint32 filesize; // total file size, inc. headers
123 wxUint32 reserved; // for future use
124 wxUint32 data_offset; // image data offset in the file
125
126 // BitmapInfoHeader:
127 wxUint32 bih_size; // 2nd part's size
128 wxUint32 width, height; // bitmap's dimensions
129 wxUint16 planes; // num of planes
130 wxUint16 bpp; // bits per pixel
131 wxUint32 compression; // compression method
132 wxUint32 size_of_bmp; // size of the bitmap
133 wxUint32 h_res, v_res; // image resolution in dpi
134 wxUint32 num_clrs; // number of colors used
135 wxUint32 num_signif_clrs;// number of significant colors
136 } hdr;
137
138 wxUint32 hdr_size = 14/*BitmapHeader*/ + 40/*BitmapInfoHeader*/;
139
140 hdr.magic = wxUINT16_SWAP_ON_BE(0x4D42/*'BM'*/);
141 hdr.filesize = wxUINT32_SWAP_ON_BE( hdr_size + palette_size*4 +
142 row_width * image->GetHeight() );
143 hdr.reserved = 0;
144 hdr.data_offset = wxUINT32_SWAP_ON_BE(hdr_size + palette_size*4);
145
146 hdr.bih_size = wxUINT32_SWAP_ON_BE(hdr_size - 14);
147 hdr.width = wxUINT32_SWAP_ON_BE(image->GetWidth());
148 hdr.height = wxUINT32_SWAP_ON_BE(image->GetHeight());
149 hdr.planes = wxUINT16_SWAP_ON_BE(1); // always 1 plane
150 hdr.bpp = wxUINT16_SWAP_ON_BE(bpp);
151 hdr.compression = 0; // RGB uncompressed
152 hdr.size_of_bmp = wxUINT32_SWAP_ON_BE(row_width * image->GetHeight());
153 hdr.h_res = hdr.v_res = wxUINT32_SWAP_ON_BE(72); // 72dpi is standard
154 hdr.num_clrs = wxUINT32_SWAP_ON_BE(palette_size); // # colors in colormap
155 hdr.num_signif_clrs = 0; // all colors are significant
156
157 if (// VS: looks ugly but compilers tend to do ugly things with structs,
158 // like aligning hdr.filesize's ofset to dword :(
159 // VZ: we should add padding then...
160 !stream.Write(&hdr.magic, 2) ||
161 !stream.Write(&hdr.filesize, 4) ||
162 !stream.Write(&hdr.reserved, 4) ||
163 !stream.Write(&hdr.data_offset, 4) ||
164 !stream.Write(&hdr.bih_size, 4) ||
165 !stream.Write(&hdr.width, 4) ||
166 !stream.Write(&hdr.height, 4) ||
167 !stream.Write(&hdr.planes, 2) ||
168 !stream.Write(&hdr.bpp, 2) ||
169 !stream.Write(&hdr.compression, 4) ||
170 !stream.Write(&hdr.size_of_bmp, 4) ||
171 !stream.Write(&hdr.h_res, 4) ||
172 !stream.Write(&hdr.v_res, 4) ||
173 !stream.Write(&hdr.num_clrs, 4) ||
174 !stream.Write(&hdr.num_signif_clrs, 4)
175 )
176 {
177 if (verbose)
178 wxLogError(_("BMP: Couldn't write the file header."));
179 return FALSE;
180 }
181
182 wxPalette *palette = NULL; // entries for quantized images
183 wxUint8 *rgbquad = NULL; // for the RGBQUAD bytes for the colormap
184 wxImage *q_image = NULL; // destination for quantized image
185
186 // if <24bpp use quantization to reduce colors for *some* of the formats
187 if ( (format == wxBMP_1BPP) || (format == wxBMP_4BPP) ||
188 (format == wxBMP_8BPP) || (format == wxBMP_8BPP_PALETTE))
189 {
190 // make a new palette and quantize the image
191 if (format != wxBMP_8BPP_PALETTE)
192 {
193 q_image = new wxImage();
194
195 // I get a delete error using Quantize when desired colors > 236
196 int quantize = ((palette_size > 236) ? 236 : palette_size);
197 // fill the destination too, it gives much nicer 4bpp images
198 wxQuantize::Quantize( *image, *q_image, &palette, quantize, 0,
199 wxQUANTIZE_FILL_DESTINATION_IMAGE );
200 }
201 else
202 {
203 #if wxUSE_PALETTE
204 palette = new wxPalette(image->GetPalette());
205 #endif // wxUSE_PALETTE
206 }
207
208 int i;
209 unsigned char r, g, b;
210 rgbquad = new wxUint8 [palette_size*4];
211
212 for (i=0; i<palette_size; i++)
213 {
214 #if wxUSE_PALETTE
215 if (!palette->GetRGB( i, &r, &g, &b ))
216 #endif // wxUSE_PALETTE
217 r = g = b = 0;
218
219 rgbquad[i*4] = b;
220 rgbquad[i*4+1] = g;
221 rgbquad[i*4+2] = r;
222 rgbquad[i*4+3] = 0;
223 }
224 }
225 // make a 256 entry greyscale colormap or 2 entry black & white
226 else if ((format == wxBMP_8BPP_GREY) || (format == wxBMP_8BPP_RED) ||
227 (format == wxBMP_1BPP_BW))
228 {
229 int i;
230 rgbquad = new wxUint8 [palette_size*4];
231
232 for (i=0; i<palette_size; i++)
233 {
234 // if 1BPP_BW then just 0 and 255 then exit
235 if (( i > 0) && (format == wxBMP_1BPP_BW)) i = 255;
236 rgbquad[i*4] = i;
237 rgbquad[i*4+1] = i;
238 rgbquad[i*4+2] = i;
239 rgbquad[i*4+3] = 0;
240 }
241 }
242
243 // if the colormap was made, then it needs to be written
244 if (rgbquad)
245 {
246 if (!stream.Write(rgbquad, palette_size*4))
247 {
248 if (verbose)
249 wxLogError(_("BMP: Couldn't write RGB color map."));
250 delete [] rgbquad;
251 #if wxUSE_PALETTE
252 delete palette;
253 #endif // wxUSE_PALETTE
254 delete q_image;
255 return FALSE;
256 }
257 delete []rgbquad;
258 }
259
260 // pointer to the image data, use quantized if available
261 wxUint8 *data = (wxUint8*) image->GetData();
262 if (q_image) if (q_image->Ok()) data = (wxUint8*) q_image->GetData();
263
264 wxUint8 *buffer = new wxUint8[row_width];
265 memset(buffer, 0, row_width);
266 int y; unsigned x;
267 long int pixel;
268
269 for (y = image->GetHeight() -1 ; y >= 0; y--)
270 {
271 if (format == wxBMP_24BPP) // 3 bytes per pixel red,green,blue
272 {
273 for (x = 0; x < width; x++)
274 {
275 pixel = 3*(y*width + x);
276
277 buffer[3*x ] = data[pixel+2];
278 buffer[3*x + 1] = data[pixel+1];
279 buffer[3*x + 2] = data[pixel];
280 }
281 }
282 else if ((format == wxBMP_8BPP) || // 1 byte per pixel in color
283 (format == wxBMP_8BPP_PALETTE))
284 {
285 for (x = 0; x < width; x++)
286 {
287 pixel = 3*(y*width + x);
288 #if wxUSE_PALETTE
289 buffer[x] = palette->GetPixel( data[pixel],
290 data[pixel+1],
291 data[pixel+2] );
292 #else
293 // FIXME: what should this be? use some std palette maybe?
294 buffer[x] = 0;
295 #endif // wxUSE_PALETTE
296 }
297 }
298 else if (format == wxBMP_8BPP_GREY) // 1 byte per pix, rgb ave to grey
299 {
300 for (x = 0; x < width; x++)
301 {
302 pixel = 3*(y*width + x);
303 buffer[x] = (wxUint8)(.299*data[pixel] +
304 .587*data[pixel+1] +
305 .114*data[pixel+2]);
306 }
307 }
308 else if (format == wxBMP_8BPP_RED) // 1 byte per pixel, red as greys
309 {
310 for (x = 0; x < width; x++)
311 {
312 buffer[x] = (wxUint8)data[3*(y*width + x)];
313 }
314 }
315 else if (format == wxBMP_4BPP) // 4 bpp in color
316 {
317 for (x = 0; x < width; x+=2)
318 {
319 pixel = 3*(y*width + x);
320
321 // fill buffer, ignore if > width
322 #if wxUSE_PALETTE
323 buffer[x/2] =
324 ((wxUint8)palette->GetPixel(data[pixel],
325 data[pixel+1],
326 data[pixel+2]) << 4) |
327 (((x+1) > width)
328 ? 0
329 : ((wxUint8)palette->GetPixel(data[pixel+3],
330 data[pixel+4],
331 data[pixel+5]) ));
332 #else
333 // FIXME: what should this be? use some std palette maybe?
334 buffer[x/2] = 0;
335 #endif // wxUSE_PALETTE
336 }
337 }
338 else if (format == wxBMP_1BPP) // 1 bpp in "color"
339 {
340 for (x = 0; x < width; x+=8)
341 {
342 pixel = 3*(y*width + x);
343
344 #if wxUSE_PALETTE
345 buffer[x/8] = ((wxUint8)palette->GetPixel(data[pixel], data[pixel+1], data[pixel+2]) << 7) |
346 (((x+1) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+3], data[pixel+4], data[pixel+5]) << 6)) |
347 (((x+2) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+6], data[pixel+7], data[pixel+8]) << 5)) |
348 (((x+3) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+9], data[pixel+10], data[pixel+11]) << 4)) |
349 (((x+4) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+12], data[pixel+13], data[pixel+14]) << 3)) |
350 (((x+5) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+15], data[pixel+16], data[pixel+17]) << 2)) |
351 (((x+6) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+18], data[pixel+19], data[pixel+20]) << 1)) |
352 (((x+7) > width) ? 0 : ((wxUint8)palette->GetPixel(data[pixel+21], data[pixel+22], data[pixel+23]) ));
353 #else
354 // FIXME: what should this be? use some std palette maybe?
355 buffer[x/8] = 0;
356 #endif // wxUSE_PALETTE
357 }
358 }
359 else if (format == wxBMP_1BPP_BW) // 1 bpp B&W colormap from red color ONLY
360 {
361 for (x = 0; x < width; x+=8)
362 {
363 pixel = 3*(y*width + x);
364
365 buffer[x/8] =
366 (((wxUint8)(data[pixel] /128.)) << 7) |
367 ( ((x+1) > width) ? 0 : (((wxUint8)(data[pixel+3] /128.)) << 6)) |
368 ( ((x+2) > width) ? 0 : (((wxUint8)(data[pixel+6] /128.)) << 5)) |
369 ( ((x+3) > width) ? 0 : (((wxUint8)(data[pixel+9] /128.)) << 4)) |
370 ( ((x+4) > width) ? 0 : (((wxUint8)(data[pixel+12]/128.)) << 3)) |
371 ( ((x+5) > width) ? 0 : (((wxUint8)(data[pixel+15]/128.)) << 2)) |
372 ( ((x+6) > width) ? 0 : (((wxUint8)(data[pixel+18]/128.)) << 1)) |
373 ( ((x+7) > width) ? 0 : (((wxUint8)(data[pixel+21]/128.)) ));
374 }
375 }
376
377 if (!stream.Write(buffer, row_width))
378 {
379 if (verbose)
380 wxLogError(_("BMP: Couldn't write data."));
381 delete[] buffer;
382 #if wxUSE_PALETTE
383 delete palette;
384 #endif // wxUSE_PALETTE
385 delete q_image;
386 return FALSE;
387 }
388 }
389 delete[] buffer;
390 #if wxUSE_PALETTE
391 delete palette;
392 #endif // wxUSE_PALETTE
393 delete q_image;
394
395 return TRUE;
396 }
397
398
399
400 #ifndef BI_RGB
401 #define BI_RGB 0
402 #define BI_RLE8 1
403 #define BI_RLE4 2
404 #endif
405
406 #ifndef BI_BITFIELDS
407 #define BI_BITFIELDS 3
408 #endif
409
410 #define poffset (line * width * 3 + column * 3)
411
412 bool wxBMPHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int WXUNUSED(index) )
413 {
414 int rshift = 0, gshift = 0, bshift = 0;
415 wxUint8 aByte;
416 wxUint16 aWord;
417 wxInt32 dbuf[4];
418 wxInt32 aDword, rmask = 0, gmask = 0, bmask = 0;
419 wxInt8 bbuf[4];
420 struct _cmap {
421 unsigned char r, g, b;
422 } *cmap = NULL;
423
424 off_t start_offset = stream.TellI();
425 if (start_offset == wxInvalidOffset) start_offset = 0;
426
427 image->Destroy();
428
429 /*
430 * Read the BMP header
431 */
432
433 stream.Read( bbuf, 2 );
434 stream.Read( dbuf, 4 * 4 );
435
436 #if 0 // unused
437 wxInt32 size = wxINT32_SWAP_ON_BE( dbuf[0] );
438 #endif
439 wxInt32 offset = wxINT32_SWAP_ON_BE( dbuf[2] );
440
441 stream.Read(dbuf, 4 * 2);
442 int width = (int)wxINT32_SWAP_ON_BE( dbuf[0] );
443 int height = (int)wxINT32_SWAP_ON_BE( dbuf[1] );
444 if (width > 32767)
445 {
446 if (verbose)
447 wxLogError( _("BMP: Image width > 32767 pixels for file.") );
448 return FALSE;
449 }
450 if (height > 32767)
451 {
452 if (verbose)
453 wxLogError( _("BMP: Image height > 32767 pixels for file.") );
454 return FALSE;
455 }
456
457 stream.Read( &aWord, 2 );
458 /*
459 TODO
460 int planes = (int)wxUINT16_SWAP_ON_BE( aWord );
461 */
462 stream.Read( &aWord, 2 );
463 int bpp = (int)wxUINT16_SWAP_ON_BE( aWord );
464 if (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32)
465 {
466 if (verbose)
467 wxLogError( _("BMP: Unknown bitdepth in file.") );
468 return FALSE;
469 }
470
471 stream.Read( dbuf, 4 * 4 );
472 int comp = (int)wxINT32_SWAP_ON_BE( dbuf[0] );
473 if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS)
474 {
475 if (verbose)
476 wxLogError( _("BMP: Unknown encoding in file.") );
477 return FALSE;
478 }
479
480 stream.Read( dbuf, 4 * 2 );
481 int ncolors = (int)wxINT32_SWAP_ON_BE( dbuf[0] );
482 if (ncolors == 0)
483 ncolors = 1 << bpp;
484 /* some more sanity checks */
485 if (((comp == BI_RLE4) && (bpp != 4)) ||
486 ((comp == BI_RLE8) && (bpp != 8)) ||
487 ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32)))
488 {
489 if (verbose)
490 wxLogError( _("BMP: Encoding doesn't match bitdepth.") );
491 return FALSE;
492 }
493 if (bpp < 16)
494 {
495 cmap = (struct _cmap *)malloc(sizeof(struct _cmap) * ncolors);
496 if (!cmap)
497 {
498 if (verbose)
499 wxLogError( _("BMP: Couldn't allocate memory.") );
500 return FALSE;
501 }
502 }
503 else
504 cmap = NULL;
505
506 image->Create( width, height );
507 unsigned char *ptr = image->GetData();
508 if (!ptr)
509 {
510 if (verbose)
511 wxLogError( _("BMP: Couldn't allocate memory.") );
512 if (cmap)
513 free(cmap);
514 return FALSE;
515 }
516
517 /*
518 * Reading the palette, if it exists.
519 */
520 if (bpp < 16 && ncolors != 0)
521 {
522 unsigned char* r = new unsigned char[ncolors];
523 unsigned char* g = new unsigned char[ncolors];
524 unsigned char* b = new unsigned char[ncolors];
525 for (int j = 0; j < ncolors; j++)
526 {
527 stream.Read( bbuf, 4 );
528 cmap[j].b = bbuf[0];
529 cmap[j].g = bbuf[1];
530 cmap[j].r = bbuf[2];
531
532 r[j] = cmap[j].r;
533 g[j] = cmap[j].g;
534 b[j] = cmap[j].b;
535 }
536
537 #if wxUSE_PALETTE
538 // Set the palette for the wxImage
539 image->SetPalette(wxPalette(ncolors, r, g, b));
540 #endif // wxUSE_PALETTE
541
542 delete[] r;
543 delete[] g;
544 delete[] b;
545 }
546 else if (bpp == 16 || bpp == 32)
547 {
548 if (comp == BI_BITFIELDS)
549 {
550 int bit = 0;
551 stream.Read( dbuf, 4 * 3 );
552 bmask = wxINT32_SWAP_ON_BE( dbuf[0] );
553 gmask = wxINT32_SWAP_ON_BE( dbuf[1] );
554 rmask = wxINT32_SWAP_ON_BE( dbuf[2] );
555 /* find shift amount.. ugly, but i can't think of a better way */
556 for (bit = 0; bit < bpp; bit++)
557 {
558 if (bmask & (1 << bit))
559 bshift = bit;
560 if (gmask & (1 << bit))
561 gshift = bit;
562 if (rmask & (1 << bit))
563 rshift = bit;
564 }
565 }
566 else if (bpp == 16)
567 {
568 rmask = 0x7C00;
569 gmask = 0x03E0;
570 bmask = 0x001F;
571 rshift = 10;
572 gshift = 5;
573 bshift = 0;
574 }
575 else if (bpp == 32)
576 {
577 rmask = 0x00FF0000;
578 gmask = 0x0000FF00;
579 bmask = 0x000000FF;
580 rshift = 16;
581 gshift = 8;
582 bshift = 0;
583 }
584 }
585
586 /*
587 * Reading the image data
588 */
589 stream.SeekI( start_offset + offset );
590 unsigned char *data = ptr;
591
592 /* set the whole image to the background color */
593 if (bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8))
594 {
595 for (int i = 0; i < width * height; i++)
596 {
597 *ptr++ = cmap[0].r;
598 *ptr++ = cmap[0].g;
599 *ptr++ = cmap[0].b;
600 }
601 ptr = data;
602 }
603
604 int line = 0;
605 int column = 0;
606 int linesize = ((width * bpp + 31) / 32) * 4;
607
608 /* BMPs are stored upside down */
609 for (line = (height - 1); line >= 0; line--)
610 {
611 int linepos = 0;
612 for (column = 0; column < width;)
613 {
614 if (bpp < 16)
615 {
616 int index = 0;
617 linepos++;
618 aByte = stream.GetC();
619 if (bpp == 1)
620 {
621 int bit = 0;
622 for (bit = 0; bit < 8 && column < width; bit++)
623 {
624 index = ((aByte & (0x80 >> bit)) ? 1 : 0);
625 ptr[poffset] = cmap[index].r;
626 ptr[poffset + 1] = cmap[index].g;
627 ptr[poffset + 2] = cmap[index].b;
628 column++;
629 }
630 }
631 else if (bpp == 4)
632 {
633 if (comp == BI_RLE4)
634 {
635 if (verbose)
636 wxLogError( _("BMP: Cannot deal with 4bit encoded yet.") );
637 image->Destroy();
638 free(cmap);
639 return FALSE;
640 }
641 else
642 {
643 int nibble = 0;
644 for (nibble = 0; nibble < 2 && column < width; nibble++)
645 {
646 index = ((aByte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
647 if (index >= 16)
648 index = 15;
649 ptr[poffset] = cmap[index].r;
650 ptr[poffset + 1] = cmap[index].g;
651 ptr[poffset + 2] = cmap[index].b;
652 column++;
653 }
654 }
655 }
656 else if (bpp == 8)
657 {
658 if (comp == BI_RLE8)
659 {
660 unsigned char first;
661 first = aByte;
662 aByte = stream.GetC();
663 if (first == 0)
664 {
665 if (aByte == 0)
666 {
667 /* column = width; */
668 }
669 else if (aByte == 1)
670 {
671 column = width;
672 line = -1;
673 }
674 else if (aByte == 2)
675 {
676 aByte = stream.GetC();
677 column += aByte;
678 linepos = column * bpp / 8;
679 aByte = stream.GetC();
680 line += aByte;
681 }
682 else
683 {
684 int absolute = aByte;
685 for (int k = 0; k < absolute; k++)
686 {
687 linepos++;
688 aByte = stream.GetC();
689 ptr[poffset ] = cmap[aByte].r;
690 ptr[poffset + 1] = cmap[aByte].g;
691 ptr[poffset + 2] = cmap[aByte].b;
692 column++;
693 }
694 if (absolute & 0x01)
695 aByte = stream.GetC();
696 }
697 }
698 else
699 {
700 for (int l = 0; l < first && column < width; l++)
701 {
702 ptr[poffset ] = cmap[aByte].r;
703 ptr[poffset + 1] = cmap[aByte].g;
704 ptr[poffset + 2] = cmap[aByte].b;
705 column++;
706 linepos++;
707 }
708 }
709 }
710 else
711 {
712 ptr[poffset ] = cmap[aByte].r;
713 ptr[poffset + 1] = cmap[aByte].g;
714 ptr[poffset + 2] = cmap[aByte].b;
715 column++;
716 // linepos += size; seems to be wrong, RR
717 }
718 }
719 }
720 else if (bpp == 24)
721 {
722 stream.Read( bbuf, 3 );
723 linepos += 3;
724 ptr[poffset ] = (unsigned char)bbuf[2];
725 ptr[poffset + 1] = (unsigned char)bbuf[1];
726 ptr[poffset + 2] = (unsigned char)bbuf[0];
727 column++;
728 }
729 else if (bpp == 16)
730 {
731 unsigned char temp;
732 stream.Read( &aWord, 2 );
733 aWord = wxUINT16_SWAP_ON_BE( aWord );
734 linepos += 2;
735 temp = (aWord & rmask) >> rshift;
736 ptr[poffset] = temp;
737 temp = (aWord & gmask) >> gshift;
738 ptr[poffset + 1] = temp;
739 temp = (aWord & bmask) >> bshift;
740 ptr[poffset + 2] = temp;
741 column++;
742 }
743 else
744 {
745 unsigned char temp;
746 stream.Read( &aDword, 4 );
747 aDword = wxINT32_SWAP_ON_BE( aDword );
748 linepos += 4;
749 temp = (aDword & rmask) >> rshift;
750 ptr[poffset] = temp;
751 temp = (aDword & gmask) >> gshift;
752 ptr[poffset + 1] = temp;
753 temp = (aDword & bmask) >> bshift;
754 ptr[poffset + 2] = temp;
755 column++;
756 }
757 }
758 while ((linepos < linesize) && (comp != 1) && (comp != 2))
759 {
760 stream.Read( &aByte, 1 );
761 linepos += 1;
762 if (stream.LastError() != wxStream_NOERROR)
763 break;
764 }
765 }
766 if (cmap)
767 free(cmap);
768
769 image->SetMask( FALSE );
770
771 return TRUE;
772 }
773
774 bool wxBMPHandler::DoCanRead( wxInputStream& stream )
775 {
776 unsigned char hdr[2];
777
778 stream.Read(hdr, 2);
779 stream.SeekI(-2, wxFromCurrent);
780 return (hdr[0] == 'B' && hdr[1] == 'M');
781 }
782
783 #endif // wxUSE_STREAMS
784
785 #endif // wxUSE_IMAGE