00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <GL/glew.h>
00019 #include "Image.h"
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 ImageBuffer::ImageBuffer (const string &filename)
00035 : _filename (filename), _data (NULL), _length (0)
00036 {
00037
00038 std::ifstream ifs (filename.c_str(), std::ios::in | std::ios::binary);
00039
00040 if (ifs.fail ())
00041 throw ImageException ("Couldn't open file", filename);
00042
00043
00044 ifs.seekg (0, std::ios::end);
00045 _length = ifs.tellg ();
00046 ifs.seekg (0, std::ios::beg);
00047
00048 try
00049 {
00050
00051 _data = new GLubyte[_length];
00052
00053
00054 ifs.read (reinterpret_cast<char *> (_data), _length);
00055 ifs.close ();
00056 }
00057 catch (...)
00058 {
00059 delete [] _data;
00060 throw;
00061 }
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071 ImageBuffer::~ImageBuffer ()
00072 {
00073 delete [] _data;
00074 _data = NULL;
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 Image::Image (const string &name, GLsizei w, GLsizei h, GLint numMipMaps,
00094 GLenum format, GLint components, const GLubyte *pixels,
00095 bool stdCoordSystem)
00096 : _width (w), _height (h), _numMipmaps (numMipMaps),
00097 _format (format), _components (components), _name (name),
00098 _standardCoordSystem (stdCoordSystem)
00099 {
00100
00101
00102
00103 long size = _width * _height * _components;
00104
00105 if (size <= 0)
00106 throw std::invalid_argument
00107 ("Image::Image: Invalid width, height or component value");
00108
00109 if (!pixels)
00110 throw std::invalid_argument
00111 ("Image::Image: Invalid pixel data source");
00112
00113
00114 _pixels = new GLubyte[size];
00115
00116
00117 memcpy (_pixels, pixels, size);
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 Image::~Image ()
00129 {
00130 delete [] _pixels;
00131 _pixels = NULL;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141 bool
00142 Image::isPowerOfTwo () const
00143 {
00144 GLsizei m;
00145 for (m = 1; m < _width; m *= 2)
00146 ;
00147
00148 if (m != _width)
00149 return false;
00150
00151 for (m = 1; m < _height; m *= 2)
00152 ;
00153
00154 if (m != _height)
00155 return false;
00156
00157 return true;
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 int ImageTGA::rgbaTable[4] = { 2, 1, 0, 3 };
00169 int ImageTGA::bgraTable[4] = { 0, 1, 2, 3 };
00170
00171
00172
00173
00174
00175
00176
00177
00178 ImageTGA::ImageTGA (const ImageBuffer &ibuff)
00179 : _header (NULL)
00180 {
00181 const GLubyte *colormap = NULL;
00182 const GLubyte *data_ptr;
00183
00184 try
00185 {
00186 _name = ibuff.filename ();
00187 data_ptr = ibuff.data ();
00188 _standardCoordSystem = true;
00189
00190
00191 _header = reinterpret_cast<const TGA_Header *>(data_ptr);
00192 data_ptr += sizeof (TGA_Header) + _header->id_lenght;
00193
00194
00195 getTextureInfo ();
00196
00197
00198 _pixels = new GLubyte[_width * _height * _components];
00199
00200
00201 if (_header->colormap_type)
00202 {
00203
00204 colormap = data_ptr;
00205 data_ptr += _header->cm_length * (_header->cm_size >> 3);
00206 }
00207
00208
00209 switch (_header->image_type)
00210 {
00211 case 0:
00212
00213 break;
00214
00215 case 1:
00216
00217 readTGA8bits (data_ptr, colormap);
00218 break;
00219
00220 case 2:
00221
00222 switch (_header->pixel_depth)
00223 {
00224 case 16:
00225 readTGA16bits (data_ptr);
00226 break;
00227
00228 case 24:
00229 readTGA24bits (data_ptr);
00230 break;
00231
00232 case 32:
00233 readTGA32bits (data_ptr);
00234 break;
00235 }
00236
00237 break;
00238
00239 case 3:
00240
00241 if (_header->pixel_depth == 8)
00242 readTGAgray8bits (data_ptr);
00243 else
00244 readTGAgray16bits (data_ptr);
00245
00246 break;
00247
00248 case 9:
00249
00250 readTGA8bitsRLE (data_ptr, colormap);
00251 break;
00252
00253 case 10:
00254
00255 switch (_header->pixel_depth)
00256 {
00257 case 16:
00258 readTGA16bitsRLE (data_ptr);
00259 break;
00260
00261 case 24:
00262 readTGA24bitsRLE (data_ptr);
00263 break;
00264
00265 case 32:
00266 readTGA32bitsRLE (data_ptr);
00267 break;
00268 }
00269
00270 break;
00271
00272 case 11:
00273
00274 if (_header->pixel_depth == 8)
00275 readTGAgray8bitsRLE (data_ptr);
00276 else
00277 readTGAgray16bitsRLE (data_ptr);
00278
00279 break;
00280
00281 default:
00282
00283 throw ImageException ("Unknown TGA image type", _name);
00284 }
00285 }
00286 catch (...)
00287 {
00288 delete [] _pixels;
00289 throw;
00290 }
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300 void
00301 ImageTGA::getTextureInfo ()
00302 {
00303 _width = _header->width;
00304 _height = _header->height;
00305
00306 switch (_header->image_type)
00307 {
00308 case 3:
00309 case 11:
00310 {
00311 if (_header->pixel_depth == 8)
00312 {
00313 _format = GL_LUMINANCE;
00314 _components = 1;
00315 }
00316 else
00317 {
00318 _format = GL_LUMINANCE_ALPHA;
00319 _components = 2;
00320 }
00321
00322 break;
00323 }
00324
00325 case 1:
00326 case 2:
00327 case 9:
00328 case 10:
00329 {
00330
00331 if (_header->pixel_depth <= 24)
00332 {
00333 _format = GLEW_EXT_bgra ? GL_BGR : GL_RGB;
00334 _components = 3;
00335 }
00336 else
00337 {
00338 _format = GLEW_EXT_bgra ? GL_BGRA : GL_RGBA;
00339 _components = 4;
00340 }
00341
00342 break;
00343 }
00344 }
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354 void
00355 ImageTGA::readTGA8bits (const GLubyte *data, const GLubyte *colormap)
00356 {
00357 const GLubyte *pData = data;
00358 int *compTable = GLEW_EXT_bgra ? bgraTable : rgbaTable;
00359
00360 for (int i = 0; i < _width * _height; ++i)
00361 {
00362
00363 GLubyte color = *(pData++);
00364
00365
00366 _pixels[(i * 3) + compTable[0]] = colormap[(color * 3) + 0];
00367 _pixels[(i * 3) + compTable[1]] = colormap[(color * 3) + 1];
00368 _pixels[(i * 3) + compTable[2]] = colormap[(color * 3) + 2];
00369 }
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379 void
00380 ImageTGA::readTGA16bits (const GLubyte *data)
00381 {
00382 const GLubyte *pData = data;
00383 int *compTable = GLEW_EXT_bgra ? bgraTable : rgbaTable;
00384
00385 for (int i = 0; i < _width * _height; ++i, pData += 2)
00386 {
00387
00388 unsigned short color = pData[0] + (pData[1] << 8);
00389
00390
00391 _pixels[(i * 3) + compTable[2]] = (((color & 0x7C00) >> 10) << 3);
00392 _pixels[(i * 3) + compTable[1]] = (((color & 0x03E0) >> 5) << 3);
00393 _pixels[(i * 3) + compTable[0]] = (((color & 0x001F) >> 0) << 3);
00394 }
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404 void
00405 ImageTGA::readTGA24bits (const GLubyte *data)
00406 {
00407 if (GLEW_EXT_bgra)
00408 {
00409 memcpy (_pixels, data, _width * _height * 3);
00410 }
00411 else
00412 {
00413 const GLubyte *pData = data;
00414
00415 for (int i = 0; i < _width * _height; ++i)
00416 {
00417
00418 _pixels[(i * 3) + rgbaTable[0]] = *(pData++);
00419 _pixels[(i * 3) + rgbaTable[1]] = *(pData++);
00420 _pixels[(i * 3) + rgbaTable[2]] = *(pData++);
00421 }
00422 }
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432 void
00433 ImageTGA::readTGA32bits (const GLubyte *data)
00434 {
00435 if (GLEW_EXT_bgra)
00436 {
00437 memcpy (_pixels, data, _width * _height * 4);
00438 }
00439 else
00440 {
00441 const GLubyte *pData = data;
00442
00443 for (int i = 0; i < _width * _height; ++i)
00444 {
00445
00446 _pixels[(i * 4) + rgbaTable[0]] = *(pData++);
00447 _pixels[(i * 4) + rgbaTable[1]] = *(pData++);
00448 _pixels[(i * 4) + rgbaTable[2]] = *(pData++);
00449 _pixels[(i * 4) + rgbaTable[3]] = *(pData++);
00450 }
00451 }
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461 void
00462 ImageTGA::readTGAgray8bits (const GLubyte *data)
00463 {
00464 memcpy (_pixels, data, _width * _height);
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474 void
00475 ImageTGA::readTGAgray16bits (const GLubyte *data)
00476 {
00477 memcpy (_pixels, data, _width * _height * 2);
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487 void
00488 ImageTGA::readTGA8bitsRLE (const GLubyte *data, const GLubyte *colormap)
00489 {
00490 GLubyte *ptr = _pixels;
00491 const GLubyte *pData = data;
00492 int *compTable = GLEW_EXT_bgra ? bgraTable : rgbaTable;
00493
00494 while (ptr < _pixels + (_width * _height) * 3)
00495 {
00496
00497 GLubyte packet_header = *(pData++);
00498 int size = 1 + (packet_header & 0x7f);
00499
00500 if (packet_header & 0x80)
00501 {
00502
00503 GLubyte color = *(pData++);
00504
00505 for (int i = 0; i < size; ++i, ptr += 3)
00506 {
00507 ptr[0] = colormap[(color * 3) + compTable[0]];
00508 ptr[1] = colormap[(color * 3) + compTable[1]];
00509 ptr[2] = colormap[(color * 3) + compTable[2]];
00510 }
00511 }
00512 else
00513 {
00514
00515 for (int i = 0; i < size; ++i, ptr += 3)
00516 {
00517 GLubyte color = *(pData++);
00518
00519 ptr[0] = colormap[(color * 3) + compTable[0]];
00520 ptr[1] = colormap[(color * 3) + compTable[1]];
00521 ptr[2] = colormap[(color * 3) + compTable[2]];
00522 }
00523 }
00524 }
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534 void
00535 ImageTGA::readTGA16bitsRLE (const GLubyte *data)
00536 {
00537 const GLubyte *pData = data;
00538 GLubyte *ptr = _pixels;
00539 int *compTable = GLEW_EXT_bgra ? bgraTable : rgbaTable;
00540
00541 while (ptr < _pixels + (_width * _height) * 3)
00542 {
00543
00544 GLubyte packet_header = *(pData++);
00545 int size = 1 + (packet_header & 0x7f);
00546
00547 if (packet_header & 0x80)
00548 {
00549
00550 unsigned short color = pData[0] + (pData[1] << 8);
00551 pData += 2;
00552
00553 for (int i = 0; i < size; ++i, ptr += 3)
00554 {
00555 ptr[compTable[2]] = (((color & 0x7C00) >> 10) << 3);
00556 ptr[compTable[1]] = (((color & 0x03E0) >> 5) << 3);
00557 ptr[compTable[0]] = (((color & 0x001F) >> 0) << 3);
00558 }
00559 }
00560 else
00561 {
00562
00563 for (int i = 0; i < size; ++i, ptr += 3)
00564 {
00565 unsigned short color = pData[0] + (pData[1] << 8);
00566 pData += 2;
00567
00568 ptr[compTable[2]] = (((color & 0x7C00) >> 10) << 3);
00569 ptr[compTable[1]] = (((color & 0x03E0) >> 5) << 3);
00570 ptr[compTable[0]] = (((color & 0x001F) >> 0) << 3);
00571 }
00572 }
00573 }
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583 void
00584 ImageTGA::readTGA24bitsRLE (const GLubyte *data)
00585 {
00586 const GLubyte *pData = data;
00587 GLubyte *ptr = _pixels;
00588 int *compTable = GLEW_EXT_bgra ? bgraTable : rgbaTable;
00589
00590 while (ptr < _pixels + (_width * _height) * 3)
00591 {
00592
00593 GLubyte packet_header = *(pData++);
00594 int size = 1 + (packet_header & 0x7f);
00595
00596 if (packet_header & 0x80)
00597 {
00598
00599 for (int i = 0; i < size; ++i, ptr += 3)
00600 {
00601 ptr[0] = pData[compTable[0]];
00602 ptr[1] = pData[compTable[1]];
00603 ptr[2] = pData[compTable[2]];
00604 }
00605
00606 pData += 3;
00607 }
00608 else
00609 {
00610
00611 for (int i = 0; i < size; ++i, ptr += 3)
00612 {
00613 ptr[0] = pData[compTable[0]];
00614 ptr[1] = pData[compTable[1]];
00615 ptr[2] = pData[compTable[2]];
00616 pData += 3;
00617 }
00618 }
00619 }
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629 void
00630 ImageTGA::readTGA32bitsRLE (const GLubyte *data)
00631 {
00632 const GLubyte *pData = data;
00633 GLubyte *ptr = _pixels;
00634 int *compTable = GLEW_EXT_bgra ? bgraTable : rgbaTable;
00635
00636 while (ptr < _pixels + (_width * _height) * 4)
00637 {
00638
00639 GLubyte packet_header = *(pData++);
00640 int size = 1 + (packet_header & 0x7f);
00641
00642 if (packet_header & 0x80)
00643 {
00644
00645 for (int i = 0; i < size; ++i, ptr += 4)
00646 {
00647 ptr[0] = pData[compTable[0]];
00648 ptr[1] = pData[compTable[1]];
00649 ptr[2] = pData[compTable[2]];
00650 ptr[3] = pData[compTable[3]];
00651 }
00652
00653 pData += 4;
00654 }
00655 else
00656 {
00657
00658 for (int i = 0; i < size; ++i, ptr += 4)
00659 {
00660 ptr[0] = pData[compTable[0]];
00661 ptr[1] = pData[compTable[1]];
00662 ptr[2] = pData[compTable[2]];
00663 ptr[3] = pData[compTable[3]];
00664 pData += 4;
00665 }
00666 }
00667 }
00668 }
00669
00670
00671
00672
00673
00674
00675
00676
00677 void
00678 ImageTGA::readTGAgray8bitsRLE (const GLubyte *data)
00679 {
00680 const GLubyte *pData = data;
00681 GLubyte *ptr = _pixels;
00682
00683 while (ptr < _pixels + (_width * _height))
00684 {
00685
00686 GLubyte packet_header = *(pData++);
00687 int size = 1 + (packet_header & 0x7f);
00688
00689 if (packet_header & 0x80)
00690 {
00691
00692 GLubyte color = *(pData++);
00693
00694 memset (ptr, color, size);
00695 ptr += size;
00696 }
00697 else
00698 {
00699
00700 memcpy (ptr, pData, size);
00701 ptr += size;
00702 pData += size;
00703 }
00704 }
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714 void
00715 ImageTGA::readTGAgray16bitsRLE (const GLubyte *data)
00716 {
00717 const GLubyte *pData = data;
00718 GLubyte *ptr = _pixels;
00719
00720 while (ptr < _pixels + (_width * _height) * 2)
00721 {
00722
00723 GLubyte packet_header = *(pData++);
00724 int size = 1 + (packet_header & 0x7f);
00725
00726 if (packet_header & 0x80)
00727 {
00728
00729 GLubyte color = *(pData++);
00730 GLubyte alpha = *(pData++);
00731
00732 for (int i = 0; i < size; ++i, ptr += 2)
00733 {
00734 ptr[0] = color;
00735 ptr[1] = alpha;
00736 }
00737 }
00738 else
00739 {
00740
00741 memcpy (ptr, pData, size * 2);
00742 ptr += size * 2;
00743 pData += size * 2;
00744 }
00745 }
00746 }
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 ImageJPEG::ImageJPEG (const ImageBuffer &ibuff)
00762 {
00763 jpeg_decompress_struct cinfo;
00764 my_error_mgr jerr;
00765 jpeg_source_mgr jsrc;
00766 JSAMPROW j;
00767
00768 try
00769 {
00770 _name = ibuff.filename ();
00771 _standardCoordSystem = true;
00772
00773
00774 jpeg_create_decompress (&cinfo);
00775 cinfo.err = jpeg_std_error (&jerr.pub);
00776 cinfo.src = &jsrc;
00777
00778
00779 jerr.pub.error_exit = errorExit_callback;
00780 jerr.pub.output_message = outputMessage_callback;
00781
00782 if (setjmp (jerr.setjmp_buffer))
00783 throw ImageException (jerr.errorMsg, _name);
00784
00785
00786 jsrc.next_input_byte = ibuff.data ();
00787 jsrc.bytes_in_buffer = ibuff.length ();
00788
00789 jsrc.init_source = initSource_callback;
00790 jsrc.fill_input_buffer = fillInputBuffer_callback;
00791 jsrc.skip_input_data = skipInputData_callback;
00792 jsrc.resync_to_restart = jpeg_resync_to_restart;
00793 jsrc.term_source = termSource_callback;
00794
00795
00796 jpeg_read_header (&cinfo, TRUE);
00797 jpeg_start_decompress (&cinfo);
00798
00799
00800 _width = cinfo.image_width;
00801 _height = cinfo.image_height;
00802 _components = cinfo.num_components;
00803 _format = (cinfo.num_components == 1) ? GL_LUMINANCE : GL_RGB;
00804 _pixels = new GLubyte[_width * _height * _components];
00805
00806
00807 for (int i = 0; i < _height; ++i)
00808 {
00809
00810 j = (_pixels + ((_height - (i + 1)) * _width * _components));
00811 jpeg_read_scanlines (&cinfo, &j, 1);
00812 }
00813
00814
00815 jpeg_finish_decompress (&cinfo);
00816 jpeg_destroy_decompress (&cinfo);
00817 }
00818 catch (...)
00819 {
00820 delete [] _pixels;
00821 jpeg_destroy_decompress (&cinfo);
00822
00823 throw;
00824 }
00825 }
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 void
00838 ImageJPEG::initSource_callback (j_decompress_ptr cinfo)
00839 {
00840
00841 }
00842
00843
00844 boolean
00845 ImageJPEG::fillInputBuffer_callback (j_decompress_ptr cinfo)
00846 {
00847 JOCTET eoi_buffer[2] = { 0xFF, JPEG_EOI };
00848 struct jpeg_source_mgr *jsrc = cinfo->src;
00849
00850
00851 jsrc->next_input_byte = eoi_buffer;
00852 jsrc->bytes_in_buffer = 2;
00853
00854 return TRUE;
00855 }
00856
00857
00858 void
00859 ImageJPEG::skipInputData_callback (j_decompress_ptr cinfo, long num_bytes)
00860 {
00861 struct jpeg_source_mgr *jsrc = cinfo->src;
00862
00863 if (num_bytes > 0)
00864 {
00865 while (num_bytes > static_cast<long>(jsrc->bytes_in_buffer))
00866 {
00867 num_bytes -= static_cast<long>(jsrc->bytes_in_buffer);
00868 fillInputBuffer_callback (cinfo);
00869 }
00870
00871 jsrc->next_input_byte += num_bytes;
00872 jsrc->bytes_in_buffer -= num_bytes;
00873 }
00874 }
00875
00876
00877 void
00878 ImageJPEG::termSource_callback (j_decompress_ptr cinfo)
00879 {
00880
00881 }
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 void
00892 ImageJPEG::errorExit_callback (j_common_ptr cinfo)
00893 {
00894 my_error_ptr jerr = reinterpret_cast<my_error_ptr>(cinfo->err);
00895
00896
00897 char message[JMSG_LENGTH_MAX];
00898 (*cinfo->err->format_message) (cinfo, message);
00899 jerr->errorMsg.assign (message);
00900
00901
00902 longjmp (jerr->setjmp_buffer, 1);
00903 }
00904
00905
00906 void
00907 ImageJPEG::outputMessage_callback (j_common_ptr cinfo)
00908 {
00909 my_error_ptr jerr = reinterpret_cast<my_error_ptr>(cinfo->err);
00910
00911
00912 char message[JMSG_LENGTH_MAX];
00913 (*cinfo->err->format_message) (cinfo, message);
00914 jerr->errorMsg.assign (message);
00915
00916
00917 std::cerr << "libjpeg: " << jerr->errorMsg << std::endl;
00918 }