00001 #include "TextureUtils.h"
00002 #include "glwxOpenGL.h"
00003
00004 #ifdef GLWX_PNG_SUPPORT
00005 #include "glpng.h"
00006 #endif
00007
00008
00009
00010
00011
00012
00013 Texture::Texture(GLuint target_) : IOXMLObject("Texture")
00014 {
00015 currUnit = 0;
00016 target = target_;
00017 height = 0;
00018 width = 0;
00019 depth = 0;
00020 id = 0;
00021 }
00022
00023 Texture::Texture(const Texture & texture) : IOXMLObject("Texture")
00024 {
00025 currUnit = 0;
00026 target = GL_TEXTURE_2D;
00027 height = 0;
00028 width = 0;
00029 depth = 0;
00030 id = 0;
00031 this->operator=(texture);
00032 }
00033
00034 Texture &Texture::operator= (const Texture & copy)
00035 {
00036 if(this != ©)
00037 {
00038 setID(copy.id);
00039
00040 currUnit = copy.currUnit;
00041 target = copy.target;
00042 height = copy.height;
00043 width = copy.width;
00044 depth = copy.depth;
00045 }
00046 return *this;
00047 }
00048
00049 bool Texture::checkForRepeat(const char* string)
00050 {
00051 TextureInfo *textureInfo = NULL;
00052
00053 if(textureInfo = TexturesManager::getTextureInfo(string))
00054 setID(textureInfo->getMedia());
00055
00056 return (textureInfo != NULL);
00057 }
00058
00059 bool Texture::finalizeLoading(const char* string)
00060 {
00061 if(!id)
00062 return Logger::writeErrorLog(std::string("Failed to load texture <") + string + ">");
00063 else
00064 {
00065 TextureInfo *textureInfo = new TextureInfo(string, id);
00066 TexturesManager::addTextureInfo(textureInfo);
00067 }
00068 return true;
00069 }
00070
00071 const bool Texture::activate(GLuint unit)
00072 {
00073 if(!id)
00074 return false;
00075
00076 currUnit = unit;
00077
00078
00079 glEnable(target);
00080 glBindTexture(target, id);
00081
00082 return true;
00083 }
00084
00085 void Texture::copyCurrentBuffer(int newTarget)
00086 {
00087 if(!id)
00088 return;
00089
00090 newTarget = (newTarget == -1) ? target : newTarget;
00091 activate();
00092 glCopyTexSubImage2D(newTarget, 0, 0, 0, 0, 0, width, height);
00093 deactivate();
00094 }
00095
00096 const bool Texture::deactivate()
00097 {
00098 if(id > 0 )
00099 {
00100
00101 glDisable(target);
00102 return true;
00103 }
00104 return false;
00105 }
00106
00107 void Texture::setID(GLuint texID)
00108 {
00109 static int unknown = 1;
00110
00111 if(!texID)
00112 {
00113 Logger::writeErrorLog("invalid texID, Texture::setID(GLuint texID)");
00114 return;
00115 }
00116
00117 TextureInfo *newTextureInfo = TexturesManager::getTextureInfo(texID),
00118 *oldTextureInfo = TexturesManager::getTextureInfo(id);
00119
00120 if(newTextureInfo)
00121 newTextureInfo->increaseUserCount();
00122 else
00123 {
00124 newTextureInfo = new TextureInfo(std::string("Unknown texture"), texID);
00125 unknown++;
00126 }
00127
00128 if(oldTextureInfo)
00129 oldTextureInfo->decreaseUserCount();
00130
00131 id = texID;
00132
00133 GLint info;
00134
00135 activate();
00136 glGetTexLevelParameteriv(target, 0, GL_TEXTURE_WIDTH , &info);
00137 width = info;
00138 glGetTexLevelParameteriv(target, 0, GL_TEXTURE_HEIGHT, &info);
00139 height = info;
00140 deactivate();
00141 }
00142
00143 void Texture::setTarget(GLuint target_){ target = target_;}
00144 const GLuint Texture::getTarget() const { return target; }
00145 const GLuint Texture::getHeight() const { return height; }
00146 const GLuint Texture::getWidth() const { return width; }
00147 const GLuint Texture::getDepth() const { return depth; }
00148 const GLuint Texture::getID() const { return id; }
00149
00150 bool Texture::loadXMLSettings(const TiXmlElement *element)
00151 {
00152 if(!isSuitable(element))
00153 return false;
00154
00155 std::string path;
00156 int clampS = GL_CLAMP,
00157 clampT = GL_CLAMP,
00158 aniso = 0,
00159 magFilter = GL_LINEAR,
00160 minFilter = GL_LINEAR;
00161 bool mipmap = false,
00162 result = false;
00163
00164 const char *description = element->Attribute("description");
00165 if(description)
00166 return IOXMLObject::loadXMLSettings(description);
00167
00168 mipmap = XMLArbiter::analyzeBooleanAttr(element, "mipmap", true);
00169 target = getTypei(element->Attribute("type"));
00170 path = element->Attribute("path");
00171
00172 for(const TiXmlElement *child = element->FirstChildElement();
00173 child;
00174 child = child->NextSiblingElement() )
00175 {
00176 std::string childName = child->Value();
00177
00178 if(!childName.size())
00179 continue;
00180
00181 if(childName == "Wrap")
00182 {
00183 const char* attribute = child->Attribute("s");
00184 attribute = attribute ? attribute :
00185 child->Attribute("u");
00186
00187 clampS = getWrapModei(attribute);
00188
00189 attribute = child->Attribute("t");
00190 attribute = attribute ? attribute : child->Attribute("v");
00191
00192 clampT = getWrapModei(attribute);
00193 continue;
00194 }
00195
00196 if(childName == "Filter")
00197 {
00198 magFilter = getMagFilteri(child->Attribute("mag"));
00199 minFilter = getMinFilteri(child->Attribute("min"));
00200 aniso = XMLArbiter::fillComponents1i(child, "aniso", 0);
00201 continue;
00202 }
00203 }
00204
00205 result = (target == GL_TEXTURE_2D ) ? load2D (path.c_str(), clampS, clampT, magFilter, minFilter, mipmap) :
00206
00207 Logger::writeErrorLog("Unsupported texture type");
00208 return result;
00209 }
00210
00211 int Texture::getMagFilteri(const std::string &value)
00212 {
00213 if(value.size())
00214 {
00215 if(value == "NEAREST") return GL_NEAREST;
00216 }
00217 return GL_LINEAR;
00218 }
00219
00220 int Texture::getMinFilteri(const std::string &value)
00221 {
00222 if(value.size())
00223 {
00224 if(value == "NEAREST_MIPMAP_NEAREST") return GL_NEAREST_MIPMAP_NEAREST;
00225 if(value == "LINEAR_MIPMAP_NEAREST") return GL_LINEAR_MIPMAP_NEAREST;
00226 if(value == "NEAREST_MIPMAP_LINEAR") return GL_NEAREST_MIPMAP_LINEAR;
00227 if(value == "LINEAR_MIPMAP_LINEAR") return GL_LINEAR_MIPMAP_LINEAR;
00228 if(value == "NEAREST") return GL_NEAREST;
00229 }
00230 return GL_LINEAR;
00231 }
00232
00233 int Texture::getWrapModei(const std::string &value)
00234 {
00235 if(value.size())
00236 {
00237
00238
00239 if(value == "REPEAT") return GL_REPEAT;
00240 }
00241 return GL_CLAMP;
00242 }
00243
00244 int Texture::getTypei(const std::string &value)
00245 {
00246 if(value.size())
00247 {
00248 if(value == "TEXTURE_1D") return GL_TEXTURE_1D;
00249
00250
00251 }
00252 return GL_TEXTURE_2D;
00253 }
00254
00255 int Texture::getValidWrapMode(int clamp)
00256 {
00257 return (clamp == GL_CLAMP ) ? GL_CLAMP :
00258 (clamp == GL_REPEAT ) ? GL_REPEAT : GL_REPEAT;
00259
00260
00261 }
00262
00263 int Texture::getValidMagFilter(int filter)
00264 {
00265 return (filter == GL_NEAREST ) ? GL_NEAREST : GL_LINEAR;
00266 }
00267
00268 int Texture::getValidMinFilter(int filter)
00269 {
00270 return (filter == GL_NEAREST ) ? GL_NEAREST :
00271 (filter == GL_LINEAR_MIPMAP_LINEAR ) ? GL_LINEAR_MIPMAP_LINEAR :
00272 (filter == GL_NEAREST_MIPMAP_LINEAR ) ? GL_NEAREST_MIPMAP_LINEAR :
00273 (filter == GL_LINEAR_MIPMAP_NEAREST ) ? GL_LINEAR_MIPMAP_NEAREST :
00274 (filter == GL_NEAREST_MIPMAP_NEAREST ) ? GL_NEAREST_MIPMAP_NEAREST : GL_LINEAR;
00275 }
00276
00277 bool Texture::exportXMLSettings(ofstream &xmlFile )
00278 {
00279 if(!xmlFile.is_open())
00280 return Logger::writeErrorLog("Cannot export Texture to XML: file not ready.");
00281
00282 if(!id)
00283 return Logger::writeErrorLog("Cannot export Texture to XML: invalid texture handle.");
00284
00285 TextureInfo *textureInfo = TexturesManager::getTextureInfo(id);
00286
00287 if(!textureInfo)
00288 return Logger::writeErrorLog("Cannot export Texture to XML: cannot locate a valid MediaInfo.");
00289
00290 xmlFile << " <Texture type = \""
00291 << ((target == GL_TEXTURE_2D ) ? "TEXTURE_2D\"\n" :
00292 "TEXTURE_1D\"\n")
00293
00294 << " path = \"" << textureInfo->getMediaPath() << "\"\n"
00295 << " mipmap = \"true\" > \n"
00296 << " <Wrap s = \"REPEAT\" \n"
00297
00298 << " t = \"REPEAT\" />\n"
00299 << " <Filter mag = \"LINEAR\" \n"
00300 << " min = \"LINEAR_MIPMAP_LINEAR\"/> \n";
00301
00302 xmlFile << " </Texture>\n";
00303 return true;
00304 }
00305
00306 void Texture::destroy()
00307 {
00308 TextureInfo *textureInfo = TexturesManager::getTextureInfo(id);
00309
00310 if(textureInfo)
00311 textureInfo->decreaseUserCount();
00312 else
00313 glDeleteTextures(1, &id);
00314
00315 TexturesManager::flushUnusedTextures();
00316
00317 height = 0;
00318 width = 0;
00319 depth = 0;
00320 id = 0;
00321 }
00322
00323 Texture::~Texture()
00324 {
00325 destroy();
00326 }
00327
00328 bool Texture::load2D(const char* filename,
00329 GLuint clampS , GLuint clampT,
00330 GLuint magFilter, GLuint minFilter,
00331 bool mipmap)
00332 {
00333 std::string texturePath = MediaPathManager::lookUpMediaPath(filename);
00334
00335 if(!texturePath.size())
00336 return Logger::writeErrorLog(std::string("Couldn't locate the Texture file at <") + filename + "> even with a look up");
00337
00338 if(checkForRepeat(texturePath.c_str()))
00339 return true;
00340
00341 Image image;
00342
00343 if(!image.load(filename))
00344 return Logger::writeErrorLog(std::string("Could not load Texture2D file at -> ") + filename);
00345
00346 return load2DImage(image, clampS, clampT, magFilter, minFilter, mipmap);
00347 }
00348
00349 bool Texture::load2DImage(const Image& image,
00350 GLuint clampS , GLuint clampT,
00351 GLuint magFilter, GLuint minFilter,
00352 bool mipmap)
00353 {
00354 const char *path = image.getPath().c_str();
00355 if(checkForRepeat(path))
00356 return true;
00357
00358 destroy();
00359 target = GL_TEXTURE_2D;
00360
00361 glGenTextures(1, &id);
00362 glBindTexture(GL_TEXTURE_2D, id);
00363 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getValidMagFilter(magFilter));
00364 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getValidMinFilter(minFilter));
00365 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getValidWrapMode(clampS));
00366 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getValidWrapMode(clampT));
00367
00368 if(loadTextureFace(image, GL_TEXTURE_2D, mipmap));
00369 else
00370 {
00371 destroy();
00372 return Logger::writeErrorLog(std::string("Could not load Texture2D file."));
00373 }
00374
00375 height = image.getHeight();
00376 width = image.getWidth();
00377 depth = 1;
00378
00379 if(finalizeLoading(path))
00380 {
00381 Logger::writeInfoLog(std::string("Loaded Texture2D file at -> ") + path);
00382 return true;
00383 }
00384 return false;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
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
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889 bool Texture::loadTextureFace(const Image &image,
00890 GLuint target,
00891 bool mipmap)
00892 {
00893 if(!id)
00894 return Logger::writeErrorLog("Invalid texture id, Texture::loadTextureFace");
00895
00896 if((this->target != GL_TEXTURE_2D) )
00897 return Logger::writeErrorLog("Unrecognized texture target, Texture::loadTextureFace");
00898
00899 GLuint quickFix = 0;
00900 switch(target)
00901 {
00902 case GL_TEXTURE_2D:
00903 quickFix = GL_TEXTURE_2D;
00904 break;
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914 }
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 if(mipmap)
00997 gluBuild2DMipmaps(target,
00998 image.getInternalFormat(),
00999 image.getWidth(),
01000 image.getHeight(),
01001 image.getFormat(),
01002 GL_UNSIGNED_BYTE,
01003 image.getDataBuffer());
01004 else
01005 glTexImage2D(target, 0, image.getInternalFormat(), image.getWidth(),
01006 image.getHeight(), 0, image.getFormat(),
01007 GL_UNSIGNED_BYTE, image.getDataBuffer());
01008
01009
01010 return true;
01011 }
01012
01013
01014
01015
01016
01017
01018
01019 vector<TextureInfo*> TexturesManager::textureCollection;
01020
01021 bool TexturesManager::addTextureInfo(TextureInfo *textureInfo)
01022 {
01023 flushUnusedTextures();
01024
01025 if(!textureInfo)
01026 return false;
01027 textureCollection.push_back(textureInfo);
01028 return true;
01029 }
01030
01031 TextureInfo *TexturesManager::getTextureInfo(const char* texturePath)
01032 {
01033 flushUnusedTextures();
01034 if(!texturePath || !textureCollection.size())
01035 return NULL;
01036
01037 for(size_t i = 0; i < textureCollection.size(); i++)
01038 if(textureCollection[i]->getMediaPath() == texturePath)
01039 return textureCollection[i];
01040
01041 return NULL;
01042 }
01043
01044 TextureInfo *TexturesManager::getTextureInfo(GLuint textureID)
01045 {
01046 if(!textureID || !textureCollection.size())
01047 return NULL;
01048
01049 for(size_t i = 0; i < textureCollection.size(); i++)
01050 if(textureCollection[i]->getMedia() == textureID)
01051 return textureCollection[i];
01052
01053 return NULL;
01054 }
01055
01056 void TexturesManager::flushUnusedTextures()
01057 {
01058 vector<TextureInfo*> validTextures;
01059 size_t i = 0,
01060 count = 0;
01061 GLuint textureID = 0;
01062
01063 for(i = 0; i < textureCollection.size(); i++)
01064 if(textureCollection[i]->getUserCount() > 0)
01065 {
01066 validTextures.push_back(textureCollection[i]);
01067 }
01068 else
01069 {
01070 count++;
01071 textureID = textureCollection[i]->getMedia();
01072 glDeleteTextures(1, &textureID);
01073 deleteObject(textureCollection[i]);
01074 }
01075
01076 textureCollection.clear();
01077
01078 for(i = 0; i < validTextures.size(); i++)
01079 textureCollection.push_back(validTextures[i]);
01080
01081 if(count)
01082 Logger::writeInfoLog(std::string("Flushed texture."));
01083 }
01084
01085 void TexturesManager::flushAllTextures(){
01086 GLuint textureID = 0;
01087
01088 size_t i = 0;
01089 for(i = 0; i < textureCollection.size(); i++)
01090 {
01091 textureID = textureCollection[i]->getMedia();
01092 glDeleteTextures(1, &textureID);
01093 deleteObject(textureCollection[i]);
01094 }
01095
01096 textureCollection.clear();
01097 if(i) Logger::writeInfoLog("Flushed all active textures");
01098 }
01099
01100 void TexturesManager::printTexturesInfo()
01101 {
01102 if(!textureCollection.size())
01103 cout << "This Manager contains no Textures as of yet." << endl;
01104 else{
01105 cout << "Textures list: " << endl;
01106 for(size_t i = 0; i < textureCollection.size(); i++)
01107 cout << "<users = \"" << textureCollection[i]->getUserCount() << "\" "
01108 << " path = \"" << textureCollection[i]->getMediaPath() << "\" "
01109 << " id = \"" << textureCollection[i]->getMedia() << "\" />" << endl;
01110 }
01111 }
01112
01113
01114
01115
01116
01117
01118 Image::Image(const char *path)
01119 {
01120 internalFormat = 0;
01121 components = 0;
01122 dataBuffer = NULL;
01123 format = 0;
01124 height = 0;
01125 width = 0;
01126 depth = 0;
01127
01128 if(path)
01129 load(path);
01130 }
01131
01132 void Image::setWidth(unsigned short w)
01133 {
01134 width = w;
01135 }
01136
01137 void Image::setHeight(unsigned short h){
01138 height = h;
01139 }
01140
01141 void Image::setDataBuffer(const unsigned char *buffer)
01142 {
01143 if(!buffer)
01144 return;
01145
01146 if(dataBuffer)
01147 deleteArray(dataBuffer);
01148
01149 dataBuffer = new unsigned char[width*height*components];
01150 memcpy(dataBuffer, buffer, width*height*components);
01151 }
01152
01153 void Image::setFormat(unsigned int f)
01154 {
01155 format = f;
01156 }
01157
01158 void Image::setInternalFormat(unsigned int iformat)
01159 {
01160 internalFormat = iformat;
01161 }
01162
01163 void Image::setComponentsCount(unsigned int c)
01164 {
01165 components = c < 1 ? 1 : c > 4 ? 4 : c;
01166 }
01167
01168 void Image::flipVertically()
01169 {
01170 if(depth)
01171 return;
01172
01173 unsigned char *newDataBuffer = new unsigned char[width*height*components];
01174 int counterDown = 0,
01175 counterUp = 0;
01176
01177 if(components == 3){
01178 for(int y = 0, y1 = height - 1; y < height; y++, y1--)
01179 for(int x = 0; x < width; x++){
01180 counterUp = (x + y1*width)*3;
01181 counterDown = (x + y*width)*3;
01182 newDataBuffer[counterUp + 0] = dataBuffer[counterDown + 0];
01183 newDataBuffer[counterUp + 1] = dataBuffer[counterDown + 1];
01184 newDataBuffer[counterUp + 2] = dataBuffer[counterDown + 2];
01185 }
01186 }
01187
01188 if(components == 4){
01189 for(int y = 0, y1 = height - 1; y < height; y++, y1--)
01190 for(int x = 0; x < width; x++){
01191 counterUp = (x + y1*width)*components;
01192 counterDown = (x + y*width)*components;
01193 newDataBuffer[counterUp + 0] = dataBuffer[counterDown + 0];
01194 newDataBuffer[counterUp + 1] = dataBuffer[counterDown + 1];
01195 newDataBuffer[counterUp + 2] = dataBuffer[counterDown + 2];
01196 newDataBuffer[counterUp + 3] = dataBuffer[counterDown + 3];
01197 }
01198 }
01199
01200 if(components == 1){
01201 for(int y = 0, y1 = height - 1; y < height; y++, y1--)
01202 for(int x = 0; x < width; x++){
01203 counterUp = x + y1*width;
01204 counterDown = x + y*width;
01205 newDataBuffer[counterUp + 0] = dataBuffer[counterDown + 0];
01206 }
01207 }
01208
01209 setDataBuffer(newDataBuffer);
01210 deleteArray(newDataBuffer);
01211 }
01212
01213 bool Image::load(const char* path_)
01214 {
01215 std::string verifiedPath = MediaPathManager::lookUpMediaPath(path_);
01216
01217 if(!verifiedPath.size())
01218 return false;
01219
01220 const char* cPath = verifiedPath.c_str();
01221 path = verifiedPath;
01222
01223 #ifdef GLWX_PNG_SUPPORT
01224 if(strstr(path_, "png") || strstr(path_, "PNG" ))
01225 return loadPNG(cPath);
01226 #endif
01227
01228 if(strstr(path_, "ppm") || strstr(path_, "PPM" ))
01229 return loadPPM(cPath);
01230
01231 if(strstr(path_, "jpg") || strstr(path_, "JPG" ) ||
01232 strstr(path_, "jpeg") || strstr(path_, "JPEG"))
01233 return loadJPG(cPath);
01234
01235 if(strstr(path_, "targa") || strstr(path_, "TARGA" ) ||
01236 strstr(path_, "tga") || strstr(path_, "TGA"))
01237 return loadTGA(cPath);
01238
01239 return false;
01240 }
01241
01242 const unsigned int Image::getComponentsCount() const { return components; }
01243 const unsigned int Image::getInternalFormat() const { return internalFormat; }
01244 const unsigned char* Image::getDataBuffer() const { return dataBuffer; }
01245 const unsigned int Image::getFormat() const { return format; }
01246 const std::string &Image::getPath() const { return path; }
01247
01248 const unsigned short Image::getHeight() const {return height;}
01249 const unsigned short Image::getWidth() const {return width; }
01250 const unsigned short Image::getDepth() const {return depth; }
01251
01252 Image::~Image()
01253 {
01254 if(dataBuffer)
01255 deleteArray(dataBuffer);
01256 }
01257
01258
01259
01260
01261
01262
01263
01264
01265 #ifndef max
01266 #define max(a, b) (((a)>(b))?(a):(b))
01267 #endif
01268
01269 #ifndef min
01270 #define min(a, b) (((a)<(b))?(a):(b))
01271 #endif
01272
01273 unsigned char getByte();
01274 char fileOpen(const char *);
01275
01276 void decodeQTable(int);
01277 void strmSkip(int n);
01278 void decodeBlock();
01279 void fileClose();
01280 void getInfo();
01281 void fidct();
01282
01283 int wordDec(int);
01284
01285 typedef unsigned short qTable[64];
01286
01287 typedef struct
01288 {
01289 struct tables{
01290 unsigned char size;
01291 unsigned char code;
01292 } TSmall[512], TLarge[65536];
01293 } HuffTable;
01294
01295 void decodeHuffTable(int);
01296
01297 typedef struct
01298 {
01299 HuffTable *huffAC, *huffDC;
01300 qTable *qTab;
01301 int dcPrev,smpx, smpy;
01302 float t[256];
01303 }ComponentTable;
01304
01305 ComponentTable component[4];
01306 HuffTable huffTableAC[4],
01307 huffTableDC[4];
01308 qTable qtable[4];
01309
01310 unsigned int xblock, yblock, blockx, blocky,
01311 bsize, restartInt, bfree,
01312 dt;
01313 unsigned char *data, *bpos , *dend,
01314 eof , ssStart, ssEnd,
01315 sbits, prec , ncomp;
01316 float dctt[64];
01317
01318 int zigzag[64]=
01319 {
01320 0, 1, 8, 16, 9, 2, 3, 10,
01321 17, 24, 32, 25, 18, 11, 4, 5,
01322 12, 19, 26, 33, 40, 48, 41, 34,
01323 27, 20, 13, 6, 7, 14, 21, 28,
01324 35, 42, 49, 56, 57, 50, 43, 36,
01325 29, 22, 15, 23, 30, 37, 44, 51,
01326 58, 59, 52, 45, 38, 31, 39, 46,
01327 53, 60, 61, 54, 47, 55, 62, 63
01328 };
01329
01330
01331 char fileOpen(const char *filename)
01332 {
01333 FILE *stream;
01334 data = NULL;
01335 if((stream=fopen(filename, "rb"))==NULL)
01336 return 0;
01337 else{
01338 fseek(stream, 0, SEEK_END);
01339 bsize = ftell(stream);
01340 fseek(stream, 0, SEEK_SET);
01341 data = new unsigned char[bsize];
01342 fread(data, 1, bsize, stream);
01343 fclose(stream);
01344 return 1;
01345 }
01346 }
01347
01348 void fileClose(void)
01349 {
01350 if(data)
01351 delete[] data;
01352 }
01353
01354 unsigned char getByte(void)
01355 {
01356 if(bpos>=dend){
01357 eof = 1;
01358 return 0;
01359 }
01360 else
01361 return *bpos++;
01362 }
01363
01364 void strmSkip(int n)
01365 {
01366 unsigned char a, b;
01367 bfree+=n;
01368 dt<<=n;
01369
01370 while(bfree>=8){
01371 bfree-=8;
01372 b = getByte();
01373 if(b==255)
01374 a=getByte();
01375 dt|=(b<<bfree);
01376 }
01377 }
01378
01379 int huffDec(HuffTable *h)
01380 {
01381 unsigned int id, n, c;
01382
01383 id = (dt>>(23));
01384 n = h->TSmall[id].size;
01385 c = h->TSmall[id].code;
01386
01387 if(n==255){
01388 id = (dt>>(16));
01389 n = h->TLarge[id].size;
01390 c = h->TLarge[id].code;
01391 }
01392
01393 strmSkip(n);
01394 return c;
01395 }
01396
01397 int wordDec(int n)
01398 {
01399 int w;
01400 unsigned int s;
01401
01402 if(n==0)
01403 return 0;
01404 else{
01405 s= (dt>>(31));
01406 w= (dt>>(32-n));
01407 strmSkip(n);
01408 if(s==0)
01409 w = (w|(0xffffffff<<n))+1;
01410 }
01411 return w;
01412 }
01413
01414 void Image::getJPGInfo()
01415 {
01416 unsigned char cn, sf, qt;
01417 int i;
01418
01419 prec = getByte();
01420
01421 if(prec!=8)
01422 return;
01423
01424 height = ((getByte()<<8)+getByte());
01425 width = ((getByte()<<8)+getByte());
01426 ncomp = getByte();
01427
01428 if((ncomp!=3)&&(ncomp!=1))
01429 return;
01430
01431 for(i=0;i<ncomp;i++)
01432 {
01433 cn = getByte();
01434 sf = getByte();
01435 qt = getByte();
01436
01437 component[cn-1].qTab = &qtable[qt];
01438 component[cn-1].smpy = sf&15;
01439 component[cn-1].smpx = (sf>>4)&15;
01440 }
01441
01442 if(component[0].smpx == 1)
01443 blockx = 8;
01444 else
01445 blockx = 16;
01446
01447 if(component[0].smpy==1)
01448 blocky = 8;
01449 else
01450 blocky = 16;
01451
01452 xblock=width/blockx;
01453
01454 if((width & (blockx-1))!=0)
01455 xblock++;
01456
01457 yblock = height/blocky;
01458
01459 if((height&(blocky-1))!=0)
01460 yblock++;
01461 }
01462
01463 void decodeHuffTable(int len)
01464 {
01465 int length[257], i, j, n, code, codelen, delta, rcode, cd, rng;
01466 unsigned char lengths[16], b, symbol[257];
01467 HuffTable *h;
01468
01469 len-=2;
01470
01471 while(len>0){
01472 b = getByte();
01473 len--;
01474 h = &huffTableDC[0];
01475
01476 switch(b){
01477 case 0:
01478 h = &huffTableDC[0];
01479 break;
01480
01481 case 1:
01482 h = &huffTableDC[1];
01483 break;
01484
01485 case 16:
01486 h = &huffTableAC[0];
01487 break;
01488
01489 case 17:
01490 h=&huffTableAC[1];
01491 break;
01492 }
01493
01494 for(i=0;i<16;i++)
01495 lengths[i] = getByte();
01496
01497 len -= 16;
01498 n = 0;
01499
01500 for(i=0;i<16;i++){
01501 len-=lengths[i];
01502 for(j=0;j<lengths[i];j++){
01503 symbol[n] = getByte();
01504 length[n++] = i+1;
01505 }
01506 }
01507
01508 code = 0;
01509 codelen = length[0];
01510
01511 for(i=0;i<n;i++){
01512
01513 rcode = code<<(16-codelen);
01514 cd = rcode>>7;
01515
01516 if(codelen<=9){
01517 rng = 1 <<(9-codelen);
01518
01519 for(j=cd;j<cd+rng;j++){
01520 h->TSmall[j].code = (unsigned char)symbol[i];
01521 h->TSmall[j].size = (unsigned char)codelen;
01522 }
01523 }
01524 else{
01525 h->TSmall[cd].size=(unsigned char)255;
01526 rng = 1<<(16-codelen);
01527
01528 for(j=rcode;j<rcode+rng;j++){
01529 h->TLarge[j].code=(unsigned char)symbol[i];
01530 h->TLarge[j].size=(unsigned char)codelen;
01531 }
01532 }
01533
01534 code++;
01535 delta=length[i+1]-codelen;
01536 code<<=delta;
01537 codelen+=delta;
01538 }
01539 }
01540 }
01541
01542 void fidct(void)
01543 {
01544 float a = 0.353553385f,
01545 b = 0.490392625f,
01546 c = 0.415734798f,
01547 d = 0.277785122f,
01548 e = 0.097545162f,
01549 f = 0.461939752f,
01550 g = 0.191341713f,
01551 cd =0.6935199499f,
01552 be =0.5879377723f,
01553 bc =0.9061274529f,
01554 de =0.3753302693f,
01555 a0, f2, g2, a4, f6, g6, s0, s1, s2, s3,
01556 t0, t1, t2, t3, m0, m1, m2, m3,
01557 h0, h1, h2, h3, r0, r1, r2, r3, w;
01558 int i;
01559
01560 for(i=0;i<64;i+=8){
01561 if((dctt[i+1]!=0)||(dctt[i+2]!=0)||(dctt[i+3]!=0)||(dctt[i+4]!=0)||(dctt[i+5]!=0)||(dctt[i+6]!=0)||(dctt[i+7]!=0))
01562 {
01563 a0 = a*dctt[i];
01564 f2 = f*dctt[i+2];
01565 g2 = g*dctt[i+2];
01566 a4 = a*dctt[i+4];
01567 g6 = g*dctt[i+6];
01568 f6 = f*dctt[i+6];
01569 m0 = a0+a4;
01570 m1 = a0-a4;
01571 m2 = f2+g6;
01572 m3 = g2-f6;
01573 s0 = m0+m2;
01574 s1 = m1+m3;
01575 s2 = m1-m3;
01576 s3 = m0-m2;
01577 h2 = dctt[i+7]+dctt[i+1];
01578 h3 = dctt[i+7]-dctt[i+1];
01579 r2 = dctt[i+3]+dctt[i+5];
01580 r3 = dctt[i+3]-dctt[i+5];
01581 h0 = cd*dctt[i+1];
01582 h1 = be*dctt[i+1];
01583 r0 = be*dctt[i+5];
01584 r1 = cd*dctt[i+3];
01585 w = de*r3;
01586 t0 = h1+r1+e*(h3+r3)-w;
01587 t1 = h0-r0-d*(h2-r3)-w;
01588 w = bc*r2;
01589 t2 = h0+r0+c*(h3+r2)-w;
01590 t3 = h1-r1-b*(h2+r2)+w;
01591 dctt[i] = s0+t0;
01592 dctt[i+1] = s1+t1;
01593 dctt[i+2] = s2+t2;
01594 dctt[i+3] = s3+t3;
01595 dctt[i+4] = s3-t3;
01596 dctt[i+5] = s2-t2;
01597 dctt[i+6] = s1-t1;
01598 dctt[i+7] = s0-t0;
01599 }
01600 else{
01601 a0 = dctt[i]*a;
01602 dctt[i]=dctt[i+1]=dctt[i+2]=dctt[i+3]=dctt[i+4]=dctt[i+5]=dctt[i+6]=dctt[i+7]=a0;
01603 }
01604 }
01605
01606 for(i=0;i<8;i++){
01607 if((dctt[8+i]!=0)||(dctt[16+i]!=0)||(dctt[24+i]!=0)||(dctt[32+i]!=0)||(dctt[40+i]!=0)||(dctt[48+i]!=0)||(dctt[56+i]!=0))
01608 {
01609 a0 = a*dctt[i];
01610 f2 = f*dctt[16+i];
01611 g2 = g*dctt[16+i];
01612 a4 = a*dctt[32+i];
01613 g6 = g*dctt[48+i];
01614 f6 = f*dctt[48+i];
01615 m0 = a0+a4;
01616 m1 = a0-a4;
01617 m2 = f2+g6;
01618 m3 = g2-f6;
01619 s0 = m0+m2;
01620 s1 = m1+m3;
01621 s2 = m1-m3;
01622 s3 = m0-m2;
01623 h2 = dctt[56+i]+dctt[8+i];
01624 h3 = dctt[56+i]-dctt[8+i];
01625 r2 = dctt[24+i]+dctt[40+i];
01626 r3 = dctt[24+i]-dctt[40+i];
01627 h0 = cd*dctt[8+i];
01628 h1 = be*dctt[8+i];
01629 r0 = be*dctt[40+i];
01630 r1 = cd*dctt[24+i];
01631 w = de*r3;
01632 t0 = h1+r1+e*(h3+r3)-w;
01633 t1 = h0-r0-d*(h2-r3)-w;
01634 w = bc*r2;
01635 t2 = h0+r0+c*(h3+r2)-w;
01636 t3 = h1-r1-b*(h2+r2)+w;
01637 dctt[i] = s0+t0;
01638 dctt[i+8] = s1+t1;
01639 dctt[i+16] = s2+t2;
01640 dctt[i+24] = s3+t3;
01641 dctt[i+32] = s3-t3;
01642 dctt[i+40] = s2-t2;
01643 dctt[i+48] = s1-t1;
01644 dctt[i+56] = s0-t0;
01645 }
01646 else{
01647 a0 = dctt[i]*a;
01648 dctt[i]=dctt[i+8]=dctt[i+16]=dctt[i+24]=dctt[i+32]=dctt[i+40]=dctt[i+48]=dctt[i+56]=a0;
01649 }
01650 }
01651 }
01652
01653 void decodeQTable(int len)
01654 {
01655 int i;
01656 unsigned char b;
01657
01658 len-=2;
01659
01660 while(len>0){
01661 b = (unsigned char)getByte();
01662 len--;
01663
01664 if((b&16)==0){
01665 for(i=0;i<64;i++)
01666 qtable[b&15][i]=getByte();
01667 len-=64;
01668 }
01669 else{
01670 for(i=0;i<64;i++)
01671 qtable[b&15][i]=((getByte()<<8)+getByte());
01672 len-=128;
01673 }
01674 }
01675 }
01676
01677 void decodeBlock(void)
01678 {
01679 int compn, i, j, b, p, codelen, code, cx, cy, otab[64];
01680 qTable *qtab;
01681
01682 for(compn=0;compn<ncomp;compn++)
01683 {
01684 qtab = component[compn].qTab;
01685
01686 for(cy=0;cy<component[compn].smpy;cy++){
01687 for(cx=0;cx<component[compn].smpx;cx++){
01688 for(i=0;i<64;i++)
01689 otab[i]=0;
01690
01691 codelen= huffDec(component[compn].huffDC);
01692 code=wordDec(codelen);
01693
01694 otab[0] = code+component[compn].dcPrev;
01695 component[compn].dcPrev = otab[0];
01696 i=1;
01697
01698 while(i<64){
01699 codelen=huffDec(component[compn].huffAC);
01700 if(codelen==0)
01701 i=64;
01702 else
01703 if(codelen==0xf0)
01704 i+=16;
01705 else{
01706 code = wordDec(codelen&15);
01707 i = i+(codelen>>4);
01708 otab[i++]=code;
01709 }
01710 }
01711
01712 for(i=0;i<64;i++)
01713 dctt[zigzag[i]]=(float)((*qtab)[i]*otab[i]);
01714
01715 fidct();
01716 b=(cy<<7)+(cx<<3);
01717 p=0;
01718
01719 for(i=0;i<8;i++){
01720 for(j=0;j<8;j++)
01721 component[compn].t[b++]=dctt[p++]+128;
01722 b+=8;
01723 }
01724 }
01725 }
01726 }
01727 }
01728
01729 int Image::decodeScanJPG()
01730 {
01731 unsigned int nnx, nny, i, j,
01732 xmin, ymin, xmax, ymax, blockn, adr1, adr2,
01733 y1, u1, v1, y2, u2, v2, u3, v3,
01734 dux, duy, dvx, dvy;
01735 unsigned char sc, ts;
01736 float cy, cu, cv;
01737 components = GLuint(getByte());
01738
01739 setFormat(GL_BGR);
01740 setInternalFormat(GL_RGB8);
01741
01742 if(dataBuffer)
01743 deleteArray(dataBuffer);
01744
01745 dataBuffer = new unsigned char[width*height*components];
01746
01747 for(i=0;i<components;i++){
01748 sc = getByte();
01749 ts = getByte();
01750
01751 component[sc-1].huffDC = &huffTableDC[ts>>4];
01752 component[sc-1].huffAC = &huffTableAC[ts&15];
01753 }
01754
01755 ssStart = getByte();
01756 ssEnd = getByte();
01757 sbits = getByte();
01758
01759 if((ssStart!=0)||(ssEnd!=63))
01760 return 0;
01761
01762 if(components == 3){
01763 dux = 2+component[1].smpx-component[0].smpx;
01764 duy = 2+component[1].smpy-component[0].smpy;
01765 dvx = 2+component[2].smpx-component[0].smpx;
01766 dvy = 2+component[2].smpy-component[0].smpy;
01767 }
01768
01769 dt = 0;
01770 bfree = 0;
01771 strmSkip(32);
01772
01773 blockn=0;
01774 ymin=0;
01775
01776 for(nny=0;nny<yblock;nny++){
01777 ymax = ymin+blocky;
01778
01779 if(ymax>height)
01780 ymax = height;
01781
01782 xmin=0;
01783
01784 for(nnx=0;nnx<xblock;nnx++){
01785 xmax=xmin+blockx;
01786
01787 if(xmax>width)
01788 xmax=width;
01789
01790 decodeBlock();
01791
01792 blockn++;
01793 if((blockn==restartInt)&&((nnx<xblock-1)||(nny<yblock-1)))
01794 {
01795 blockn=0;
01796
01797 if(bfree!=0)
01798 strmSkip(8-bfree);
01799
01800 if(wordDec(8)!=255)
01801 return 0;
01802
01803 for(i=0;i<components;i++)
01804 component[i].dcPrev=0;
01805 }
01806
01807 if(components ==3){
01808 y1=u1=v1=0;
01809 adr1=(height-1-ymin)*width+xmin;
01810
01811 for(i=ymin;i<ymax;i++){
01812 adr2=adr1;
01813 adr1-=width;
01814 y2=y1;
01815 y1+=16;
01816 u3=(u1>>1)<<4;
01817 u1+=duy;
01818 v3=(v1>>1)<<4;
01819 v1+=dvy;
01820 u2=v2=0;
01821
01822 for(j=xmin;j<xmax;j++){
01823 int cr, cg, cb;
01824 cy=component[0].t[y2++];
01825 cu=component[1].t[u3+(u2>>1)]-128.0f;
01826 cv=component[2].t[v3+(v2>>1)]-128.0f;
01827
01828 cr=(int)(cy+1.402f*cv);
01829 cg=(int)(cy-0.34414f*cu-0.71414f*cv);
01830 cb=(int)(cy+1.772f*cu);
01831
01832 dataBuffer[3*adr2] = max(0, min(255, cb));
01833 dataBuffer[3*adr2+1] = max(0, min(255, cg));
01834 dataBuffer[3*adr2+2] = max(0, min(255, cr));
01835 adr2++;
01836
01837 u2+=dux;
01838 v2+=dvx;
01839 }
01840 }
01841 }
01842 else
01843 if(components==1)
01844 {
01845 y1=0;
01846 adr1=(height-1-ymin)*width+xmin;
01847
01848 for(i=ymin;i<ymax;i++){
01849 adr2=adr1;
01850 adr1-=width;
01851 y2=y1;
01852 y1+=16;
01853
01854 for(j=xmin;j<xmax;j++){
01855 int lum=(int)component[0].t[y2++];
01856 dataBuffer[adr2++]=max(0, min(255, lum));
01857 }
01858 }
01859 }
01860 xmin=xmax;
01861 }
01862 ymin=ymax;
01863 }
01864 return 1;
01865 }
01866
01867 int Image::decodeJPG()
01868 {
01869 int w;
01870 unsigned char a, hdr=0, scan=0;
01871
01872 eof=0;
01873 bpos=data;
01874 dend=bpos+bsize;
01875 w=((getByte()<<8)+getByte());
01876
01877 if(w!=0xffd8)
01878 return 0;
01879
01880 while(eof==0)
01881 {
01882 a=(unsigned char)getByte();
01883
01884 if(a!=0xff)
01885 return 0;
01886
01887 a=(unsigned char)getByte();
01888 w=((getByte()<<8)+getByte());
01889
01890 switch(a){
01891 case 0xe0:
01892 if(hdr!=0)
01893 break;
01894
01895 if(getByte()!='J')
01896 return 0;
01897
01898 if(getByte()!='F')
01899 return 0;
01900
01901 if(getByte()!='I')
01902 return 0;
01903
01904 if(getByte()!='F')
01905 return 0;
01906
01907 hdr=1;
01908 w-=4;
01909 break;
01910
01911 case 0xc0:
01912 getJPGInfo();
01913 w=0;
01914 break;
01915
01916 case 0xc4:
01917 decodeHuffTable(w);
01918 w=0;
01919 break;
01920
01921 case 0xd9:
01922 w=0;
01923 break;
01924
01925 case 0xda:
01926 if(scan!=0)
01927 break;
01928
01929 scan=1;
01930
01931 if(!decodeScanJPG())
01932 return 0;
01933
01934 w=0;
01935 eof=1;
01936 break;
01937
01938 case 0xdb:
01939 decodeQTable(w);
01940 w=0;
01941 break;
01942
01943 case 0xdd:
01944 restartInt=((getByte()<<8)+getByte());
01945 w=0;
01946 break;
01947 }
01948
01949 while(w>2){
01950 getByte();
01951 w--;
01952 }
01953 }
01954 return 1;
01955 }
01956
01957 bool Image::loadJPG(const char *filename)
01958 {
01959 int i;
01960 for(i=0;i<4;i++)
01961 component[i].dcPrev=0;
01962
01963 restartInt = 0;
01964
01965 if(fileOpen(filename)){
01966 int ret= decodeJPG();
01967 fileClose();
01968 if(!ret) return false;
01969 else {
01970 flipVertically();
01971 return true;
01972 }
01973 }
01974 else
01975 return false;
01976 }
01977
01978
01979
01980
01981
01982
01983 #ifdef GLWX_PNG_SUPPORT
01984
01985 bool Image::loadPNG(const char* filename)
01986 {
01987 pngRawInfo info;
01988
01989 if(!pngLoadRaw(filename, &info))
01990 return false;
01991
01992 setComponentsCount(info.Components);
01993 setWidth(info.Width);
01994 setHeight(info.Height);
01995 setFormat(info.Components == 4 ? GL_RGBA :
01996 info.Components == 3 ? GL_RGB : GL_LUMINANCE );
01997 setInternalFormat(info.Components == 4 ? GL_RGBA8 :
01998 info.Components == 3 ? GL_RGB8 : GL_LUMINANCE8);
01999 setDataBuffer(info.Data);
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009 delete info.Data;
02010 delete info.Palette;
02011
02012 return true;
02013 }
02014
02015 #endif //GLWX_PNG_SUPPORT
02016
02017
02018
02019
02020
02021
02022
02023 bool Image::loadPPM(const char* filename)
02024 {
02025
02026
02027 char buffer[100];
02028 GLubyte *theTexture;
02029 unsigned char c;
02030 int w, h, maxVal, pixelSize;
02031
02032
02033
02034 FILE * inFile = fopen(filename, "rb");
02035 if (inFile == NULL)
02036 return Logger::writeErrorLog(std::string("Could not find file -> ") + filename);
02037
02038
02039 fgets(buffer, sizeof(buffer), inFile);
02040 if ((buffer[0] != 'P') || (buffer[1] != '6'))
02041 return Logger::writeErrorLog(std::string("Error, PPM is not RGB or RGBA binary type: ") + filename);
02042
02043 if (buffer[2] == 'A')
02044 pixelSize = 4;
02045 else
02046 pixelSize = 3;
02047
02048
02049 do fgets(buffer, sizeof (buffer), inFile);
02050 while (buffer[0] == '#');
02051 sscanf (buffer, "%d %d", &w, &h);
02052
02053
02054 do fgets (buffer, sizeof (buffer), inFile);
02055 while (buffer[0] == '#');
02056 sscanf (buffer, "%d", &maxVal);
02057
02058
02059 int memSize = w * h * 4;
02060 theTexture = new unsigned char[memSize];
02061
02062
02063 for (int i = 0; i < memSize; i++) {
02064 if ((i % 4) < 3 || pixelSize == 4) {
02065 c = fgetc(inFile);
02066 theTexture[i]=(GLubyte) c;
02067 }
02068 else theTexture[i] = (GLubyte) 255;
02069 }
02070 fclose(inFile);
02071
02072 this->setComponentsCount(4);
02073 this->setWidth(w);
02074 this->setHeight(h);
02075 this->setFormat(GL_RGBA );
02076 this->setInternalFormat( GL_RGBA8 );
02077 this->setDataBuffer(theTexture);
02078
02079 deleteArray(theTexture);
02080
02081 return true;
02082 }
02083
02084
02085
02086
02087
02088
02089
02090 bool Image::loadTGA(const char* filename)
02091 {
02092 unsigned char uncompressed8BitTGAHeader[12]= {0, 1, 1, 0, 0, 0, 1, 24, 0, 0, 0, 0},
02093 uncompressedTGAHeader[12] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0},
02094 compressedTGAHeader[12] = {0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
02095
02096 unsigned char TGAcompare[12];
02097
02098 FILE * file = fopen(filename, "rb");
02099
02100 if(file==NULL )
02101 return Logger::writeErrorLog(std::string("Could not find file -> ") + filename);
02102
02103
02104
02105 fread(TGAcompare, 1, sizeof(TGAcompare), file);
02106 fclose(file);
02107
02108 if(!memcmp(uncompressedTGAHeader, TGAcompare, sizeof(uncompressedTGAHeader)))
02109 {
02110 return loadUncompressedTrueColorTGA(filename);
02111 }
02112 else if(!memcmp(compressedTGAHeader, TGAcompare, sizeof(compressedTGAHeader)))
02113 {
02114 return loadCompressedTrueColorTGA(filename);
02115 }
02116 else if(!memcmp(uncompressed8BitTGAHeader, TGAcompare, sizeof(uncompressed8BitTGAHeader)))
02117 {
02118 return loadUncompressed8BitTGA(filename);
02119 }
02120 else
02121 return Logger::writeErrorLog(std::string("Unrecognized TGA format -> ") + filename);
02122
02123 return false;
02124 }
02125
02126 bool Image::loadUncompressed8BitTGA(const char * filename)
02127 {
02128 unsigned char TGAHeader[12]={0, 1, 1, 0, 0, 0, 1, 24, 0, 0, 0, 0};
02129 unsigned char TGAcompare[12];
02130 unsigned char header[6];
02131
02132 FILE * file = fopen(filename, "rb");
02133
02134 if(file == NULL)
02135 return Logger::writeErrorLog(std::string("Could not find file at -> ") + filename);
02136
02137 if(fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)||
02138 memcmp(TGAHeader, TGAcompare, sizeof(TGAHeader))!=0 ||
02139 fread(header, 1, sizeof(header), file)!=sizeof(header))
02140 {
02141 fclose(file);
02142 return Logger::writeErrorLog(std::string("Could not process file at -> ") + filename);
02143 }
02144
02145
02146 setWidth(header[1]*256+header[0]);
02147 setHeight(header[3]*256+header[2]);
02148 setComponentsCount(header[4]/8);
02149
02150 if(width <=0 ||
02151 height <=0 ||
02152 header[4] != 8)
02153 {
02154 fclose(file);
02155 return Logger::writeErrorLog(std::string("The height or width is less than zero, or the TGA is not 8 bpp -> ") + filename);
02156 }
02157
02158 setFormat(GL_RGB);
02159 setInternalFormat(GL_RGB8);
02160
02161
02162 unsigned char * palette=new unsigned char[256*3];
02163 if(!palette)
02164 return Logger::writeErrorLog("Unable to allocate memory for palette");
02165
02166
02167
02168 fread(palette, 256*3, 1, file);
02169
02170
02171 unsigned char * indices=new unsigned char[width*height];
02172 if(!indices)
02173 return Logger::writeErrorLog("Unable to allocate memory for indices");
02174
02175
02176
02177 fread(indices, 1, width*height, file);
02178
02179
02180 fclose(file);
02181
02182 if(dataBuffer)
02183 deleteArray(dataBuffer);
02184
02185
02186 dataBuffer = new unsigned char[width*height*3];
02187
02188 if(!dataBuffer)
02189 {
02190 fclose(file);
02191 return Logger::writeErrorLog(std::string("Unable to allocate memory for ->") + filename);
02192 }
02193
02194
02195 for(int currentRow=0; currentRow<height; currentRow++)
02196 {
02197 for(int i=0; i<width; i++)
02198 {
02199 dataBuffer[(currentRow*width+i)*3+0]=palette[indices[currentRow*width+i]*3+2];
02200 dataBuffer[(currentRow*width+i)*3+1]=palette[indices[currentRow*width+i]*3+1];
02201 dataBuffer[(currentRow*width+i)*3+2]=palette[indices[currentRow*width+i]*3+0];
02202 }
02203 }
02204 return true;
02205 }
02206
02207 bool Image::loadUncompressedTrueColorTGA(const char * filename)
02208 {
02209 unsigned char TGAheader[12]={0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
02210 unsigned char TGAcompare[12];
02211 unsigned char header[6];
02212 unsigned int imageSize;
02213
02214 FILE * file = fopen(filename, "rb");
02215
02216 if(file == NULL)
02217 return Logger::writeErrorLog(std::string("Could not load file at -> ") + filename);
02218
02219 if( fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)||
02220 memcmp(TGAheader, TGAcompare, sizeof(TGAheader))!=0 ||
02221 fread(header, 1, sizeof(header), file)!=sizeof(header))
02222 {
02223 fclose(file);
02224 return Logger::writeErrorLog(std::string("Could not process file at -> ") + filename);
02225 }
02226
02227
02228 setWidth(header[1]*256+header[0]);
02229 setHeight(header[3]*256+header[2]);
02230 setComponentsCount(header[4]/3);
02231
02232 if(width <=0 ||
02233 height<=0 ||
02234 (header[4] !=24 && header[4]!=32))
02235 {
02236 fclose(file);
02237 return Logger::writeErrorLog(std::string("The height or width is less than zero, or the TGA is not 24 bpp -> ") + filename);
02238 }
02239
02240
02241 if(header[4] == 24){
02242 setFormat(GL_BGR);
02243 setInternalFormat(GL_RGB8);
02244 }
02245 else{
02246 setFormat(GL_BGRA);
02247 setInternalFormat(GL_RGBA8);
02248 }
02249
02250 imageSize = width*height*getComponentsCount();
02251
02252 if(dataBuffer)
02253 deleteArray(dataBuffer);
02254
02255 dataBuffer = new unsigned char[imageSize];
02256
02257 if(dataBuffer==NULL)
02258 {
02259 fclose(file);
02260 return Logger::writeErrorLog(std::string("Unable to allocate memory for image ->") + filename);
02261 }
02262
02263
02264 fread(dataBuffer, 1, imageSize, file);
02265 fclose(file);
02266 return true;
02267 }
02268
02269
02270 bool Image::loadCompressedTrueColorTGA(const char * filename)
02271 {
02272 unsigned char TGAheader[12]={0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
02273 unsigned char TGAcompare[12];
02274 unsigned char header[6];
02275 unsigned int bytesPerPixel;
02276 unsigned int imageSize;
02277
02278 FILE * file = fopen(filename, "rb");
02279
02280 if(file == NULL)
02281 return Logger::writeErrorLog(std::string("Could not load file at -> ") + filename);
02282
02283
02284 if( fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)||
02285 memcmp(TGAheader, TGAcompare, sizeof(TGAheader))!=0 ||
02286 fread(header, 1, sizeof(header), file)!=sizeof(header))
02287 {
02288 fclose(file);
02289 return Logger::writeErrorLog(std::string("Could not process file at -> ") + filename);
02290 }
02291
02292
02293 setWidth(header[1]*256+header[0]);
02294 setHeight(header[3]*256+header[2]);
02295 setComponentsCount(header[4]/8);
02296 bytesPerPixel = getComponentsCount();
02297
02298 if(width <=0 ||
02299 height <=0 ||
02300 (header[4] !=24 && header[4] !=32))
02301 {
02302 fclose(file);
02303 return Logger::writeErrorLog(std::string("The height or width is less than zero, or the TGA is not 24 bpp -> ") + filename);
02304 }
02305
02306
02307 if(header[4] == 24)
02308 {
02309 setFormat(GL_RGB);
02310 setInternalFormat(GL_RGB8);
02311 }
02312 else
02313 {
02314 setFormat(GL_RGBA);
02315 setInternalFormat(GL_RGBA8);
02316 }
02317
02318 imageSize = width*height*getComponentsCount();
02319
02320 if(dataBuffer)
02321 deleteArray(dataBuffer);
02322 dataBuffer = new unsigned char[imageSize];
02323
02324 if(!dataBuffer)
02325 {
02326 fclose(file);
02327 return Logger::writeErrorLog(std::string("Unable to allocate memory for image -> ") + filename);
02328 }
02329
02330
02331 int pixelCount = width*height;
02332 int currentPixel= 0;
02333 int currentByte = 0;
02334 unsigned char *colorBuffer = new unsigned char[getComponentsCount()];
02335
02336 do
02337 {
02338 unsigned char chunkHeader=0;
02339
02340 if(!fread(&chunkHeader, sizeof(unsigned char), 1, file))
02341 {
02342 if(file)
02343 fclose(file);
02344 deleteArray(dataBuffer);
02345 return Logger::writeErrorLog("Could not read RLE chunk header");
02346 }
02347
02348 if(chunkHeader<128)
02349 {
02350 chunkHeader++;
02351
02352 for(short counter=0; counter<chunkHeader; counter++)
02353 {
02354 if(fread(colorBuffer, 1, bytesPerPixel, file) != bytesPerPixel)
02355 {
02356 if(file)
02357 fclose(file);
02358 deleteArray(colorBuffer);
02359 deleteArray(dataBuffer);
02360 return Logger::writeErrorLog(std::string("Could not read image data -> ") + filename);
02361 }
02362
02363
02364 dataBuffer[currentByte] = colorBuffer[2];
02365 dataBuffer[currentByte+1] = colorBuffer[1];
02366 dataBuffer[currentByte+2] = colorBuffer[0];
02367
02368 if(bytesPerPixel==4)
02369 dataBuffer[currentByte+3]=colorBuffer[3];
02370
02371 currentByte+=bytesPerPixel;
02372 currentPixel++;
02373
02374 if(currentPixel > pixelCount)
02375 {
02376 if(file)
02377 fclose(file);
02378 deleteArray(colorBuffer);
02379 deleteArray(dataBuffer);
02380 return Logger::writeErrorLog("Too many pixels read");
02381 }
02382 }
02383 }
02384 else
02385 {
02386 chunkHeader-=127;
02387
02388 if(fread(colorBuffer, 1, bytesPerPixel, file) != bytesPerPixel)
02389 {
02390 if(file)
02391 fclose(file);
02392 deleteArray(colorBuffer);
02393 deleteArray(dataBuffer);
02394 return Logger::writeErrorLog(std::string("Unable to read image data -> ") + filename);
02395 }
02396
02397 for(short counter=0; counter<chunkHeader; counter++)
02398 {
02399
02400 dataBuffer[currentByte] = colorBuffer[2];
02401 dataBuffer[currentByte+1] = colorBuffer[1];
02402 dataBuffer[currentByte+2] = colorBuffer[0];
02403
02404 if(bytesPerPixel==4)
02405 dataBuffer[currentByte+3]=colorBuffer[3];
02406
02407 currentByte+=bytesPerPixel;
02408 currentPixel++;
02409
02410 if(currentPixel > pixelCount)
02411 {
02412 if(file)
02413 fclose(file);
02414 deleteArray(colorBuffer);
02415 deleteArray(dataBuffer);
02416 return Logger::writeErrorLog("Too many pixels read");
02417 }
02418 }
02419 }
02420 }while(currentPixel<pixelCount);
02421
02422 fclose(file);
02423 deleteArray(colorBuffer);
02424 return true;
02425 }