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