fltk  1.3.5-source
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X.
  Fossies Dox: fltk-1.3.5-source.tar.bz2  ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_BMP_Image.cxx
Go to the documentation of this file.
1 //
2 // "$Id$"
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. Distribution and use rights are outlined in
10 // the file "COPYING" which should have been included with this file. If this
11 // file is missing or damaged, see the license at:
12 //
13 // http://www.fltk.org/COPYING.php
14 //
15 // Please report all bugs and problems on the following page:
16 //
17 // http://www.fltk.org/str.php
18 //
19 // Contents:
20 //
21 // Fl_BMP_Image::Fl_BMP_Image() - Load a BMP image file.
22 //
23 
24 //
25 // Include necessary header files...
26 //
27 
28 #include <FL/Fl_BMP_Image.H>
29 #include <FL/fl_utf8.h>
30 #include <FL/Fl.H>
31 #include <config.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 
35 
36 //
37 // BMP definitions...
38 //
39 
40 #ifndef BI_RGB
41 # define BI_RGB 0 // No compression - straight BGR data
42 # define BI_RLE8 1 // 8-bit run-length compression
43 # define BI_RLE4 2 // 4-bit run-length compression
44 # define BI_BITFIELDS 3 // RGB bitmap with RGB masks
45 #endif // !BI_RGB
46 
47 
48 //
49 // Local functions...
50 //
51 
52 static int read_long(FILE *fp);
53 static unsigned short read_word(FILE *fp);
54 static unsigned int read_dword(FILE *fp);
55 
56 
68 Fl_BMP_Image::Fl_BMP_Image(const char *bmp) // I - File to read
69  : Fl_RGB_Image(0,0,0) {
70  FILE *fp; // File pointer
71  int info_size, // Size of info header
72  depth, // Depth of image (bits)
73  bDepth = 3, // Depth of image (bytes)
74  compression, // Type of compression
75  colors_used, // Number of colors used
76  x, y, // Looping vars
77  color, // Color of RLE pixel
78  repcount, // Number of times to repeat
79  temp, // Temporary color
80  align, // Alignment bytes
81  dataSize, // number of bytes in image data set
82  row_order, // 1 = normal; -1 = flipped row order
83  start_y, // Beginning Y
84  end_y; // Ending Y
85  long offbits; // Offset to image data
86  uchar bit, // Bit in image
87  byte; // Byte in image
88  uchar *ptr; // Pointer into pixels
89  uchar colormap[256][3];// Colormap
90  uchar havemask; // Single bit mask follows image data
91  int use_5_6_5; // Use 5:6:5 for R:G:B channels in 16 bit images
92 
93 
94  // Open the file...
95  if ((fp = fl_fopen(bmp, "rb")) == NULL) {
97  return;
98  }
99 
100  // Get the header...
101  byte = (uchar)getc(fp); // Check "BM" sync chars
102  bit = (uchar)getc(fp);
103  if (byte != 'B' || bit != 'M') {
104  fclose(fp);
105  ld(ERR_FORMAT);
106  return;
107  }
108 
109  read_dword(fp); // Skip size
110  read_word(fp); // Skip reserved stuff
111  read_word(fp);
112  offbits = (long)read_dword(fp);// Read offset to image data
113 
114  // Then the bitmap information...
115  info_size = read_dword(fp);
116 
117 // printf("offbits = %ld, info_size = %d\n", offbits, info_size);
118 
119  havemask = 0;
120  row_order = -1;
121  use_5_6_5 = 0;
122 
123  if (info_size < 40) {
124  // Old Windows/OS2 BMP header...
125  w(read_word(fp));
126  h(read_word(fp));
127  read_word(fp);
128  depth = read_word(fp);
129  compression = BI_RGB;
130  colors_used = 0;
131 
132  repcount = info_size - 12;
133  } else {
134  // New BMP header...
135  w(read_long(fp));
136  // If the height is negative, the row order is flipped
137  temp = read_long(fp);
138  if (temp < 0) row_order = 1;
139  h(abs(temp));
140  read_word(fp);
141  depth = read_word(fp);
142  compression = read_dword(fp);
143  dataSize = read_dword(fp);
144  read_long(fp);
145  read_long(fp);
146  colors_used = read_dword(fp);
147  read_dword(fp);
148 
149  repcount = info_size - 40;
150 
151  if (!compression && depth>=8 && w()>32/depth) {
152  int Bpp = depth/8;
153  int maskSize = (((w()*Bpp+3)&~3)*h()) + (((((w()+7)/8)+3)&~3)*h());
154  if (maskSize==2*dataSize) {
155  havemask = 1;
156  h(h()/2);
157  bDepth = 4;
158  }
159  }
160  }
161 
162 // printf("w() = %d, h() = %d, depth = %d, compression = %d, colors_used = %d, repcount = %d\n",
163 // w(), h(), depth, compression, colors_used, repcount);
164 
165  // Skip remaining header bytes...
166  while (repcount > 0) {
167  getc(fp);
168  repcount --;
169  }
170 
171  // Check header data...
172  if (!w() || !h() || !depth) {
173  fclose(fp);
174  w(0); h(0); d(0); ld(ERR_FORMAT);
175  return;
176  }
177 
178  // Get colormap...
179  if (colors_used == 0 && depth <= 8)
180  colors_used = 1 << depth;
181 
182  for (repcount = 0; repcount < colors_used; repcount ++) {
183  // Read BGR color...
184  if (fread(colormap[repcount], 1, 3, fp)==0) { /* ignore */ }
185 
186  // Skip pad byte for new BMP files...
187  if (info_size > 12) getc(fp);
188  }
189 
190  // Read first dword of colormap. It tells us if 5:5:5 or 5:6:5 for 16 bit
191  if (depth == 16)
192  use_5_6_5 = (read_dword(fp) == 0xf800);
193 
194  // Set byte depth for RGBA images
195  if (depth == 32)
196  bDepth=4;
197 
198  // Setup image and buffers...
199  d(bDepth);
200  if (offbits) fseek(fp, offbits, SEEK_SET);
201 
202  if (((size_t)w()) * h() * d() > max_size() ) {
203  Fl::warning("BMP file \"%s\" is too large!\n", bmp);
204  fclose(fp);
205  w(0); h(0); d(0); ld(ERR_FORMAT);
206  return;
207  }
208  array = new uchar[w() * h() * d()];
209  alloc_array = 1;
210 
211  // Read the image data...
212  color = 0;
213  repcount = 0;
214  align = 0;
215  byte = 0;
216  temp = 0;
217 
218  if (row_order < 0) {
219  start_y = h() - 1;
220  end_y = -1;
221  } else {
222  start_y = 0;
223  end_y = h();
224  }
225 
226  for (y = start_y; y != end_y; y += row_order) {
227  ptr = (uchar *)array + y * w() * d();
228 
229  switch (depth)
230  {
231  case 1 : // Bitmap
232  for (x = w(), bit = 128; x > 0; x --) {
233  if (bit == 128) byte = (uchar)getc(fp);
234 
235  if (byte & bit) {
236  *ptr++ = colormap[1][2];
237  *ptr++ = colormap[1][1];
238  *ptr++ = colormap[1][0];
239  } else {
240  *ptr++ = colormap[0][2];
241  *ptr++ = colormap[0][1];
242  *ptr++ = colormap[0][0];
243  }
244 
245  if (bit > 1)
246  bit >>= 1;
247  else
248  bit = 128;
249  }
250 
251  // Read remaining bytes to align to 32 bits...
252  for (temp = (w() + 7) / 8; temp & 3; temp ++) {
253  getc(fp);
254  }
255  break;
256 
257  case 4 : // 16-color
258  for (x = w(), bit = 0xf0; x > 0; x --) {
259  // Get a new repcount as needed...
260  if (repcount == 0) {
261  if (compression != BI_RLE4) {
262  repcount = 2;
263  color = -1;
264  } else {
265  while (align > 0) {
266  align --;
267  getc(fp);
268  }
269 
270  if ((repcount = getc(fp)) == 0) {
271  if ((repcount = getc(fp)) == 0) {
272  // End of line...
273  x ++;
274  continue;
275  } else if (repcount == 1) {
276  // End of image...
277  break;
278  } else if (repcount == 2) {
279  // Delta...
280  repcount = getc(fp) * getc(fp) * w();
281  color = 0;
282  } else {
283  // Absolute...
284  color = -1;
285  align = ((4 - (repcount & 3)) / 2) & 1;
286  }
287  } else {
288  color = getc(fp);
289  }
290  }
291  }
292 
293  // Get a new color as needed...
294  repcount --;
295 
296  // Extract the next pixel...
297  if (bit == 0xf0) {
298  // Get the next color byte as needed...
299  if (color < 0) temp = getc(fp);
300  else temp = color;
301 
302  // Copy the color value...
303  *ptr++ = colormap[(temp >> 4) & 15][2];
304  *ptr++ = colormap[(temp >> 4) & 15][1];
305  *ptr++ = colormap[(temp >> 4) & 15][0];
306 
307  bit = 0x0f;
308  } else {
309  bit = 0xf0;
310 
311  // Copy the color value...
312  *ptr++ = colormap[temp & 15][2];
313  *ptr++ = colormap[temp & 15][1];
314  *ptr++ = colormap[temp & 15][0];
315  }
316 
317  }
318 
319  if (!compression) {
320  // Read remaining bytes to align to 32 bits...
321  for (temp = (w() + 1) / 2; temp & 3; temp ++) {
322  getc(fp);
323  }
324  }
325  break;
326 
327  case 8 : // 256-color
328  for (x = w(); x > 0; x --) {
329  // Get a new repcount as needed...
330  if (compression != BI_RLE8) {
331  repcount = 1;
332  color = -1;
333  }
334 
335  if (repcount == 0) {
336  while (align > 0) {
337  align --;
338  getc(fp);
339  }
340 
341  if ((repcount = getc(fp)) == 0) {
342  if ((repcount = getc(fp)) == 0) {
343  // End of line...
344  x ++;
345  continue;
346  } else if (repcount == 1) {
347  // End of image...
348  break;
349  } else if (repcount == 2) {
350  // Delta...
351  repcount = getc(fp) * getc(fp) * w();
352  color = 0;
353  } else {
354  // Absolute...
355  color = -1;
356  align = (2 - (repcount & 1)) & 1;
357  }
358  } else {
359  color = getc(fp);
360  }
361  }
362 
363  // Get a new color as needed...
364  if (color < 0) temp = getc(fp);
365  else temp = color;
366 
367  repcount --;
368 
369  // Copy the color value...
370  *ptr++ = colormap[temp][2];
371  *ptr++ = colormap[temp][1];
372  *ptr++ = colormap[temp][0];
373  if (havemask) ptr++;
374  }
375 
376  if (!compression) {
377  // Read remaining bytes to align to 32 bits...
378  for (temp = w(); temp & 3; temp ++) {
379  getc(fp);
380  }
381  }
382  break;
383 
384  case 16 : // 16-bit 5:5:5 or 5:6:5 RGB
385  for (x = w(); x > 0; x --, ptr += bDepth) {
386  uchar b = getc(fp), a = getc(fp) ;
387  if (use_5_6_5) {
388  ptr[2] = (uchar)(( b << 3 ) & 0xf8);
389  ptr[1] = (uchar)(((a << 5) & 0xe0) | ((b >> 3) & 0x1c));
390  ptr[0] = (uchar)(a & 0xf8);
391  } else {
392  ptr[2] = (uchar)((b << 3) & 0xf8);
393  ptr[1] = (uchar)(((a << 6) & 0xc0) | ((b >> 2) & 0x38));
394  ptr[0] = (uchar)((a<<1) & 0xf8);
395  }
396  }
397 
398  // Read remaining bytes to align to 32 bits...
399  for (temp = w() * 2; temp & 3; temp ++) {
400  getc(fp);
401  }
402  break;
403 
404  case 24 : // 24-bit RGB
405  for (x = w(); x > 0; x --, ptr += bDepth) {
406  ptr[2] = (uchar)getc(fp);
407  ptr[1] = (uchar)getc(fp);
408  ptr[0] = (uchar)getc(fp);
409  }
410 
411  // Read remaining bytes to align to 32 bits...
412  for (temp = w() * 3; temp & 3; temp ++) {
413  getc(fp);
414  }
415  break;
416 
417  case 32 : // 32-bit RGBA
418  for (x = w(); x > 0; x --, ptr += bDepth) {
419  ptr[2] = (uchar)getc(fp);
420  ptr[1] = (uchar)getc(fp);
421  ptr[0] = (uchar)getc(fp);
422  ptr[3] = (uchar)getc(fp);
423  }
424  break;
425  }
426  }
427 
428  if (havemask) {
429  for (y = h() - 1; y >= 0; y --) {
430  ptr = (uchar *)array + y * w() * d() + 3;
431  for (x = w(), bit = 128; x > 0; x --, ptr+=bDepth) {
432  if (bit == 128) byte = (uchar)getc(fp);
433  if (byte & bit)
434  *ptr = 0;
435  else
436  *ptr = 255;
437  if (bit > 1)
438  bit >>= 1;
439  else
440  bit = 128;
441  }
442  // Read remaining bytes to align to 32 bits...
443  for (temp = (w() + 7) / 8; temp & 3; temp ++)
444  getc(fp);
445  }
446  }
447 
448  // Close the file and return...
449  fclose(fp);
450 }
451 
452 
453 //
454 // 'read_word()' - Read a 16-bit unsigned integer.
455 //
456 
457 static unsigned short // O - 16-bit unsigned integer
458 read_word(FILE *fp) { // I - File to read from
459  unsigned char b0, b1; // Bytes from file
460 
461  b0 = (uchar)getc(fp);
462  b1 = (uchar)getc(fp);
463 
464  return ((b1 << 8) | b0);
465 }
466 
467 
468 //
469 // 'read_dword()' - Read a 32-bit unsigned integer.
470 //
471 
472 static unsigned int // O - 32-bit unsigned integer
473 read_dword(FILE *fp) { // I - File to read from
474  unsigned char b0, b1, b2, b3; // Bytes from file
475 
476  b0 = (uchar)getc(fp);
477  b1 = (uchar)getc(fp);
478  b2 = (uchar)getc(fp);
479  b3 = (uchar)getc(fp);
480 
481  return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
482 }
483 
484 
485 //
486 // 'read_long()' - Read a 32-bit signed integer.
487 //
488 
489 static int // O - 32-bit signed integer
490 read_long(FILE *fp) { // I - File to read from
491  unsigned char b0, b1, b2, b3; // Bytes from file
492 
493  b0 = (uchar)getc(fp);
494  b1 = (uchar)getc(fp);
495  b2 = (uchar)getc(fp);
496  b3 = (uchar)getc(fp);
497 
498  return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
499 }
500 
501 
502 //
503 // End of "$Id$".
504 //
read_word
static unsigned short read_word(FILE *fp)
Definition: Fl_BMP_Image.cxx:458
Fl.H
read_long
static int read_long(FILE *fp)
Definition: Fl_BMP_Image.cxx:490
BI_RLE8
#define BI_RLE8
Definition: Fl_BMP_Image.cxx:42
Fl_Image::d
int d() const
Definition: Fl_Image.H:121
NULL
#define NULL
Definition: forms.H:34
fl_fopen
FILE * fl_fopen(const char *f, const char *mode)
Definition: fl_utf8.cxx:498
b
long b
Definition: jpegint.h:397
BI_RLE4
#define BI_RLE4
Definition: Fl_BMP_Image.cxx:43
Fl_Image::ld
int ld() const
Definition: Fl_Image.H:126
SEEK_SET
#define SEEK_SET
Definition: zconf.h:484
Fl_RGB_Image::alloc_array
int alloc_array
Definition: Fl_Image.H:215
fl_utf8.h
header for Unicode and UTF-8 character handling
Fl_Image::ERR_FORMAT
static const int ERR_FORMAT
Definition: Fl_Image.H:60
Fl_BMP_Image.H
Fl_Image::h
int h() const
Definition: Fl_Image.H:115
Fl_RGB_Image::array
const uchar * array
Definition: Fl_Image.H:212
color
void color(int n)
Definition: gl2opengl.h:29
x
int x
Definition: test.c:73
Fl_RGB_Image::max_size
static size_t max_size()
Definition: Fl_Image.H:255
y
int y
Definition: test.c:74
Fl_Image::w
int w() const
Definition: Fl_Image.H:111
read_dword
static unsigned int read_dword(FILE *fp)
Definition: Fl_BMP_Image.cxx:473
Fl::warning
static void(* warning)(const char *,...)
Definition: Fl.H:498
Fl_BMP_Image::Fl_BMP_Image
Fl_BMP_Image(const char *filename)
Definition: Fl_BMP_Image.cxx:68
BI_RGB
#define BI_RGB
Definition: Fl_BMP_Image.cxx:41
Fl_Image::ERR_FILE_ACCESS
static const int ERR_FILE_ACCESS
Definition: Fl_Image.H:59
uchar
unsigned char uchar
Definition: fl_types.h:30
Fl_RGB_Image
Definition: Fl_Image.H:202