2 // "$Id: Fl_BMP_Image.cxx 7903 2010-11-28 21:06:39Z matt $"
4 // Fl_BMP_Image routines.
6 // Copyright 1997-2010 by Easy Software Products.
7 // Image support by Matthias Melcher, Copyright 2000-2009.
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Library General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Library General Public License for more details.
19 // You should have received a copy of the GNU Library General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 // Please report all bugs and problems on the following page:
26 // http://www.fltk.org/str.php
30 // Fl_BMP_Image::Fl_BMP_Image() - Load a BMP image file.
34 // Include necessary header files...
37 #include <FL/Fl_BMP_Image.H>
38 #include <FL/fl_utf8.h>
49 # define BI_RGB 0 // No compression - straight BGR data
50 # define BI_RLE8 1 // 8-bit run-length compression
51 # define BI_RLE4 2 // 4-bit run-length compression
52 # define BI_BITFIELDS 3 // RGB bitmap with RGB masks
60 static int read_long(FILE *fp
);
61 static unsigned short read_word(FILE *fp
);
62 static unsigned int read_dword(FILE *fp
);
64 The constructor loads the named BMP image from the given bmp filename.
65 <P>The inherited destructor free all memory and server resources that are used by
67 <P>The destructor free all memory and server resources that are used by
70 Fl_BMP_Image::Fl_BMP_Image(const char *bmp
) // I - File to read
71 : Fl_RGB_Image(0,0,0) {
72 FILE *fp
; // File pointer
73 int info_size
, // Size of info header
74 depth
, // Depth of image (bits)
75 bDepth
= 3, // Depth of image (bytes)
76 compression
, // Type of compression
77 colors_used
, // Number of colors used
79 color
, // Color of RLE pixel
80 repcount
, // Number of times to repeat
81 temp
, // Temporary color
82 align
, // Alignment bytes
83 dataSize
, // number of bytes in image data set
84 row_order
, // 1 = normal; -1 = flipped row order
85 start_y
, // Beginning Y
87 long offbits
; // Offset to image data
88 uchar bit
, // Bit in image
89 byte
; // Byte in image
90 uchar
*ptr
; // Pointer into pixels
91 uchar colormap
[256][3];// Colormap
92 uchar havemask
; // Single bit mask follows image data
93 int use_5_6_5
; // Use 5:6:5 for R:G:B channels in 16 bit images
97 if ((fp
= fl_fopen(bmp
, "rb")) == NULL
) return;
100 byte
= (uchar
)getc(fp
); // Check "BM" sync chars
101 bit
= (uchar
)getc(fp
);
102 if (byte
!= 'B' || bit
!= 'M') {
107 read_dword(fp
); // Skip size
108 read_word(fp
); // Skip reserved stuff
110 offbits
= (long)read_dword(fp
);// Read offset to image data
112 // Then the bitmap information...
113 info_size
= read_dword(fp
);
115 // printf("offbits = %ld, info_size = %d\n", offbits, info_size);
121 if (info_size
< 40) {
122 // Old Windows/OS2 BMP header...
126 depth
= read_word(fp
);
127 compression
= BI_RGB
;
130 repcount
= info_size
- 12;
134 // If the height is negative, the row order is flipped
135 temp
= read_long(fp
);
136 if (temp
< 0) row_order
= 1;
139 depth
= read_word(fp
);
140 compression
= read_dword(fp
);
141 dataSize
= read_dword(fp
);
144 colors_used
= read_dword(fp
);
147 repcount
= info_size
- 40;
149 if (!compression
&& depth
>=8 && w()>32/depth
) {
151 int maskSize
= (((w()*Bpp
+3)&~3)*h()) + (((((w()+7)/8)+3)&~3)*h());
152 if (maskSize
==2*dataSize
) {
160 // printf("w() = %d, h() = %d, depth = %d, compression = %d, colors_used = %d, repcount = %d\n",
161 // w(), h(), depth, compression, colors_used, repcount);
163 // Skip remaining header bytes...
164 while (repcount
> 0) {
169 // Check header data...
170 if (!w() || !h() || !depth
) {
176 if (colors_used
== 0 && depth
<= 8)
177 colors_used
= 1 << depth
;
179 for (repcount
= 0; repcount
< colors_used
; repcount
++) {
181 if (fread(colormap
[repcount
], 1, 3, fp
)==0) { /* ignore */ }
183 // Skip pad byte for new BMP files...
184 if (info_size
> 12) getc(fp
);
187 // Read first dword of colormap. It tells us if 5:5:5 or 5:6:5 for 16 bit
189 use_5_6_5
= (read_dword(fp
) == 0xf800);
191 // Set byte depth for RGBA images
195 // Setup image and buffers...
197 if (offbits
) fseek(fp
, offbits
, SEEK_SET
);
199 array
= new uchar
[w() * h() * d()];
202 // Read the image data...
217 for (y
= start_y
; y
!= end_y
; y
+= row_order
) {
218 ptr
= (uchar
*)array
+ y
* w() * d();
223 for (x
= w(), bit
= 128; x
> 0; x
--) {
224 if (bit
== 128) byte
= (uchar
)getc(fp
);
227 *ptr
++ = colormap
[1][2];
228 *ptr
++ = colormap
[1][1];
229 *ptr
++ = colormap
[1][0];
231 *ptr
++ = colormap
[0][2];
232 *ptr
++ = colormap
[0][1];
233 *ptr
++ = colormap
[0][0];
242 // Read remaining bytes to align to 32 bits...
243 for (temp
= (w() + 7) / 8; temp
& 3; temp
++) {
249 for (x
= w(), bit
= 0xf0; x
> 0; x
--) {
250 // Get a new repcount as needed...
252 if (compression
!= BI_RLE4
) {
261 if ((repcount
= getc(fp
)) == 0) {
262 if ((repcount
= getc(fp
)) == 0) {
266 } else if (repcount
== 1) {
269 } else if (repcount
== 2) {
271 repcount
= getc(fp
) * getc(fp
) * w();
276 align
= ((4 - (repcount
& 3)) / 2) & 1;
284 // Get a new color as needed...
287 // Extract the next pixel...
289 // Get the next color byte as needed...
290 if (color
< 0) temp
= getc(fp
);
293 // Copy the color value...
294 *ptr
++ = colormap
[(temp
>> 4) & 15][2];
295 *ptr
++ = colormap
[(temp
>> 4) & 15][1];
296 *ptr
++ = colormap
[(temp
>> 4) & 15][0];
302 // Copy the color value...
303 *ptr
++ = colormap
[temp
& 15][2];
304 *ptr
++ = colormap
[temp
& 15][1];
305 *ptr
++ = colormap
[temp
& 15][0];
311 // Read remaining bytes to align to 32 bits...
312 for (temp
= (w() + 1) / 2; temp
& 3; temp
++) {
318 case 8 : // 256-color
319 for (x
= w(); x
> 0; x
--) {
320 // Get a new repcount as needed...
321 if (compression
!= BI_RLE8
) {
332 if ((repcount
= getc(fp
)) == 0) {
333 if ((repcount
= getc(fp
)) == 0) {
337 } else if (repcount
== 1) {
340 } else if (repcount
== 2) {
342 repcount
= getc(fp
) * getc(fp
) * w();
347 align
= (2 - (repcount
& 1)) & 1;
354 // Get a new color as needed...
355 if (color
< 0) temp
= getc(fp
);
360 // Copy the color value...
361 *ptr
++ = colormap
[temp
][2];
362 *ptr
++ = colormap
[temp
][1];
363 *ptr
++ = colormap
[temp
][0];
368 // Read remaining bytes to align to 32 bits...
369 for (temp
= w(); temp
& 3; temp
++) {
375 case 16 : // 16-bit 5:5:5 or 5:6:5 RGB
376 for (x
= w(); x
> 0; x
--, ptr
+= bDepth
) {
377 uchar b
= getc(fp
), a
= getc(fp
) ;
379 ptr
[2] = (uchar
)(( b
<< 3 ) & 0xf8);
380 ptr
[1] = (uchar
)(((a
<< 5) & 0xe0) | ((b
>> 3) & 0x1c));
381 ptr
[0] = (uchar
)(a
& 0xf8);
383 ptr
[2] = (uchar
)((b
<< 3) & 0xf8);
384 ptr
[1] = (uchar
)(((a
<< 6) & 0xc0) | ((b
>> 2) & 0x38));
385 ptr
[0] = (uchar
)((a
<<1) & 0xf8);
389 // Read remaining bytes to align to 32 bits...
390 for (temp
= w() * 2; temp
& 3; temp
++) {
395 case 24 : // 24-bit RGB
396 for (x
= w(); x
> 0; x
--, ptr
+= bDepth
) {
397 ptr
[2] = (uchar
)getc(fp
);
398 ptr
[1] = (uchar
)getc(fp
);
399 ptr
[0] = (uchar
)getc(fp
);
402 // Read remaining bytes to align to 32 bits...
403 for (temp
= w() * 3; temp
& 3; temp
++) {
408 case 32 : // 32-bit RGBA
409 for (x
= w(); x
> 0; x
--, ptr
+= bDepth
) {
410 ptr
[2] = (uchar
)getc(fp
);
411 ptr
[1] = (uchar
)getc(fp
);
412 ptr
[0] = (uchar
)getc(fp
);
413 ptr
[3] = (uchar
)getc(fp
);
420 for (y
= h() - 1; y
>= 0; y
--) {
421 ptr
= (uchar
*)array
+ y
* w() * d() + 3;
422 for (x
= w(), bit
= 128; x
> 0; x
--, ptr
+=bDepth
) {
423 if (bit
== 128) byte
= (uchar
)getc(fp
);
433 // Read remaining bytes to align to 32 bits...
434 for (temp
= (w() + 7) / 8; temp
& 3; temp
++)
439 // Close the file and return...
445 // 'read_word()' - Read a 16-bit unsigned integer.
448 static unsigned short // O - 16-bit unsigned integer
449 read_word(FILE *fp
) { // I - File to read from
450 unsigned char b0
, b1
; // Bytes from file
452 b0
= (uchar
)getc(fp
);
453 b1
= (uchar
)getc(fp
);
455 return ((b1
<< 8) | b0
);
460 // 'read_dword()' - Read a 32-bit unsigned integer.
463 static unsigned int // O - 32-bit unsigned integer
464 read_dword(FILE *fp
) { // I - File to read from
465 unsigned char b0
, b1
, b2
, b3
; // Bytes from file
467 b0
= (uchar
)getc(fp
);
468 b1
= (uchar
)getc(fp
);
469 b2
= (uchar
)getc(fp
);
470 b3
= (uchar
)getc(fp
);
472 return ((((((b3
<< 8) | b2
) << 8) | b1
) << 8) | b0
);
477 // 'read_long()' - Read a 32-bit signed integer.
480 static int // O - 32-bit signed integer
481 read_long(FILE *fp
) { // I - File to read from
482 unsigned char b0
, b1
, b2
, b3
; // Bytes from file
484 b0
= (uchar
)getc(fp
);
485 b1
= (uchar
)getc(fp
);
486 b2
= (uchar
)getc(fp
);
487 b3
= (uchar
)getc(fp
);
489 return ((int)(((((b3
<< 8) | b2
) << 8) | b1
) << 8) | b0
);
494 // End of "$Id: Fl_BMP_Image.cxx 7903 2010-11-28 21:06:39Z matt $".