00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <fstream>
00011
00012 #ifndef MACOSX
00013 #define JPEG_SUPPORT
00014 #define PNG_SUPPORT
00015 #endif
00016
00017 #ifdef MACOSX
00018 #include <unistd.h>
00019 #include "CGBuffer.h"
00020 #ifndef PNG_SUPPORT
00021 #include <Quicktime/ImageCompression.h>
00022 #include <QuickTime/QuickTimeComponents.h>
00023 #endif
00024 #endif
00025
00026 #ifndef _WIN32
00027 #ifndef MACOSX
00028 #include <config.h>
00029 #endif
00030 #endif
00031
00032 #include "image.h"
00033
00034 #ifdef JPEG_SUPPORT
00035
00036 #ifndef PNG_SUPPORT
00037 #include "setjmp.h"
00038 #endif // PNG_SUPPORT
00039
00040 extern "C" {
00041 #ifdef _WIN32
00042 #include "jpeglib.h"
00043 #else
00044 #include <cstdio>
00045 #include <jpeglib.h>
00046 #endif
00047 }
00048
00049 #endif // JPEG_SUPPORT
00050
00051 #ifdef PNG_SUPPORT // PNG_SUPPORT
00052 #ifdef MACOSX
00053 #include "../../macosx/png.h"
00054 #else
00055 #include "png.h"
00056 #endif // MACOSX
00057
00058 #include <celutil/debug.h>
00059 #include <celutil/util.h>
00060 #include <celutil/filetype.h>
00061 #include "gl.h"
00062 #include "glext.h"
00063 #include "celestia.h"
00064
00065 #include <cassert>
00066 #include <iostream>
00067 #include <algorithm>
00068 #include <cmath>
00069
00070 using namespace std;
00071
00072
00073
00074 #ifndef png_jmpbuf
00075 #define png_jmpbuf(png_ptr) png_ptr->jmpbuf
00076 #endif // PNG_SUPPORT
00077
00078
00079 #if PNG_LIBPNG_VER < 10004
00080 #define png_set_palette_to_rgb(p) png_set_expand(p)
00081 #define png_set_gray_1_2_4_to_8(p) png_set_expand(p)
00082 #define png_set_tRNS_to_alpha(p) png_set_expand(p)
00083 #endif // PNG_LIBPNG_VER < 10004
00084
00085 #endif // PNG_SUPPORT
00086
00087
00088 static int formatComponents(int fmt)
00089 {
00090 switch (fmt)
00091 {
00092 case GL_RGBA:
00093 case GL_BGRA_EXT:
00094 return 4;
00095 case GL_RGB:
00096 case GL_BGR_EXT:
00097 return 3;
00098 case GL_LUMINANCE_ALPHA:
00099 case GL_DSDT_NV:
00100 return 2;
00101 case GL_ALPHA:
00102 case GL_LUMINANCE:
00103 return 1;
00104
00105
00106 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
00107 return 3;
00108 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
00109 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
00110 return 4;
00111
00112
00113 default:
00114 return 0;
00115 }
00116 }
00117
00118
00119 static int calcMipLevelSize(int fmt, int w, int h, int mip)
00120 {
00121 w = max(w >> mip, 1);
00122 h = max(h >> mip, 1);
00123
00124 switch (fmt)
00125 {
00126 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
00127
00128 return ((w + 3) / 4) * ((h + 3) / 4) * 8;
00129 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
00130 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
00131
00132 return ((w + 3) / 4) * ((h + 3) / 4) * 16;
00133 default:
00134 return h * w * formatComponents(fmt);
00135 }
00136 }
00137
00138
00139 Image::Image(int fmt, int w, int h, int mips) :
00140 width(w),
00141 height(h),
00142 mipLevels(mips),
00143 format(fmt),
00144 pixels(NULL)
00145 {
00146 components = formatComponents(fmt);
00147 assert(components != 0);
00148
00149 size = 0;
00150 for (int i = 0; i < mipLevels; i++)
00151 size += calcMipLevelSize(fmt, w, h, i);
00152 pixels = new unsigned char[size];
00153 }
00154
00155
00156 Image::~Image()
00157 {
00158 if (pixels != NULL)
00159 delete[] pixels;
00160 }
00161
00162
00163 int Image::getWidth() const
00164 {
00165 return width;
00166 }
00167
00168
00169 int Image::getHeight() const
00170 {
00171 return height;
00172 }
00173
00174
00175 int Image::getMipLevelCount() const
00176 {
00177 return mipLevels;
00178 }
00179
00180
00181 int Image::getSize() const
00182 {
00183 return size;
00184 }
00185
00186
00187 int Image::getFormat() const
00188 {
00189 return format;
00190 }
00191
00192
00193 int Image::getComponents() const
00194 {
00195 return components;
00196 }
00197
00198
00199 unsigned char* Image::getPixels()
00200 {
00201 return pixels;
00202 }
00203
00204
00205 unsigned char* Image::getPixelRow(int mip, int row)
00206 {
00207 int w = max(width >> mip, 1);
00208 int h = max(height >> mip, 1);
00209 if (mip >= mipLevels || row >= h)
00210 return NULL;
00211
00212
00213 if (isCompressed())
00214 return NULL;
00215
00216 return getMipLevel(mip) + row * w * components;
00217 }
00218
00219
00220 unsigned char* Image::getPixelRow(int row)
00221 {
00222 return getPixelRow(0, row);
00223 }
00224
00225
00226 unsigned char* Image::getMipLevel(int mip)
00227 {
00228 if (mip >= mipLevels)
00229 return NULL;
00230
00231 int offset = 0;
00232 for (int i = 0; i < mip; i++)
00233 offset += calcMipLevelSize(format, width, height, i);
00234
00235 return pixels + offset;
00236 }
00237
00238
00239 int Image::getMipLevelSize(int mip) const
00240 {
00241 if (mip >= mipLevels)
00242 return 0;
00243 else
00244 return calcMipLevelSize(format, width, height, mip);
00245 }
00246
00247
00248 bool Image::isCompressed() const
00249 {
00250 switch (format)
00251 {
00252 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
00253 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
00254 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
00255 return true;
00256 default:
00257 return false;
00258 }
00259 }
00260
00261
00262 bool Image::hasAlpha() const
00263 {
00264 switch (format)
00265 {
00266 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
00267 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
00268 case GL_RGBA:
00269 case GL_BGRA_EXT:
00270 case GL_LUMINANCE_ALPHA:
00271 case GL_ALPHA:
00272 return true;
00273 default:
00274 return false;
00275 }
00276 }
00277
00278
00279
00280
00281
00282
00283 Image* Image::computeNormalMap(float scale, bool wrap) const
00284 {
00285
00286
00287 if (isCompressed())
00288 return NULL;
00289
00290 Image* normalMap = new Image(GL_RGBA, width, height);
00291 if (normalMap == NULL)
00292 return NULL;
00293
00294 unsigned char* nmPixels = normalMap->getPixels();
00295
00296
00297 for (int i = 0; i < height; i++)
00298 {
00299 for (int j = 0; j < width; j++)
00300 {
00301 int i0 = i;
00302 int j0 = j;
00303 int i1 = i - 1;
00304 int j1 = j - 1;
00305 if (i1 < 0)
00306 {
00307 if (wrap)
00308 {
00309 i1 = height - 1;
00310 }
00311 else
00312 {
00313 i0++;
00314 i1++;
00315 }
00316 }
00317 if (j1 < 0)
00318 {
00319 if (wrap)
00320 {
00321 j1 = width - 1;
00322 }
00323 else
00324 {
00325 j0++;
00326 j1++;
00327 }
00328 }
00329
00330 int h00 = (int) pixels[(i0 * width + j0) * components];
00331 int h10 = (int) pixels[(i0 * width + j1) * components];
00332 int h01 = (int) pixels[(i1 * width + j0) * components];
00333
00334 float dx = (float) (h10 - h00) * (1.0f / 255.0f) * scale;
00335 float dy = (float) (h01 - h00) * (1.0f / 255.0f) * scale;
00336
00337 float mag = (float) sqrt(dx * dx + dy * dy + 1.0f);
00338 float rmag = 1.0f / mag;
00339
00340 int n = (i * width + j) * 4;
00341 nmPixels[n] = (unsigned char) (128 + 127 * dx * rmag);
00342 nmPixels[n + 1] = (unsigned char) (128 + 127 * dy * rmag);
00343 nmPixels[n + 2] = (unsigned char) (128 + 127 * rmag);
00344 nmPixels[n + 3] = 255;
00345 }
00346 }
00347
00348 return normalMap;
00349 }
00350
00351
00352 Image* LoadImageFromFile(const string& filename)
00353 {
00354 ContentType type = DetermineFileType(filename);
00355 Image* img = NULL;
00356
00357 clog << _("Loading image from file ") << filename << '\n';
00358
00359 switch (type)
00360 {
00361 case Content_JPEG:
00362 img = LoadJPEGImage(filename);
00363 break;
00364 case Content_BMP:
00365 img = LoadBMPImage(filename);
00366 break;
00367 case Content_PNG:
00368 img = LoadPNGImage(filename);
00369 break;
00370 case Content_DDS:
00371 img = LoadDDSImage(filename);
00372 break;
00373 default:
00374 clog << filename << _(": unrecognized or unsupported image file type.\n");
00375 break;
00376 }
00377
00378 return img;
00379 }
00380
00381
00382
00383
00384
00385 #ifdef JPEG_SUPPORT
00386
00387 struct my_error_mgr
00388 {
00389 struct jpeg_error_mgr pub;
00390 jmp_buf setjmp_buffer;
00391 };
00392
00393 typedef struct my_error_mgr *my_error_ptr;
00394
00395 METHODDEF(void) my_error_exit(j_common_ptr cinfo)
00396 {
00397
00398 my_error_ptr myerr = (my_error_ptr) cinfo->err;
00399
00400
00401
00402 (*cinfo->err->output_message) (cinfo);
00403
00404
00405 longjmp(myerr->setjmp_buffer, 1);
00406 }
00407 #endif // JPEG_SUPPORT
00408
00409
00410 Image* LoadJPEGImage(const string& filename, int channels)
00411 {
00412 #ifdef JPEG_SUPPORT
00413 Image* img = NULL;
00414
00415
00416
00417 struct jpeg_decompress_struct cinfo;
00418
00419
00420
00421
00422 struct my_error_mgr jerr;
00423
00424 JSAMPARRAY buffer;
00425 int row_stride;
00426 long cont;
00427
00428
00429
00430
00431
00432
00433 FILE *in;
00434 in = fopen(filename.c_str(), "rb");
00435 if (in == NULL)
00436 return NULL;
00437
00438
00439
00440 cinfo.err = jpeg_std_error(&jerr.pub);
00441 jerr.pub.error_exit = my_error_exit;
00442
00443 if (setjmp(jerr.setjmp_buffer))
00444 {
00445
00446
00447 jpeg_destroy_decompress(&cinfo);
00448 fclose(in);
00449 if (img != NULL)
00450 delete img;
00451
00452 return NULL;
00453 }
00454
00455
00456 jpeg_create_decompress(&cinfo);
00457
00458
00459 jpeg_stdio_src(&cinfo, in);
00460
00461
00462 (void) jpeg_read_header(&cinfo, TRUE);
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 (void) jpeg_start_decompress(&cinfo);
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 row_stride = cinfo.output_width * cinfo.output_components;
00486
00487 buffer = (*cinfo.mem->alloc_sarray)
00488 ((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1);
00489
00490
00491
00492
00493
00494
00495
00496 int format = GL_RGB;
00497 if (cinfo.output_components == 1)
00498 format = GL_LUMINANCE;
00499
00500 img = new Image(format, cinfo.image_width, cinfo.image_height);
00501
00502
00503 cont = 0;
00504 while (cinfo.output_scanline < cinfo.output_height)
00505 {
00506
00507
00508
00509 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
00510
00511
00512
00513 memcpy(img->getPixelRow(cont), buffer[0], row_stride);
00514 cont++;
00515 }
00516
00517
00518
00519 (void) jpeg_finish_decompress(&cinfo);
00520
00521
00522
00523
00524
00525
00526 jpeg_destroy_decompress(&cinfo);
00527
00528
00529
00530
00531
00532
00533 fclose(in);
00534
00535
00536
00537
00538 return img;
00539
00540 #elif MACOSX
00541
00542 Image* img = NULL;
00543 CGBuffer* cgJpegImage;
00544 size_t img_w, img_h, img_d;
00545
00546 cgJpegImage = new CGBuffer(filename.c_str());
00547 if (cgJpegImage == NULL) {
00548 char tempcwd[2048];
00549 getcwd(tempcwd, sizeof(tempcwd));
00550 DPRINTF(0, "CGBuffer :: Error opening JPEG image file %s/%s\n", tempcwd, filename.c_str());
00551 delete cgJpegImage;
00552 return NULL;
00553 }
00554
00555 if (!cgJpegImage->LoadJPEG()) {
00556 char tempcwd[2048];
00557 getcwd(tempcwd, sizeof(tempcwd));
00558 DPRINTF(0, "CGBuffer :: Error loading JPEG image file %s/%s\n", tempcwd, filename.c_str());
00559 delete cgJpegImage;
00560 return NULL;
00561 }
00562
00563 cgJpegImage->Render();
00564
00565 img_w = (size_t) cgJpegImage->image_size.width;
00566 img_h = (size_t) cgJpegImage->image_size.height;
00567 img_d = (size_t) ((cgJpegImage->image_depth == 8) ? 1 : 4);
00568
00569
00570
00571 #ifdef MACOSX_ALPHA_JPEGS
00572 int format = (img_d == 1) ? GL_LUMINANCE : GL_RGBA;
00573 #else
00574 int format = (img_d == 1) ? GL_LUMINANCE : GL_RGB;
00575 #endif
00576 img = new Image(format, img_w, img_h);
00577 if (img == NULL || img->getPixels() == NULL) {
00578 DPRINTF(0, "Could not create image\n");
00579 delete cgJpegImage;
00580 return NULL;
00581 }
00582
00583 unsigned char* bout = (unsigned char*) img->getPixels();
00584 unsigned char* bin = (unsigned char*) cgJpegImage->buffer->data;
00585 unsigned int bcount = img_w * img_h * img_d;
00586 unsigned int i = 0;
00587 bin += bcount+(img_w*img_d);
00588 for (i=0; i<bcount; ++i)
00589 {
00590
00591 if ( (i % (img_w * img_d)) == 0 ) bin -= 2*(img_w * img_d);
00592
00593 #ifndef MACOSX_ALPHA_JPEGS
00594 if (( (img_d != 1) && !((i&3)^3) ))
00595 {
00596 ++bin;
00597 } else
00598 #endif // !MACOSX_ALPHA_JPEGS
00599
00600 *bout++ = *bin++;
00601 }
00602 delete cgJpegImage;
00603 return img;
00604
00605 #else
00606 return NULL;
00607 #endif // JPEG_SUPPORT
00608 }
00609
00610
00611 #ifdef PNG_SUPPORT
00612 void PNGReadData(png_structp png_ptr, png_bytep data, png_size_t length)
00613 {
00614 FILE* fp = (FILE*) png_get_io_ptr(png_ptr);
00615 fread((void*) data, 1, length, fp);
00616 }
00617 #endif
00618
00619
00620 Image* LoadPNGImage(const string& filename)
00621 {
00622 #ifndef PNG_SUPPORT
00623 return NULL;
00624 #else
00625 char header[8];
00626 png_structp png_ptr;
00627 png_infop info_ptr;
00628 png_uint_32 width, height;
00629 int bit_depth, color_type, interlace_type;
00630 FILE* fp = NULL;
00631 Image* img = NULL;
00632 png_bytep* row_pointers = NULL;
00633
00634 fp = fopen(filename.c_str(), "rb");
00635 if (fp == NULL)
00636 {
00637 clog << _("Error opening image file ") << filename << '\n';
00638 return NULL;
00639 }
00640
00641 fread(header, 1, sizeof(header), fp);
00642 if (png_sig_cmp((unsigned char*) header, 0, sizeof(header)))
00643 {
00644 clog << _("Error: ") << filename << _(" is not a PNG file.\n");
00645 fclose(fp);
00646 return NULL;
00647 }
00648
00649 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
00650 NULL, NULL, NULL);
00651 if (png_ptr == NULL)
00652 {
00653 fclose(fp);
00654 return NULL;
00655 }
00656
00657 info_ptr = png_create_info_struct(png_ptr);
00658 if (info_ptr == NULL)
00659 {
00660 fclose(fp);
00661 png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
00662 return NULL;
00663 }
00664
00665 if (setjmp(png_jmpbuf(png_ptr)))
00666 {
00667 fclose(fp);
00668 if (img != NULL)
00669 delete img;
00670 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
00671 clog << _("Error reading PNG image file ") << filename << '\n';
00672 return NULL;
00673 }
00674
00675
00676 png_set_read_fn(png_ptr, (void*) fp, PNGReadData);
00677 png_set_sig_bytes(png_ptr, sizeof(header));
00678
00679 png_read_info(png_ptr, info_ptr);
00680
00681 png_get_IHDR(png_ptr, info_ptr,
00682 &width, &height, &bit_depth,
00683 &color_type, &interlace_type,
00684 NULL, NULL);
00685
00686 GLenum glformat = GL_RGB;
00687 switch (color_type)
00688 {
00689 case PNG_COLOR_TYPE_GRAY:
00690 glformat = GL_LUMINANCE;
00691 break;
00692 case PNG_COLOR_TYPE_GRAY_ALPHA:
00693 glformat = GL_LUMINANCE_ALPHA;
00694 break;
00695 case PNG_COLOR_TYPE_RGB:
00696 glformat = GL_RGB;
00697 break;
00698 case PNG_COLOR_TYPE_PALETTE:
00699 case PNG_COLOR_TYPE_RGB_ALPHA:
00700 glformat = GL_RGBA;
00701 break;
00702 default:
00703
00704 break;
00705 }
00706
00707 img = new Image(glformat, width, height);
00708 if (img == NULL)
00709 {
00710 fclose(fp);
00711 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
00712 return NULL;
00713 }
00714
00715
00716 if (color_type == PNG_COLOR_TYPE_PALETTE)
00717 {
00718 png_set_palette_to_rgb(png_ptr);
00719 }
00720
00721 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
00722 {
00723 png_set_gray_1_2_4_to_8(png_ptr);
00724 }
00725
00726 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00727 {
00728 png_set_tRNS_to_alpha(png_ptr);
00729 }
00730
00731
00732
00733 if (bit_depth == 16)
00734 png_set_strip_16(png_ptr);
00735 else if (bit_depth < 8)
00736 png_set_packing(png_ptr);
00737
00738 row_pointers = new png_bytep[height];
00739 for (unsigned int i = 0; i < height; i++)
00740 row_pointers[i] = (png_bytep) img->getPixelRow(i);
00741
00742 png_read_image(png_ptr, row_pointers);
00743
00744 delete[] row_pointers;
00745
00746 png_read_end(png_ptr, NULL);
00747 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
00748
00749 fclose(fp);
00750
00751 return img;
00752 #endif
00753 }
00754
00755
00756
00757
00758 typedef struct
00759 {
00760 unsigned char b;
00761 unsigned char m;
00762 unsigned int size;
00763 unsigned int reserved;
00764 unsigned int offset;
00765 } BMPFileHeader;
00766
00767 typedef struct
00768 {
00769 unsigned int size;
00770 int width;
00771 int height;
00772 unsigned short planes;
00773 unsigned short bpp;
00774 unsigned int compression;
00775 unsigned int imageSize;
00776 int widthPPM;
00777 int heightPPM;
00778 unsigned int colorsUsed;
00779 unsigned int colorsImportant;
00780 } BMPImageHeader;
00781
00782
00783 static int readInt(ifstream& in)
00784 {
00785 unsigned char b[4];
00786 in.read(reinterpret_cast<char*>(b), 4);
00787 return ((int) b[3] << 24) + ((int) b[2] << 16)
00788 + ((int) b[1] << 8) + (int) b[0];
00789 }
00790
00791 static short readShort(ifstream& in)
00792 {
00793 unsigned char b[2];
00794 in.read(reinterpret_cast<char*>(b), 2);
00795 return ((short) b[1] << 8) + (short) b[0];
00796 }
00797
00798
00799 static Image* LoadBMPImage(ifstream& in)
00800 {
00801 BMPFileHeader fileHeader;
00802 BMPImageHeader imageHeader;
00803 unsigned char* pixels;
00804
00805 in >> fileHeader.b;
00806 in >> fileHeader.m;
00807 fileHeader.size = readInt(in);
00808 fileHeader.reserved = readInt(in);
00809 fileHeader.offset = readInt(in);
00810
00811 if (fileHeader.b != 'B' || fileHeader.m != 'M')
00812 return NULL;
00813
00814 imageHeader.size = readInt(in);
00815 imageHeader.width = readInt(in);
00816 imageHeader.height = readInt(in);
00817 imageHeader.planes = readShort(in);
00818 imageHeader.bpp = readShort(in);
00819 imageHeader.compression = readInt(in);
00820 imageHeader.imageSize = readInt(in);
00821 imageHeader.widthPPM = readInt(in);
00822 imageHeader.heightPPM = readInt(in);
00823 imageHeader.colorsUsed = readInt(in);
00824 imageHeader.colorsImportant = readInt(in);
00825
00826 if (imageHeader.width <= 0 || imageHeader.height <= 0)
00827 return NULL;
00828
00829
00830 if (imageHeader.compression != 0)
00831 return NULL;
00832
00833 if (imageHeader.bpp != 8 && imageHeader.bpp != 24 && imageHeader.bpp != 32)
00834 return NULL;
00835
00836 unsigned char* palette = NULL;
00837 if (imageHeader.bpp == 8)
00838 {
00839 printf("Reading %d color palette\n", imageHeader.colorsUsed);
00840 palette = new unsigned char[imageHeader.colorsUsed * 4];
00841 in.read(reinterpret_cast<char*>(palette), imageHeader.colorsUsed * 4);
00842 }
00843
00844 in.seekg(fileHeader.offset, ios::beg);
00845
00846 unsigned int bytesPerRow =
00847 (imageHeader.width * imageHeader.bpp / 8 + 1) & ~1;
00848 unsigned int imageBytes = bytesPerRow * imageHeader.height;
00849
00850
00851 pixels = new unsigned char[imageBytes];
00852 in.read(reinterpret_cast<char*>(pixels), imageBytes);
00853
00854
00855
00856 Image* img = new Image(GL_RGB, imageHeader.width, imageHeader.height);
00857 if (img == NULL)
00858 {
00859 delete[] pixels;
00860 return NULL;
00861 }
00862
00863
00864 for (int y = 0; y < imageHeader.height; y++)
00865 {
00866 unsigned char* src = &pixels[y * bytesPerRow];
00867 unsigned char* dst = img->getPixelRow(y);
00868
00869 switch (imageHeader.bpp)
00870 {
00871 case 8:
00872 {
00873 for (int x = 0; x < imageHeader.width; x++)
00874 {
00875 unsigned char* color = palette + (*src << 2);
00876 dst[0] = color[2];
00877 dst[1] = color[1];
00878 dst[2] = color[0];
00879 src++;
00880 dst += 3;
00881 }
00882 }
00883 break;
00884
00885 case 24:
00886 {
00887 for (int x = 0; x < imageHeader.width; x++)
00888 {
00889 dst[0] = src[2];
00890 dst[1] = src[1];
00891 dst[2] = src[0];
00892 src += 3;
00893 dst += 3;
00894 }
00895 }
00896 break;
00897
00898 case 32:
00899 {
00900 for (int x = 0; x < imageHeader.width; x++)
00901 {
00902 dst[0] = src[2];
00903 dst[1] = src[1];
00904 dst[2] = src[0];
00905 src += 4;
00906 dst += 3;
00907 }
00908 }
00909 break;
00910 }
00911 }
00912
00913 delete[] pixels;
00914
00915 return img;
00916 }
00917
00918
00919 Image* LoadBMPImage(const string& filename)
00920 {
00921 ifstream bmpFile(filename.c_str(), ios::in | ios::binary);
00922
00923 if (bmpFile.good())
00924 {
00925 Image* img = LoadBMPImage(bmpFile);
00926 bmpFile.close();
00927 return img;
00928 }
00929 else
00930 {
00931 return NULL;
00932 }
00933 }