00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043
00044 #include "OSGConfig.h"
00045
00046 #include "OSGBMPImageFileType.h"
00047 #include <OSGLog.h>
00048
00049 #include <iostream>
00050
00051 OSG_BEGIN_NAMESPACE
00052
00053
00066 static UInt32 parseUInt32(char *&ptr)
00067 {
00068 UInt32 result =
00069 (static_cast<UInt32>(static_cast<UInt8>(ptr[0])) << 0) |
00070 (static_cast<UInt32>(static_cast<UInt8>(ptr[1])) << 8) |
00071 (static_cast<UInt32>(static_cast<UInt8>(ptr[2])) << 16) |
00072 (static_cast<UInt32>(static_cast<UInt8>(ptr[3])) << 24);
00073 ptr += 4;
00074 return result;
00075 }
00076
00077 static UInt16 parseUInt16(char *&ptr)
00078 {
00079 UInt16 result =
00080 (static_cast<UInt32>(static_cast<UInt8>(ptr[0])) << 0) |
00081 (static_cast<UInt32>(static_cast<UInt8>(ptr[1])) << 8);
00082 ptr +=2;
00083 return result;
00084 }
00085
00086 typedef struct
00087 {
00088 Int8 bfType[2];
00089 UInt32 bfSize;
00090 UInt16 bfReserved1;
00091 UInt16 bfReserved2;
00092 UInt32 bfOffBits;
00093 }
00094 BITMAPFILEHEADER;
00095
00096 typedef struct
00097 {
00098 UInt32 biSize;
00099 UInt32 biWidth;
00100 Int32 biHeight;
00101 UInt16 biPlanes;
00102 UInt16 biBitCount;
00103 UInt32 biCompression;
00104 UInt32 biSizeImage;
00105 UInt32 biXPelsPerMeter;
00106 UInt32 biYPelsPerMeter;
00107 UInt32 biClrUsed;
00108 UInt32 biClrImportant;
00109 UInt32 redMask;
00110 UInt32 greenMask;
00111 UInt32 blueMask;
00112 UInt32 alphaMask;
00113 }
00114 BITMAPINFOHEADER;
00115
00116 typedef struct
00117 {
00118 UInt8 r, g, b;
00119 }
00120 RGB;
00121
00122 static bool readBitmapFileHeader(std::istream &is, BITMAPFILEHEADER &header)
00123 {
00124
00125 char buffer[14];
00126 is.read(buffer, 14);
00127 if (is.gcount() != 14)
00128 return false;
00129
00130
00131 char *ptr = buffer;
00132 memcpy(header.bfType, ptr, 2);
00133 ptr += 2;
00134 header.bfSize = parseUInt32(ptr);
00135 header.bfReserved1 = parseUInt16(ptr);
00136 header.bfReserved2 = parseUInt16(ptr);
00137 header.bfOffBits = parseUInt32(ptr);
00138
00139
00140 if (memcmp(header.bfType, "BM", 2) != 0)
00141 return false;
00142
00143 return true;
00144 }
00145
00146 static bool readBitmapInfoHeader(std::istream &is, BITMAPINFOHEADER &infoHeader)
00147 {
00148
00149 char buffer[56];
00150 is.read(buffer, 4);
00151 if (is.gcount() != 4)
00152 return false;
00153 char *ptr = buffer;
00154 infoHeader.biSize = parseUInt32(ptr);
00155
00156
00157 if (infoHeader.biSize >= 40)
00158 {
00159
00160 int size = infoHeader.biSize >= 56 ? 56 - 4 : 40 - 4;
00161 is.read(&(buffer[4]), size);
00162 if (is.gcount() != size)
00163 return false;
00164
00165 infoHeader.biWidth = parseUInt32(ptr);
00166 infoHeader.biHeight = parseUInt32(ptr);
00167 infoHeader.biPlanes = parseUInt16(ptr);
00168 infoHeader.biBitCount = parseUInt16(ptr);
00169 infoHeader.biCompression = parseUInt32(ptr);
00170 infoHeader.biSizeImage = parseUInt32(ptr);
00171 infoHeader.biXPelsPerMeter = parseUInt32(ptr);
00172 infoHeader.biYPelsPerMeter = parseUInt32(ptr);
00173 infoHeader.biClrUsed = parseUInt32(ptr);
00174 infoHeader.biClrImportant = parseUInt32(ptr);
00175
00176 if ((infoHeader.biSize >= 56) && (infoHeader.biCompression == 3 ))
00177 {
00178 infoHeader.redMask = parseUInt32(ptr);
00179 infoHeader.greenMask = parseUInt32(ptr);
00180 infoHeader.blueMask = parseUInt32(ptr);
00181 infoHeader.alphaMask = parseUInt32(ptr);
00182 }
00183 else
00184 infoHeader.alphaMask = 0;
00185
00186 is.ignore(infoHeader.biSize - size - 4);
00187 }
00188 else if (infoHeader.biSize >= 12)
00189 {
00190
00191 is.read(&(buffer[4]), 12 - 4);
00192 if (is.gcount() != 12 - 4)
00193 return false;
00194
00195 infoHeader.biWidth = parseUInt16(ptr);
00196 infoHeader.biHeight = parseUInt16(ptr);
00197 infoHeader.biPlanes = parseUInt16(ptr);
00198 infoHeader.biBitCount = parseUInt16(ptr);
00199 infoHeader.biCompression = 0;
00200 infoHeader.biSizeImage = 0;
00201 infoHeader.biXPelsPerMeter = 0;
00202 infoHeader.biYPelsPerMeter = 0;
00203 infoHeader.biClrUsed = 0;
00204 infoHeader.biClrImportant = 0;
00205
00206 is.ignore(infoHeader.biSize - 12);
00207 }
00208 else
00209 return false;
00210
00211
00212 if ((infoHeader.biBitCount != 1) &&
00213 (infoHeader.biBitCount != 4) &&
00214 (infoHeader.biBitCount != 8) &&
00215 (infoHeader.biBitCount != 16) &&
00216 (infoHeader.biBitCount != 24) &&
00217 (infoHeader.biBitCount != 32))
00218 return false;
00219 if (infoHeader.biPlanes != 1)
00220 return false;
00221 if ((infoHeader.biBitCount == 1) && (infoHeader.biCompression != 0 ))
00222 return false;
00223 if ((infoHeader.biBitCount == 4) && (infoHeader.biCompression != 0 ) && (infoHeader.biCompression != 2 ))
00224 return false;
00225 if ((infoHeader.biBitCount == 8) && (infoHeader.biCompression != 0 ) && (infoHeader.biCompression != 1 ))
00226 return false;
00227 if ((infoHeader.biBitCount == 16) && (infoHeader.biCompression != 0 ) && (infoHeader.biCompression != 3 ))
00228 return false;
00229 if ((infoHeader.biBitCount == 24) && (infoHeader.biCompression != 0 ))
00230 return false;
00231 if ((infoHeader.biBitCount == 32) && (infoHeader.biCompression != 0 ) && (infoHeader.biCompression != 3 ))
00232 return false;
00233
00234 if (infoHeader.biSize < 56)
00235 {
00236 if (infoHeader.biCompression == 3 )
00237 {
00238 is.read(buffer, 12);
00239 if (is.gcount() != 12)
00240 return false;
00241 ptr = buffer;
00242 infoHeader.redMask = parseUInt32(ptr);
00243 infoHeader.greenMask = parseUInt32(ptr);
00244 infoHeader.blueMask = parseUInt32(ptr);
00245 infoHeader.alphaMask = 0;
00246 infoHeader.biSize += 12;
00247 }
00248 else if (infoHeader.biBitCount == 16)
00249 {
00250 infoHeader.redMask = 0x7c00;
00251 infoHeader.greenMask = 0x03e0;
00252 infoHeader.blueMask = 0x001f;
00253 infoHeader.alphaMask = 0;
00254 }
00255 else if (infoHeader.biBitCount == 32)
00256 {
00257 infoHeader.redMask = 0x00ff0000;
00258 infoHeader.greenMask = 0x0000ff00;
00259 infoHeader.blueMask = 0x000000ff;
00260 infoHeader.alphaMask = 0xff000000;
00261 }
00262 }
00263
00264 #if 0
00265 std::cout << "infoHeader.biSize = " << infoHeader.biSize << std::endl;
00266 std::cout << "infoHeader.biWidth = " << infoHeader.biWidth << std::endl;
00267 std::cout << "infoHeader.biHeight = " << infoHeader.biHeight << std::endl;
00268 std::cout << "infoHeader.biPlanes = " << infoHeader.biPlanes << std::endl;
00269 std::cout << "infoHeader.biBitCount = " << infoHeader.biBitCount << std::endl;
00270 std::cout << "infoHeader.biCompression = " << infoHeader.biCompression << std::endl;
00271 #endif
00272
00273 return true;
00274 }
00275
00276 static bool readColorMap(std::istream &is, const BITMAPFILEHEADER &fileHeader, const BITMAPINFOHEADER &infoHeader, RGB colorMap[256])
00277 {
00278 if (infoHeader.biBitCount <= 8)
00279 {
00280 UInt32 nCols = 1 << infoHeader.biBitCount;
00281 if (infoHeader.biClrUsed > 0)
00282 {
00283 if (infoHeader.biClrUsed > nCols)
00284 return false;
00285 nCols = infoHeader.biClrUsed;
00286 }
00287 int bytesPerColor = (infoHeader.biSize < 40) || (infoHeader.biSize + 14 + 4 * nCols > fileHeader.bfOffBits)
00288 ? 3 : 4;
00289 char buffer[256 * 4];
00290 is.read(buffer, nCols * bytesPerColor);
00291 if (static_cast<UInt32>(is.gcount()) != nCols * bytesPerColor)
00292 return false;
00293 char *ptr = buffer;
00294 for (UInt32 i = 0; i < nCols; ++i)
00295 {
00296 colorMap[i].r = ptr[2];
00297 colorMap[i].g = ptr[1];
00298 colorMap[i].b = ptr[0];
00299 ptr += bytesPerColor;
00300 }
00301 }
00302
00303 return true;
00304 }
00305
00306 static bool parseUncompressedPaletteImage(std::istream &is, const BITMAPINFOHEADER &infoHeader, const RGB colorMap[256], ImagePtr &image)
00307 {
00308 unsigned long mask = (1 << infoHeader.biBitCount) - 1;
00309 int height;
00310 long bytesPerLine;
00311 UChar8 *data;
00312 if (infoHeader.biHeight >= 0)
00313 {
00314 height = infoHeader.biHeight;
00315 bytesPerLine = infoHeader.biWidth * 3;
00316 data = image->getData();
00317 }
00318 else
00319 {
00320 height = -infoHeader.biHeight;
00321 bytesPerLine = infoHeader.biWidth * -3;
00322 data = image->getData() + image->getSize() + bytesPerLine;
00323 }
00324
00325 for (int y = 0; y < height; ++y)
00326 {
00327 int shift = 0;
00328 unsigned long bits;
00329 UChar8 *ptr = data;
00330 for (unsigned int x = 0; x < infoHeader.biWidth; ++x)
00331 {
00332 if (shift == 0)
00333 {
00334 char buffer[4];
00335 is.read(buffer, 4);
00336 if (is.gcount() != 4)
00337 return false;
00338 bits = (static_cast<UInt32>(static_cast<UInt8>(buffer[0])) << 24) |
00339 (static_cast<UInt32>(static_cast<UInt8>(buffer[1])) << 16) |
00340 (static_cast<UInt32>(static_cast<UInt8>(buffer[2])) << 8) |
00341 (static_cast<UInt32>(static_cast<UInt8>(buffer[3])) << 0);
00342 shift = 32 - infoHeader.biBitCount;
00343 }
00344 else
00345 shift -= infoHeader.biBitCount;
00346 unsigned long index = (bits >> shift) & mask;
00347 *ptr++ = colorMap[index].r;
00348 *ptr++ = colorMap[index].g;
00349 *ptr++ = colorMap[index].b;
00350 }
00351 data += bytesPerLine;
00352 }
00353
00354 return true;
00355 }
00356
00357 static bool parseRLEImage(std::istream &is, const BITMAPINFOHEADER &infoHeader, const RGB colorMap[256], ImagePtr &image)
00358 {
00359 unsigned int height;
00360 long bytesPerLine;
00361 UChar8 *data;
00362 if (infoHeader.biHeight >= 0)
00363 {
00364 height = infoHeader.biHeight;
00365 bytesPerLine = infoHeader.biWidth * 3;
00366 data = image->getData();
00367 }
00368 else
00369 {
00370 height = -infoHeader.biHeight;
00371 bytesPerLine = infoHeader.biWidth * -3;
00372 data = image->getData() + image->getSize() + bytesPerLine;
00373 }
00374
00375 UChar8 *ptr = data;
00376 unsigned int x = 0;
00377 for (unsigned int y = 0; y < height; )
00378 {
00379 int c1 = is.get();
00380 int c2 = is.get();
00381 if ((c1 == EOF) || (c2 == EOF))
00382 return false;
00383 if (c1 == 0)
00384 {
00385 switch (c2)
00386 {
00387 case 0:
00388 x = 0;
00389 ++y;
00390 data += bytesPerLine;
00391 ptr = data;
00392 break;
00393 case 1:
00394 y = height;
00395 break;
00396 case 2:
00397 {
00398 int xOffset = is.get();
00399 int yOffset = is.get();
00400 if ((xOffset == EOF) || (yOffset == EOF))
00401 return false;
00402 x += xOffset;
00403 y += yOffset;
00404 if ((x >= infoHeader.biWidth) || (y >= height))
00405 return false;
00406 data += bytesPerLine * yOffset;
00407 ptr += bytesPerLine * yOffset + 3 * xOffset;
00408 }
00409 break;
00410 default:
00411 if (infoHeader.biWidth - x < static_cast<unsigned int>(c2))
00412 c2 = infoHeader.biWidth - x;
00413 x += c2;
00414 if (infoHeader.biBitCount == 4)
00415 {
00416 int n = c2;
00417 for (int i = 0; i < n; ++i)
00418 {
00419 int index;
00420 switch (i & 3)
00421 {
00422 case 0:
00423 c1 = is.get();
00424 c2 = is.get();
00425 if ((c1 == EOF) || (c2 == EOF))
00426 return false;
00427 index = c1 >> 4;
00428 break;
00429 case 1:
00430 index = c1 & 0xf;
00431 break;
00432 case 2:
00433 index = c2 >> 4;
00434 break;
00435 case 3:
00436 index = c2 & 0xf;
00437 break;
00438 default:
00439 index = 0;
00440 break;
00441 }
00442 *ptr++ = colorMap[index].r;
00443 *ptr++ = colorMap[index].g;
00444 *ptr++ = colorMap[index].b;
00445 }
00446 }
00447 else
00448 for (int i = 0; i < c2; ++i)
00449 {
00450 int index;
00451 if ((i & 1) == 0)
00452 {
00453 index = is.get();
00454 c1 = is.get();
00455 if ((index == EOF) || (c1 == EOF))
00456 return false;
00457 }
00458 else
00459 index = c1;
00460 *ptr++ = colorMap[index].r;
00461 *ptr++ = colorMap[index].g;
00462 *ptr++ = colorMap[index].b;
00463 }
00464 break;
00465 }
00466 }
00467 else
00468 {
00469 if (infoHeader.biWidth - x < static_cast<unsigned int>(c1))
00470 c1 = infoHeader.biWidth - x;
00471 x += c1;
00472 if (infoHeader.biBitCount == 4)
00473 for (int i = 0; i < c1; ++i)
00474 {
00475 int index = (i & 1) == 0 ? c2 >> 4 : c2 & 0xf;
00476 *ptr++ = colorMap[index].r;
00477 *ptr++ = colorMap[index].g;
00478 *ptr++ = colorMap[index].b;
00479 }
00480 else
00481 for (int i = 0; i < c1; ++i)
00482 {
00483 *ptr++ = colorMap[c2].r;
00484 *ptr++ = colorMap[c2].g;
00485 *ptr++ = colorMap[c2].b;
00486 }
00487 }
00488 }
00489
00490 return true;
00491 }
00492
00493 static int calcShift(UInt32 mask)
00494 {
00495 if (mask == 0)
00496 return 0;
00497 int shift = 0;
00498 while (mask > 255)
00499 {
00500 ++shift;
00501 mask >>= 1;
00502 }
00503 return shift;
00504 }
00505
00506 static bool parseTrueColorImage(std::istream &is, const BITMAPINFOHEADER &infoHeader, ImagePtr &image)
00507 {
00508 int redShift = calcShift(infoHeader.redMask);
00509 int redScale = infoHeader.redMask == 0 ? 0 : 255 / (infoHeader.redMask >> redShift);
00510 int greenShift = calcShift(infoHeader.greenMask);
00511 int greenScale = infoHeader.greenMask == 0 ? 0 : 255 / (infoHeader.greenMask >> greenShift);
00512 int blueShift = calcShift(infoHeader.blueMask);
00513 int blueScale = infoHeader.blueMask == 0 ? 0 : 255 / (infoHeader.blueMask >> blueShift);
00514 int alphaShift = calcShift(infoHeader.alphaMask);
00515 int alphaScale = infoHeader.alphaMask == 0 ? 0 : 255 / (infoHeader.alphaMask >> alphaShift);
00516
00517 int height;
00518 long bytesPerLine = infoHeader.biWidth * (infoHeader.alphaMask != 0 ? 4 : 3);
00519 UChar8 *data;
00520 if (infoHeader.biHeight >= 0)
00521 {
00522 height = infoHeader.biHeight;
00523 data = image->getData();
00524 }
00525 else
00526 {
00527 height = -infoHeader.biHeight;
00528 bytesPerLine = -bytesPerLine;
00529 data = image->getData() + image->getSize() + bytesPerLine;
00530 }
00531
00532 for (int y = 0; y < height; ++y)
00533 {
00534 int shift = 32;
00535 unsigned long bits;
00536 UChar8 *ptr = data;
00537 for (unsigned int x = 0; x < infoHeader.biWidth; ++x)
00538 {
00539 if (shift >= 32)
00540 {
00541 char buffer[4];
00542 is.read(buffer, 4);
00543 if (is.gcount() != 4)
00544 return false;
00545 bits = (static_cast<UInt32>(static_cast<UInt8>(buffer[0])) << 0) |
00546 (static_cast<UInt32>(static_cast<UInt8>(buffer[1])) << 8) |
00547 (static_cast<UInt32>(static_cast<UInt8>(buffer[2])) << 16) |
00548 (static_cast<UInt32>(static_cast<UInt8>(buffer[3])) << 24);
00549 shift = 0;
00550 }
00551 unsigned long color = bits >> shift;
00552 *ptr++ = static_cast<UChar8>(((color & infoHeader.redMask) >> redShift) * redScale);
00553 *ptr++ = static_cast<UChar8>(((color & infoHeader.greenMask) >> greenShift) * greenScale);
00554 *ptr++ = static_cast<UChar8>(((color & infoHeader.blueMask) >> blueShift) * blueScale);
00555 if (infoHeader.alphaMask != 0)
00556 *ptr++ = static_cast<UChar8>(((color & infoHeader.alphaMask) >> alphaShift) * alphaScale);
00557 shift += infoHeader.biBitCount;
00558 }
00559 data += bytesPerLine;
00560 }
00561
00562 return true;
00563 }
00564
00565 static bool parse24bitImage(std::istream &is, const BITMAPINFOHEADER &infoHeader, ImagePtr &image)
00566 {
00567 int height;
00568 long bytesPerLine;
00569 UChar8 *data;
00570 if (infoHeader.biHeight >= 0)
00571 {
00572 height = infoHeader.biHeight;
00573 bytesPerLine = infoHeader.biWidth * 3;
00574 data = image->getData();
00575 }
00576 else
00577 {
00578 height = -infoHeader.biHeight;
00579 bytesPerLine = infoHeader.biWidth * -3;
00580 data = image->getData() + image->getSize() + bytesPerLine;
00581 }
00582 int padding = (infoHeader.biWidth * 3) & 3;
00583 if (padding != 0)
00584 padding = 4 - padding;
00585
00586 for (int y = 0; y < height; ++y)
00587 {
00588 UChar8 *ptr = data;
00589 for (unsigned int x = 0; x < infoHeader.biWidth; ++x)
00590 {
00591 char buffer[3];
00592 is.read(buffer, 3);
00593 if (is.gcount() != 3)
00594 return false;
00595 *ptr++ = buffer[2];
00596 *ptr++ = buffer[1];
00597 *ptr++ = buffer[0];
00598 }
00599 is.ignore(padding);
00600 data += bytesPerLine;
00601 }
00602
00603 return true;
00604 }
00605
00606
00607
00608
00609
00610 static void u_short_int_write(unsigned short int u_short_int_val,
00611 std::ostream &os);
00612
00613
00614 static bool _bmp_byte_swap = true;
00615
00616 static void long_int_write ( long int long_int_val, std::ostream &os)
00617 {
00618 long int temp;
00619 unsigned short int u_short_int_val_hi;
00620 unsigned short int u_short_int_val_lo;
00621
00622 temp = long_int_val / 65536;
00623 if(temp < 0)
00624 temp = temp + 65536;
00625
00626 u_short_int_val_hi = ( unsigned short ) temp;
00627
00628 temp = long_int_val % 65536;
00629 if(temp < 0)
00630 temp = temp + 65536;
00631
00632 u_short_int_val_lo = ( unsigned short ) temp;
00633
00634 if(_bmp_byte_swap)
00635 {
00636 u_short_int_write ( u_short_int_val_lo, os);
00637 u_short_int_write ( u_short_int_val_hi, os);
00638 }
00639 else
00640 {
00641 u_short_int_write ( u_short_int_val_hi, os);
00642 u_short_int_write ( u_short_int_val_lo, os);
00643 }
00644 return;
00645 }
00646
00647 static void u_long_int_write(unsigned long int u_long_int_val,
00648 std::ostream &os)
00649 {
00650 unsigned short int u_short_int_val_hi;
00651 unsigned short int u_short_int_val_lo;
00652
00653 u_short_int_val_hi = ( unsigned short ) ( u_long_int_val / 65536 );
00654 u_short_int_val_lo = ( unsigned short ) ( u_long_int_val % 65536 );
00655
00656 if(_bmp_byte_swap)
00657 {
00658 u_short_int_write ( u_short_int_val_lo, os);
00659 u_short_int_write ( u_short_int_val_hi, os);
00660 }
00661 else
00662 {
00663 u_short_int_write ( u_short_int_val_hi, os);
00664 u_short_int_write ( u_short_int_val_lo, os);
00665 }
00666
00667 return;
00668 }
00669
00670 static void u_short_int_write(unsigned short int u_short_int_val,
00671 std::ostream &os)
00672 {
00673 unsigned char chi;
00674 unsigned char clo;
00675
00676 chi = ( unsigned char ) ( u_short_int_val / 256 );
00677 clo = ( unsigned char ) ( u_short_int_val % 256 );
00678
00679 if(_bmp_byte_swap)
00680 os << clo << chi;
00681 else
00682 os << chi << clo;
00683
00684 return;
00685 }
00686
00687 static void bmp_header1_write(std::ostream &os, unsigned short int filetype,
00688 unsigned long int filesize, unsigned short int reserved1,
00689 unsigned short int reserved2, unsigned long int bitmapoffset)
00690 {
00691 u_short_int_write(filetype, os);
00692 u_long_int_write(filesize, os);
00693 u_short_int_write(reserved1, os);
00694 u_short_int_write(reserved2, os);
00695 u_long_int_write(bitmapoffset, os);
00696 return;
00697 }
00698
00699 static void bmp_header2_write(std::ostream &os, unsigned long int size,
00700 unsigned long int width, long int height,
00701 unsigned short int planes, unsigned short int bitsperpixel,
00702 unsigned long int compression, unsigned long int sizeofbitmap,
00703 unsigned long int horzresolution, unsigned long int vertresolution,
00704 unsigned long int colorsused, unsigned long int colorsimportant)
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748 {
00749 u_long_int_write(size, os);
00750 u_long_int_write(width, os);
00751 long_int_write(height, os);
00752 u_short_int_write(planes, os);
00753 u_short_int_write(bitsperpixel, os);
00754 u_long_int_write(compression, os);
00755 u_long_int_write(sizeofbitmap, os);
00756 u_long_int_write(horzresolution, os);
00757 u_long_int_write(vertresolution, os);
00758 u_long_int_write(colorsused, os);
00759 u_long_int_write(colorsimportant, os);
00760 return;
00761 }
00762
00763 static void bmp_24_data_write(std::ostream &os, unsigned long int width,
00764 long int height, unsigned char *data)
00765 {
00766 int i;
00767 unsigned char *indexb;
00768 unsigned char *indexg;
00769 unsigned char *indexr;
00770 int j;
00771 int padding;
00772
00773
00774 padding = ( 4 - ( ( 3 * width ) % 4 ) ) % 4;
00775
00776 for(j = 0; j < abs ( height ); ++j)
00777 {
00778 for(i = 0; i < width; ++i)
00779 {
00780 os << *(data + 2);
00781 os << *(data + 1);
00782 os << *(data + 0);
00783 data += 3;
00784 }
00785
00786 for(i = 0; i < padding; ++i)
00787 {
00788 os << 0;
00789 }
00790 }
00791 return;
00792 }
00793
00794
00795
00796
00797 static const Char8 *suffixArray[] = {
00798 "bmp", "dib", "rle"
00799 };
00800
00801 BMPImageFileType BMPImageFileType::_the("image/bmp",
00802 suffixArray, sizeof(suffixArray),
00803 OSG_READ_SUPPORTED |
00804 OSG_WRITE_SUPPORTED);
00805
00806
00810 BMPImageFileType& BMPImageFileType::the (void)
00811 {
00812 return _the;
00813 }
00814
00815
00820 bool BMPImageFileType::read(ImagePtr &image, std::istream &is,
00821 const std::string &mimetype)
00822 {
00823
00824 BITMAPFILEHEADER fileHeader;
00825 if (readBitmapFileHeader(is, fileHeader) == false)
00826 return false;
00827
00828
00829 BITMAPINFOHEADER infoHeader;
00830 if (readBitmapInfoHeader(is, infoHeader) == false)
00831 return false;
00832
00833
00834 RGB colorMap[256];
00835 if (readColorMap(is, fileHeader, infoHeader, colorMap) == false)
00836 return false;
00837
00838
00839 UInt32 pixelFormat = infoHeader.alphaMask != 0 ? Image::OSG_RGBA_PF: Image::OSG_RGB_PF;
00840 Int32 height = infoHeader.biHeight >= 0 ? infoHeader.biHeight : -infoHeader.biHeight;
00841 image->set(pixelFormat, infoHeader.biWidth, height);
00842 switch (infoHeader.biBitCount)
00843 {
00844 case 1:
00845 case 4:
00846 case 8:
00847 if (infoHeader.biCompression == 0 )
00848 {
00849 if (parseUncompressedPaletteImage(is, infoHeader, colorMap, image) == false)
00850 return false;
00851 }
00852 else
00853 {
00854 if (parseRLEImage(is, infoHeader, colorMap, image) == false)
00855 return false;
00856 }
00857 break;
00858 case 16:
00859 case 32:
00860 if (parseTrueColorImage(is, infoHeader, image) == false)
00861 return false;
00862 break;
00863 case 24:
00864 if (parse24bitImage(is, infoHeader, image) == false)
00865 return false;
00866 break;
00867 default:
00868 return false;
00869 }
00870
00871 return true;
00872 }
00873
00874
00879 bool BMPImageFileType::write(const ImagePtr &image, std::ostream &os, const std::string &mimetype)
00880 {
00881 if(image == NullFC)
00882 return false;
00883
00884 int bpp = image->getBpp();
00885 if(bpp != 3)
00886 {
00887 FWARNING(("Writing of bmp files is only supported for 24 bit RGB images!\n"));
00888 return false;
00889 }
00890
00891 if (!os.good())
00892 return false;
00893
00894 int width = image->getWidth();
00895 int height = image->getHeight();
00896 unsigned char *data = (unsigned char *) image->getData();
00897
00898 unsigned long int bitmapoffset;
00899 unsigned short int bitsperpixel;
00900 unsigned long int colorsimportant;
00901 unsigned long int colorsused;
00902 unsigned long int compression;
00903 unsigned long int filesize;
00904 unsigned short int filetype;
00905 unsigned long int horzresolution;
00906 int padding;
00907 unsigned short int planes;
00908 unsigned short int reserved1 = 0;
00909 unsigned short int reserved2 = 0;
00910 unsigned long int size = 40;
00911 unsigned long int sizeofbitmap;
00912 unsigned long int vertresolution;
00913
00914
00915 if(_bmp_byte_swap)
00916 filetype = 'M' * 256 + 'B';
00917 else
00918 filetype = 'B' * 256 + 'M';
00919
00920
00921 padding = ( 4 - ( ( 3 * width ) % 4 ) ) % 4;
00922
00923 filesize = 54 + ( ( 3 * width ) + padding ) * abs ( height );
00924 bitmapoffset = 54;
00925
00926 bmp_header1_write(os, filetype, filesize, reserved1,
00927 reserved2, bitmapoffset );
00928
00929
00930
00931 planes = 1;
00932 bitsperpixel = 24;
00933 compression = 0;
00934 sizeofbitmap = 0;
00935 horzresolution = 0;
00936 vertresolution = 0;
00937 colorsused = 0;
00938 colorsimportant = 0;
00939
00940 bmp_header2_write(os, size, width, height, planes, bitsperpixel,
00941 compression, sizeofbitmap, horzresolution, vertresolution,
00942 colorsused, colorsimportant);
00943
00944
00945 bmp_24_data_write(os, width, height, data);
00946
00947 return true;
00948 }
00949
00950
00956 std::string BMPImageFileType::determineMimetypeFromStream(std::istream &is)
00957 {
00958 char filecode[2];
00959 is.read(filecode, 2);
00960 is.seekg(-2, std::ios::cur);
00961 return strncmp(filecode, "BM", 2) == 0 ?
00962 std::string(getMimeType()) : std::string();
00963 }
00964
00965
00969 BMPImageFileType::BMPImageFileType(const Char8 *mimeType,
00970 const Char8 *suffixArray[],
00971 UInt16 suffixByteCount,
00972 UInt32 flags) :
00973 ImageFileType(mimeType,suffixArray, suffixByteCount, flags)
00974 {}
00975
00976
00980 BMPImageFileType::~BMPImageFileType(void) {}
00981
00982
00983 OSG_END_NAMESPACE