1 //
2 // "$Id: Fl_BMP_Image.cxx 7903 2010-11-28 21:06:39Z matt $"
3 //
4 // Fl_BMP_Image routines.
5 //
6 // Copyright 1997-2010 by Easy Software Products.
7 // Image support by Matthias Melcher, Copyright 2000-2009.
8 //
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.
13 //
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.
18 //
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
22 // USA.
23 //
24 // Please report all bugs and problems on the following page:
25 //
26 // http://www.fltk.org/str.php
27 //
28 // Contents:
29 //
30 // Fl_BMP_Image::Fl_BMP_Image() - Load a BMP image file.
31 //
32
33 //
34 // Include necessary header files...
35 //
36
37 #include <FL/Fl_BMP_Image.H>
38 #include <FL/fl_utf8.h>
39 #include <config.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42
43
44 //
45 // BMP definitions...
46 //
47
48 #ifndef BI_RGB
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
53 #endif // !BI_RGB
54
55
56 //
57 // Local functions...
58 //
59
60 static int read_long(FILE *fp);
61 static unsigned short read_word(FILE *fp);
62 static unsigned int read_dword(FILE *fp);
63 /**
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
66 the image.
67 <P>The destructor free all memory and server resources that are used by
68 the image
69 */
Fl_BMP_Image(const char * bmp)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
78 x, y, // Looping vars
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
86 end_y; // Ending 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
94
95
96 // Open the file...
97 if ((fp = fl_fopen(bmp, "rb")) == NULL) return;
98
99 // Get the header...
100 byte = (uchar)getc(fp); // Check "BM" sync chars
101 bit = (uchar)getc(fp);
102 if (byte != 'B' || bit != 'M') {
103 fclose(fp);
104 return;
105 }
106
107 read_dword(fp); // Skip size
108 read_word(fp); // Skip reserved stuff
109 read_word(fp);
110 offbits = (long)read_dword(fp);// Read offset to image data
111
112 // Then the bitmap information...
113 info_size = read_dword(fp);
114
115 // printf("offbits = %ld, info_size = %d\n", offbits, info_size);
116
117 havemask = 0;
118 row_order = -1;
119 use_5_6_5 = 0;
120
121 if (info_size < 40) {
122 // Old Windows/OS2 BMP header...
123 w(read_word(fp));
124 h(read_word(fp));
125 read_word(fp);
126 depth = read_word(fp);
127 compression = BI_RGB;
128 colors_used = 0;
129
130 repcount = info_size - 12;
131 } else {
132 // New BMP header...
133 w(read_long(fp));
134 // If the height is negative, the row order is flipped
135 temp = read_long(fp);
136 if (temp < 0) row_order = 1;
137 h(abs(temp));
138 read_word(fp);
139 depth = read_word(fp);
140 compression = read_dword(fp);
141 dataSize = read_dword(fp);
142 read_long(fp);
143 read_long(fp);
144 colors_used = read_dword(fp);
145 read_dword(fp);
146
147 repcount = info_size - 40;
148
149 if (!compression && depth>=8 && w()>32/depth) {
150 int Bpp = depth/8;
151 int maskSize = (((w()*Bpp+3)&~3)*h()) + (((((w()+7)/8)+3)&~3)*h());
152 if (maskSize==2*dataSize) {
153 havemask = 1;
154 h(h()/2);
155 bDepth = 4;
156 }
157 }
158 }
159
160 // printf("w() = %d, h() = %d, depth = %d, compression = %d, colors_used = %d, repcount = %d\n",
161 // w(), h(), depth, compression, colors_used, repcount);
162
163 // Skip remaining header bytes...
164 while (repcount > 0) {
165 getc(fp);
166 repcount --;
167 }
168
169 // Check header data...
170 if (!w() || !h() || !depth) {
171 fclose(fp);
172 return;
173 }
174
175 // Get colormap...
176 if (colors_used == 0 && depth <= 8)
177 colors_used = 1 << depth;
178
179 for (repcount = 0; repcount < colors_used; repcount ++) {
180 // Read BGR color...
181 if (fread(colormap[repcount], 1, 3, fp)==0) { /* ignore */ }
182
183 // Skip pad byte for new BMP files...
184 if (info_size > 12) getc(fp);
185 }
186
187 // Read first dword of colormap. It tells us if 5:5:5 or 5:6:5 for 16 bit
188 if (depth == 16)
189 use_5_6_5 = (read_dword(fp) == 0xf800);
190
191 // Set byte depth for RGBA images
192 if (depth == 32)
193 bDepth=4;
194
195 // Setup image and buffers...
196 d(bDepth);
197 if (offbits) fseek(fp, offbits, SEEK_SET);
198
199 array = new uchar[w() * h() * d()];
200 alloc_array = 1;
201
202 // Read the image data...
203 color = 0;
204 repcount = 0;
205 align = 0;
206 byte = 0;
207 temp = 0;
208
209 if (row_order < 0) {
210 start_y = h() - 1;
211 end_y = -1;
212 } else {
213 start_y = 0;
214 end_y = h();
215 }
216
217 for (y = start_y; y != end_y; y += row_order) {
218 ptr = (uchar *)array + y * w() * d();
219
220 switch (depth)
221 {
222 case 1 : // Bitmap
223 for (x = w(), bit = 128; x > 0; x --) {
224 if (bit == 128) byte = (uchar)getc(fp);
225
226 if (byte & bit) {
227 *ptr++ = colormap[1][2];
228 *ptr++ = colormap[1][1];
229 *ptr++ = colormap[1][0];
230 } else {
231 *ptr++ = colormap[0][2];
232 *ptr++ = colormap[0][1];
233 *ptr++ = colormap[0][0];
234 }
235
236 if (bit > 1)
237 bit >>= 1;
238 else
239 bit = 128;
240 }
241
242 // Read remaining bytes to align to 32 bits...
243 for (temp = (w() + 7) / 8; temp & 3; temp ++) {
244 getc(fp);
245 }
246 break;
247
248 case 4 : // 16-color
249 for (x = w(), bit = 0xf0; x > 0; x --) {
250 // Get a new repcount as needed...
251 if (repcount == 0) {
252 if (compression != BI_RLE4) {
253 repcount = 2;
254 color = -1;
255 } else {
256 while (align > 0) {
257 align --;
258 getc(fp);
259 }
260
261 if ((repcount = getc(fp)) == 0) {
262 if ((repcount = getc(fp)) == 0) {
263 // End of line...
264 x ++;
265 continue;
266 } else if (repcount == 1) {
267 // End of image...
268 break;
269 } else if (repcount == 2) {
270 // Delta...
271 repcount = getc(fp) * getc(fp) * w();
272 color = 0;
273 } else {
274 // Absolute...
275 color = -1;
276 align = ((4 - (repcount & 3)) / 2) & 1;
277 }
278 } else {
279 color = getc(fp);
280 }
281 }
282 }
283
284 // Get a new color as needed...
285 repcount --;
286
287 // Extract the next pixel...
288 if (bit == 0xf0) {
289 // Get the next color byte as needed...
290 if (color < 0) temp = getc(fp);
291 else temp = color;
292
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];
297
298 bit = 0x0f;
299 } else {
300 bit = 0xf0;
301
302 // Copy the color value...
303 *ptr++ = colormap[temp & 15][2];
304 *ptr++ = colormap[temp & 15][1];
305 *ptr++ = colormap[temp & 15][0];
306 }
307
308 }
309
310 if (!compression) {
311 // Read remaining bytes to align to 32 bits...
312 for (temp = (w() + 1) / 2; temp & 3; temp ++) {
313 getc(fp);
314 }
315 }
316 break;
317
318 case 8 : // 256-color
319 for (x = w(); x > 0; x --) {
320 // Get a new repcount as needed...
321 if (compression != BI_RLE8) {
322 repcount = 1;
323 color = -1;
324 }
325
326 if (repcount == 0) {
327 while (align > 0) {
328 align --;
329 getc(fp);
330 }
331
332 if ((repcount = getc(fp)) == 0) {
333 if ((repcount = getc(fp)) == 0) {
334 // End of line...
335 x ++;
336 continue;
337 } else if (repcount == 1) {
338 // End of image...
339 break;
340 } else if (repcount == 2) {
341 // Delta...
342 repcount = getc(fp) * getc(fp) * w();
343 color = 0;
344 } else {
345 // Absolute...
346 color = -1;
347 align = (2 - (repcount & 1)) & 1;
348 }
349 } else {
350 color = getc(fp);
351 }
352 }
353
354 // Get a new color as needed...
355 if (color < 0) temp = getc(fp);
356 else temp = color;
357
358 repcount --;
359
360 // Copy the color value...
361 *ptr++ = colormap[temp][2];
362 *ptr++ = colormap[temp][1];
363 *ptr++ = colormap[temp][0];
364 if (havemask) ptr++;
365 }
366
367 if (!compression) {
368 // Read remaining bytes to align to 32 bits...
369 for (temp = w(); temp & 3; temp ++) {
370 getc(fp);
371 }
372 }
373 break;
374
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) ;
378 if (use_5_6_5) {
379 ptr[2] = (uchar)(( b << 3 ) & 0xf8);
380 ptr[1] = (uchar)(((a << 5) & 0xe0) | ((b >> 3) & 0x1c));
381 ptr[0] = (uchar)(a & 0xf8);
382 } else {
383 ptr[2] = (uchar)((b << 3) & 0xf8);
384 ptr[1] = (uchar)(((a << 6) & 0xc0) | ((b >> 2) & 0x38));
385 ptr[0] = (uchar)((a<<1) & 0xf8);
386 }
387 }
388
389 // Read remaining bytes to align to 32 bits...
390 for (temp = w() * 2; temp & 3; temp ++) {
391 getc(fp);
392 }
393 break;
394
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);
400 }
401
402 // Read remaining bytes to align to 32 bits...
403 for (temp = w() * 3; temp & 3; temp ++) {
404 getc(fp);
405 }
406 break;
407
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);
414 }
415 break;
416 }
417 }
418
419 if (havemask) {
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);
424 if (byte & bit)
425 *ptr = 0;
426 else
427 *ptr = 255;
428 if (bit > 1)
429 bit >>= 1;
430 else
431 bit = 128;
432 }
433 // Read remaining bytes to align to 32 bits...
434 for (temp = (w() + 7) / 8; temp & 3; temp ++)
435 getc(fp);
436 }
437 }
438
439 // Close the file and return...
440 fclose(fp);
441 }
442
443
444 //
445 // 'read_word()' - Read a 16-bit unsigned integer.
446 //
447
448 static unsigned short // O - 16-bit unsigned integer
read_word(FILE * fp)449 read_word(FILE *fp) { // I - File to read from
450 unsigned char b0, b1; // Bytes from file
451
452 b0 = (uchar)getc(fp);
453 b1 = (uchar)getc(fp);
454
455 return ((b1 << 8) | b0);
456 }
457
458
459 //
460 // 'read_dword()' - Read a 32-bit unsigned integer.
461 //
462
463 static unsigned int // O - 32-bit unsigned integer
read_dword(FILE * fp)464 read_dword(FILE *fp) { // I - File to read from
465 unsigned char b0, b1, b2, b3; // Bytes from file
466
467 b0 = (uchar)getc(fp);
468 b1 = (uchar)getc(fp);
469 b2 = (uchar)getc(fp);
470 b3 = (uchar)getc(fp);
471
472 return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
473 }
474
475
476 //
477 // 'read_long()' - Read a 32-bit signed integer.
478 //
479
480 static int // O - 32-bit signed integer
read_long(FILE * fp)481 read_long(FILE *fp) { // I - File to read from
482 unsigned char b0, b1, b2, b3; // Bytes from file
483
484 b0 = (uchar)getc(fp);
485 b1 = (uchar)getc(fp);
486 b2 = (uchar)getc(fp);
487 b3 = (uchar)getc(fp);
488
489 return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
490 }
491
492
493 //
494 // End of "$Id: Fl_BMP_Image.cxx 7903 2010-11-28 21:06:39Z matt $".
495 //
496