|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: Fl_BMP_Image.cxx 7903 2010-11-28 21:06:39Z matt $" 00003 // 00004 // Fl_BMP_Image routines. 00005 // 00006 // Copyright 1997-2010 by Easy Software Products. 00007 // Image support by Matthias Melcher, Copyright 2000-2009. 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Library General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Library General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Library General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00022 // USA. 00023 // 00024 // Please report all bugs and problems on the following page: 00025 // 00026 // http://www.fltk.org/str.php 00027 // 00028 // Contents: 00029 // 00030 // Fl_BMP_Image::Fl_BMP_Image() - Load a BMP image file. 00031 // 00032 00033 // 00034 // Include necessary header files... 00035 // 00036 00037 #include <FL/Fl_BMP_Image.H> 00038 #include <FL/fl_utf8.h> 00039 #include <config.h> 00040 #include <stdio.h> 00041 #include <stdlib.h> 00042 00043 00044 // 00045 // BMP definitions... 00046 // 00047 00048 #ifndef BI_RGB 00049 # define BI_RGB 0 // No compression - straight BGR data 00050 # define BI_RLE8 1 // 8-bit run-length compression 00051 # define BI_RLE4 2 // 4-bit run-length compression 00052 # define BI_BITFIELDS 3 // RGB bitmap with RGB masks 00053 #endif // !BI_RGB 00054 00055 00056 // 00057 // Local functions... 00058 // 00059 00060 static int read_long(FILE *fp); 00061 static unsigned short read_word(FILE *fp); 00062 static unsigned int read_dword(FILE *fp); 00070 Fl_BMP_Image::Fl_BMP_Image(const char *bmp) // I - File to read 00071 : Fl_RGB_Image(0,0,0) { 00072 FILE *fp; // File pointer 00073 int info_size, // Size of info header 00074 depth, // Depth of image (bits) 00075 bDepth = 3, // Depth of image (bytes) 00076 compression, // Type of compression 00077 colors_used, // Number of colors used 00078 x, y, // Looping vars 00079 color, // Color of RLE pixel 00080 repcount, // Number of times to repeat 00081 temp, // Temporary color 00082 align, // Alignment bytes 00083 dataSize, // number of bytes in image data set 00084 row_order, // 1 = normal; -1 = flipped row order 00085 start_y, // Beginning Y 00086 end_y; // Ending Y 00087 long offbits; // Offset to image data 00088 uchar bit, // Bit in image 00089 byte; // Byte in image 00090 uchar *ptr; // Pointer into pixels 00091 uchar colormap[256][3];// Colormap 00092 uchar havemask; // Single bit mask follows image data 00093 int use_5_6_5; // Use 5:6:5 for R:G:B channels in 16 bit images 00094 00095 00096 // Open the file... 00097 if ((fp = fl_fopen(bmp, "rb")) == NULL) return; 00098 00099 // Get the header... 00100 byte = (uchar)getc(fp); // Check "BM" sync chars 00101 bit = (uchar)getc(fp); 00102 if (byte != 'B' || bit != 'M') { 00103 fclose(fp); 00104 return; 00105 } 00106 00107 read_dword(fp); // Skip size 00108 read_word(fp); // Skip reserved stuff 00109 read_word(fp); 00110 offbits = (long)read_dword(fp);// Read offset to image data 00111 00112 // Then the bitmap information... 00113 info_size = read_dword(fp); 00114 00115 // printf("offbits = %ld, info_size = %d\n", offbits, info_size); 00116 00117 havemask = 0; 00118 row_order = -1; 00119 use_5_6_5 = 0; 00120 00121 if (info_size < 40) { 00122 // Old Windows/OS2 BMP header... 00123 w(read_word(fp)); 00124 h(read_word(fp)); 00125 read_word(fp); 00126 depth = read_word(fp); 00127 compression = BI_RGB; 00128 colors_used = 0; 00129 00130 repcount = info_size - 12; 00131 } else { 00132 // New BMP header... 00133 w(read_long(fp)); 00134 // If the height is negative, the row order is flipped 00135 temp = read_long(fp); 00136 if (temp < 0) row_order = 1; 00137 h(abs(temp)); 00138 read_word(fp); 00139 depth = read_word(fp); 00140 compression = read_dword(fp); 00141 dataSize = read_dword(fp); 00142 read_long(fp); 00143 read_long(fp); 00144 colors_used = read_dword(fp); 00145 read_dword(fp); 00146 00147 repcount = info_size - 40; 00148 00149 if (!compression && depth>=8 && w()>32/depth) { 00150 int Bpp = depth/8; 00151 int maskSize = (((w()*Bpp+3)&~3)*h()) + (((((w()+7)/8)+3)&~3)*h()); 00152 if (maskSize==2*dataSize) { 00153 havemask = 1; 00154 h(h()/2); 00155 bDepth = 4; 00156 } 00157 } 00158 } 00159 00160 // printf("w() = %d, h() = %d, depth = %d, compression = %d, colors_used = %d, repcount = %d\n", 00161 // w(), h(), depth, compression, colors_used, repcount); 00162 00163 // Skip remaining header bytes... 00164 while (repcount > 0) { 00165 getc(fp); 00166 repcount --; 00167 } 00168 00169 // Check header data... 00170 if (!w() || !h() || !depth) { 00171 fclose(fp); 00172 return; 00173 } 00174 00175 // Get colormap... 00176 if (colors_used == 0 && depth <= 8) 00177 colors_used = 1 << depth; 00178 00179 for (repcount = 0; repcount < colors_used; repcount ++) { 00180 // Read BGR color... 00181 if (fread(colormap[repcount], 1, 3, fp)==0) { /* ignore */ } 00182 00183 // Skip pad byte for new BMP files... 00184 if (info_size > 12) getc(fp); 00185 } 00186 00187 // Read first dword of colormap. It tells us if 5:5:5 or 5:6:5 for 16 bit 00188 if (depth == 16) 00189 use_5_6_5 = (read_dword(fp) == 0xf800); 00190 00191 // Set byte depth for RGBA images 00192 if (depth == 32) 00193 bDepth=4; 00194 00195 // Setup image and buffers... 00196 d(bDepth); 00197 if (offbits) fseek(fp, offbits, SEEK_SET); 00198 00199 array = new uchar[w() * h() * d()]; 00200 alloc_array = 1; 00201 00202 // Read the image data... 00203 color = 0; 00204 repcount = 0; 00205 align = 0; 00206 byte = 0; 00207 temp = 0; 00208 00209 if (row_order < 0) { 00210 start_y = h() - 1; 00211 end_y = -1; 00212 } else { 00213 start_y = 0; 00214 end_y = h(); 00215 } 00216 00217 for (y = start_y; y != end_y; y += row_order) { 00218 ptr = (uchar *)array + y * w() * d(); 00219 00220 switch (depth) 00221 { 00222 case 1 : // Bitmap 00223 for (x = w(), bit = 128; x > 0; x --) { 00224 if (bit == 128) byte = (uchar)getc(fp); 00225 00226 if (byte & bit) { 00227 *ptr++ = colormap[1][2]; 00228 *ptr++ = colormap[1][1]; 00229 *ptr++ = colormap[1][0]; 00230 } else { 00231 *ptr++ = colormap[0][2]; 00232 *ptr++ = colormap[0][1]; 00233 *ptr++ = colormap[0][0]; 00234 } 00235 00236 if (bit > 1) 00237 bit >>= 1; 00238 else 00239 bit = 128; 00240 } 00241 00242 // Read remaining bytes to align to 32 bits... 00243 for (temp = (w() + 7) / 8; temp & 3; temp ++) { 00244 getc(fp); 00245 } 00246 break; 00247 00248 case 4 : // 16-color 00249 for (x = w(), bit = 0xf0; x > 0; x --) { 00250 // Get a new repcount as needed... 00251 if (repcount == 0) { 00252 if (compression != BI_RLE4) { 00253 repcount = 2; 00254 color = -1; 00255 } else { 00256 while (align > 0) { 00257 align --; 00258 getc(fp); 00259 } 00260 00261 if ((repcount = getc(fp)) == 0) { 00262 if ((repcount = getc(fp)) == 0) { 00263 // End of line... 00264 x ++; 00265 continue; 00266 } else if (repcount == 1) { 00267 // End of image... 00268 break; 00269 } else if (repcount == 2) { 00270 // Delta... 00271 repcount = getc(fp) * getc(fp) * w(); 00272 color = 0; 00273 } else { 00274 // Absolute... 00275 color = -1; 00276 align = ((4 - (repcount & 3)) / 2) & 1; 00277 } 00278 } else { 00279 color = getc(fp); 00280 } 00281 } 00282 } 00283 00284 // Get a new color as needed... 00285 repcount --; 00286 00287 // Extract the next pixel... 00288 if (bit == 0xf0) { 00289 // Get the next color byte as needed... 00290 if (color < 0) temp = getc(fp); 00291 else temp = color; 00292 00293 // Copy the color value... 00294 *ptr++ = colormap[(temp >> 4) & 15][2]; 00295 *ptr++ = colormap[(temp >> 4) & 15][1]; 00296 *ptr++ = colormap[(temp >> 4) & 15][0]; 00297 00298 bit = 0x0f; 00299 } else { 00300 bit = 0xf0; 00301 00302 // Copy the color value... 00303 *ptr++ = colormap[temp & 15][2]; 00304 *ptr++ = colormap[temp & 15][1]; 00305 *ptr++ = colormap[temp & 15][0]; 00306 } 00307 00308 } 00309 00310 if (!compression) { 00311 // Read remaining bytes to align to 32 bits... 00312 for (temp = (w() + 1) / 2; temp & 3; temp ++) { 00313 getc(fp); 00314 } 00315 } 00316 break; 00317 00318 case 8 : // 256-color 00319 for (x = w(); x > 0; x --) { 00320 // Get a new repcount as needed... 00321 if (compression != BI_RLE8) { 00322 repcount = 1; 00323 color = -1; 00324 } 00325 00326 if (repcount == 0) { 00327 while (align > 0) { 00328 align --; 00329 getc(fp); 00330 } 00331 00332 if ((repcount = getc(fp)) == 0) { 00333 if ((repcount = getc(fp)) == 0) { 00334 // End of line... 00335 x ++; 00336 continue; 00337 } else if (repcount == 1) { 00338 // End of image... 00339 break; 00340 } else if (repcount == 2) { 00341 // Delta... 00342 repcount = getc(fp) * getc(fp) * w(); 00343 color = 0; 00344 } else { 00345 // Absolute... 00346 color = -1; 00347 align = (2 - (repcount & 1)) & 1; 00348 } 00349 } else { 00350 color = getc(fp); 00351 } 00352 } 00353 00354 // Get a new color as needed... 00355 if (color < 0) temp = getc(fp); 00356 else temp = color; 00357 00358 repcount --; 00359 00360 // Copy the color value... 00361 *ptr++ = colormap[temp][2]; 00362 *ptr++ = colormap[temp][1]; 00363 *ptr++ = colormap[temp][0]; 00364 if (havemask) ptr++; 00365 } 00366 00367 if (!compression) { 00368 // Read remaining bytes to align to 32 bits... 00369 for (temp = w(); temp & 3; temp ++) { 00370 getc(fp); 00371 } 00372 } 00373 break; 00374 00375 case 16 : // 16-bit 5:5:5 or 5:6:5 RGB 00376 for (x = w(); x > 0; x --, ptr += bDepth) { 00377 uchar b = getc(fp), a = getc(fp) ; 00378 if (use_5_6_5) { 00379 ptr[2] = (uchar)(( b << 3 ) & 0xf8); 00380 ptr[1] = (uchar)(((a << 5) & 0xe0) | ((b >> 3) & 0x1c)); 00381 ptr[0] = (uchar)(a & 0xf8); 00382 } else { 00383 ptr[2] = (uchar)((b << 3) & 0xf8); 00384 ptr[1] = (uchar)(((a << 6) & 0xc0) | ((b >> 2) & 0x38)); 00385 ptr[0] = (uchar)((a<<1) & 0xf8); 00386 } 00387 } 00388 00389 // Read remaining bytes to align to 32 bits... 00390 for (temp = w() * 2; temp & 3; temp ++) { 00391 getc(fp); 00392 } 00393 break; 00394 00395 case 24 : // 24-bit RGB 00396 for (x = w(); x > 0; x --, ptr += bDepth) { 00397 ptr[2] = (uchar)getc(fp); 00398 ptr[1] = (uchar)getc(fp); 00399 ptr[0] = (uchar)getc(fp); 00400 } 00401 00402 // Read remaining bytes to align to 32 bits... 00403 for (temp = w() * 3; temp & 3; temp ++) { 00404 getc(fp); 00405 } 00406 break; 00407 00408 case 32 : // 32-bit RGBA 00409 for (x = w(); x > 0; x --, ptr += bDepth) { 00410 ptr[2] = (uchar)getc(fp); 00411 ptr[1] = (uchar)getc(fp); 00412 ptr[0] = (uchar)getc(fp); 00413 ptr[3] = (uchar)getc(fp); 00414 } 00415 break; 00416 } 00417 } 00418 00419 if (havemask) { 00420 for (y = h() - 1; y >= 0; y --) { 00421 ptr = (uchar *)array + y * w() * d() + 3; 00422 for (x = w(), bit = 128; x > 0; x --, ptr+=bDepth) { 00423 if (bit == 128) byte = (uchar)getc(fp); 00424 if (byte & bit) 00425 *ptr = 0; 00426 else 00427 *ptr = 255; 00428 if (bit > 1) 00429 bit >>= 1; 00430 else 00431 bit = 128; 00432 } 00433 // Read remaining bytes to align to 32 bits... 00434 for (temp = (w() + 7) / 8; temp & 3; temp ++) 00435 getc(fp); 00436 } 00437 } 00438 00439 // Close the file and return... 00440 fclose(fp); 00441 } 00442 00443 00444 // 00445 // 'read_word()' - Read a 16-bit unsigned integer. 00446 // 00447 00448 static unsigned short // O - 16-bit unsigned integer 00449 read_word(FILE *fp) { // I - File to read from 00450 unsigned char b0, b1; // Bytes from file 00451 00452 b0 = (uchar)getc(fp); 00453 b1 = (uchar)getc(fp); 00454 00455 return ((b1 << 8) | b0); 00456 } 00457 00458 00459 // 00460 // 'read_dword()' - Read a 32-bit unsigned integer. 00461 // 00462 00463 static unsigned int // O - 32-bit unsigned integer 00464 read_dword(FILE *fp) { // I - File to read from 00465 unsigned char b0, b1, b2, b3; // Bytes from file 00466 00467 b0 = (uchar)getc(fp); 00468 b1 = (uchar)getc(fp); 00469 b2 = (uchar)getc(fp); 00470 b3 = (uchar)getc(fp); 00471 00472 return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0); 00473 } 00474 00475 00476 // 00477 // 'read_long()' - Read a 32-bit signed integer. 00478 // 00479 00480 static int // O - 32-bit signed integer 00481 read_long(FILE *fp) { // I - File to read from 00482 unsigned char b0, b1, b2, b3; // Bytes from file 00483 00484 b0 = (uchar)getc(fp); 00485 b1 = (uchar)getc(fp); 00486 b2 = (uchar)getc(fp); 00487 b3 = (uchar)getc(fp); 00488 00489 return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0); 00490 } 00491 00492 00493 // 00494 // End of "$Id: Fl_BMP_Image.cxx 7903 2010-11-28 21:06:39Z matt $". 00495 //