src/TextureUtils.cpp

Go to the documentation of this file.
00001 #include "TextureUtils.h"
00002 #include "glwxOpenGL.h"
00003 
00004 #ifdef GLWX_PNG_SUPPORT
00005         #include "glpng.h"
00006 #endif
00007 
00008 /*******************************************************************************************/
00009 /*Texture                                                                                  */
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 != &copy)
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 //  glActiveTextureARB(GL_TEXTURE0_ARB + currUnit);
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 //    glActiveTextureARB(GL_TEXTURE0_ARB + currUnit);
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            //(target == GL_TEXTURE_CUBE_MAP) ? loadCube(path.c_str(), clampS, clampT, magFilter, minFilter, mipmap) :
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 //    if(value == "CLAMP_TO_BORDER") return GL_CLAMP_TO_BORDER;
00238 //    if(value == "CLAMP_TO_EDGE")   return GL_CLAMP_TO_EDGE;
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 //    if(value == "TEXTURE_3D")       return GL_TEXTURE_3D;
00250 //    if(value == "TEXTURE_CUBE_MAP") return GL_TEXTURE_CUBE_MAP;
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 //         (clamp == GL_CLAMP_TO_EDGE  ) ? GL_CLAMP_TO_EDGE   :
00260 //         (clamp == GL_CLAMP_TO_BORDER) ? GL_CLAMP_TO_BORDER : GL_REPEAT;
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               /*(target == GL_TEXTURE_1D      ) ?*/ "TEXTURE_1D\"\n")// :
00293 //              (target == GL_TEXTURE_3D      ) ? "TEXTURE_3D\"\n" : "TEXTURE_CUBE_MAP\"\n")
00294           << "            path        = \"" << textureInfo->getMediaPath() << "\"\n"
00295           << "            mipmap      = \"true\" > \n"
00296           << "    <Wrap   s           = \"REPEAT\" \n"
00297 //          << ((target == GL_TEXTURE_3D)  ? "          r           = \"REPEAT\" \n" : "")
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 /*bool Texture::loadCube(const char* pathPXdotExtension,
00388                        GLuint clampS   , GLuint clampT,
00389                        GLuint magFilter, GLuint minFilter,
00390                        bool  mipmap)
00391 {
00392   std::string initialPath  = MediaPathManager::lookUpMediaPath(pathPXdotExtension);
00393   std::string temp;
00394 
00395   if(!initialPath.size())
00396     return Logger::writeErrorLog(std::string("Couldn't locate the texture file at <") +
00397                                  pathPXdotExtension + "> even with a look up");
00398   destroy();
00399   target = GL_TEXTURE_CUBE_MAP;
00400 
00401   std::string  verifiedPaths[6],
00402                faces[6]     = { "PX", "NX", "PY", "NY", "PZ", "NZ"},
00403                body;
00404 
00405   int extensionIndex = 0;
00406 
00407   for(int j = 0; j < int(initialPath.size()); j++)
00408     if(initialPath[j] == '.')
00409       extensionIndex = j;
00410 
00411   if(extensionIndex == 0)
00412     return false;
00413 
00414   std::string extension  = initialPath;
00415               extension += extensionIndex;
00416   size_t      strl        = 0;
00417 
00418   strl  = initialPath.size();
00419   strl -= extension.size() + 2;
00420 
00421   for(size_t i = 0; i< 6; i++)
00422   {
00423     for(size_t l = 0; l < strl; l++)
00424       verifiedPaths[i] += initialPath[l];
00425 
00426     verifiedPaths[i] += faces[i];
00427     verifiedPaths[i] += extension;
00428     temp = MediaPathManager::lookUpMediaPath(verifiedPaths[i].data());
00429 
00430     if(temp.size())
00431        verifiedPaths[i] = temp;
00432     else
00433       return Logger::writeErrorLog(std::string("Failed to locate cubemap texture face ") + verifiedPaths[i].data());
00434   }
00435 
00436   if(checkForRepeat(verifiedPaths[0].data()))
00437     return true;
00438 
00439   glGenTextures(1, &id);
00440   glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, id);
00441   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, getValidMagFilter(magFilter));
00442   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, getValidMinFilter(minFilter));
00443   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S,     getValidWrapMode(clampS));
00444   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T,     getValidWrapMode(clampT));
00445 
00446   for(int i = 0; i < 6; i++)
00447   {
00448     Image image;
00449 
00450     if(!image.load(verifiedPaths[i].data()))
00451     {
00452       destroy();
00453       return Logger::writeErrorLog(std::string("Failed at loading CubeMap face: ") + faces[i]);
00454     }
00455 
00456     if(!loadTextureFace(image, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, mipmap))
00457       return Logger::writeErrorLog(std::string("Failed while loading CubeMap face: ") + faces[i]);
00458 
00459     if(i == 5)
00460     {
00461       height = image.getHeight();
00462       width  = image.getWidth();
00463       depth  = 1;
00464     }
00465   }
00466 
00467   Logger::writeInfoLog(std::string("Loaded TextureCubeMap at ->") + initialPath);
00468   return  finalizeLoading(initialPath.c_str());
00469 }
00470 
00471 bool Texture::create2DShell(const char* name,
00472                             GLuint width    , GLuint height,
00473                             GLuint inFormat , GLuint format,
00474                             GLuint clampS   , GLuint clampT,
00475                             GLuint magFilter, GLuint minFilter)
00476 {
00477   if(!name)
00478     return Logger::writeErrorLog("2D Texture Shell must have a valid name");
00479 
00480   if(checkForRepeat(name))
00481     return true;
00482 
00483   destroy();
00484   target = GL_TEXTURE_2D;
00485 
00486   Logger::writeInfoLog(std::string("Loading new 2D Shell") + name);
00487 
00488   glGenTextures(1, &id);
00489   glBindTexture(GL_TEXTURE_2D, id);
00490 
00491   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getValidMagFilter(magFilter));
00492   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getValidMinFilter(minFilter));
00493   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     getValidWrapMode(clampS));
00494   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     getValidWrapMode(clampT));
00495   glTexImage2D(GL_TEXTURE_2D, 0, inFormat, width, height, 0, format, GL_UNSIGNED_BYTE, NULL);
00496 
00497   this->height = height;
00498   this->width  = width;
00499   depth        = 1;
00500 
00501   return finalizeLoading(name);
00502 }
00503 
00504 bool Texture::createNoise3D(const char* name, GLuint size)
00505 {
00506   if(!name)
00507     return Logger::writeErrorLog("Noise3D Texture must have a valid name");
00508 
00509   if(checkForRepeat(name))
00510     return true;
00511 
00512   destroy();
00513   target = GL_TEXTURE_3D;
00514 
00515   Logger::writeInfoLog(std::string("Creating new Noise3D Texture: ") + name);
00516 
00517 
00518   GLubyte *noise3DBuffer = new GLubyte[size * size * size * 4],
00519           *ptr           = NULL;
00520 
00521   Tuple3d  ni;
00522 
00523   double   inci= 0.0,
00524            incj = 0.0,
00525            inck = 0.0,
00526            amp  = 0.5;
00527 
00528   GLuint   f, i, j, k, inc,
00529            startFrequency = 4,
00530            frequency      = 4,
00531            numOctaves     = 4;
00532 
00533   for (f = 0, inc = 0; f < numOctaves; ++f, frequency *= 2, ++inc, amp *= 0.5)
00534   {
00535     Perlin::setNoiseFrequency(frequency);
00536         ptr = noise3DBuffer;
00537         ni.set(0.0, 0.0, 0.0);
00538 
00539                 inci = 1.0 / (size / frequency);
00540           for (i = 0; i < size; ++i, ni[0] += inci)
00541           {
00542       incj = 1.0 / (size / frequency);
00543       for (j = 0; j < size; ++j, ni[1] += incj)
00544       {
00545                         inck = 1.0 / (size / frequency);
00546                         for (k = 0; k < size; ++k, ni[2] += inck, ptr += 4)
00547           *(ptr + inc) = (GLubyte) (((Perlin::noise3(ni) + 1.0) * amp) * 128.0);
00548                   }
00549     }
00550         }
00551 
00552   glGenTextures(1, &id);
00553   glBindTexture(target, id);
00554   glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
00555   glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
00556   glTexParameterf(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
00557   glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00558   glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00559   glTexImage3DEXT(target, 0, GL_RGBA,
00560                   size, size, size,
00561                   0, GL_RGBA, GL_UNSIGNED_BYTE, noise3DBuffer);
00562   deleteArray(noise3DBuffer);
00563   return true;
00564 }
00565 
00566 bool Texture::createRectShell(const char* name,
00567                               GLuint width, GLuint height,
00568                               GLuint inFormat, GLuint format,
00569                               GLuint clampS  , GLuint clampT,
00570                               GLuint magFilter, GLuint minFilter)
00571 {
00572  if(!name)
00573     return Logger::writeErrorLog("Rectangle Texture Shell must have a valid name");
00574 
00575   if(checkForRepeat(name))
00576     return true;
00577 
00578   destroy();
00579   target = GL_TEXTURE_RECTANGLE_ARB;
00580 
00581   Logger::writeInfoLog(std::string("Loading new Rectangle Shell: ") + name);
00582 
00583   glGenTextures(1, &id);
00584   glBindTexture(GL_TEXTURE_RECTANGLE_ARB, id);
00585 
00586   glTexParameteri(target, GL_TEXTURE_MAG_FILTER, getValidMagFilter(magFilter));
00587   glTexParameteri(target, GL_TEXTURE_MIN_FILTER, getValidMinFilter(minFilter));
00588   glTexParameteri(target, GL_TEXTURE_WRAP_S,     getValidWrapMode(clampS));
00589   glTexParameteri(target, GL_TEXTURE_WRAP_T,     getValidWrapMode(clampT));
00590   glTexImage2D(target, 0, inFormat, width, height, 0, format, GL_UNSIGNED_BYTE, NULL);
00591 
00592   this->height = height;
00593   this->width  = width;
00594   depth        = 1;
00595 
00596   return finalizeLoading(name);
00597 }
00598 
00599 bool Texture::create1DShell(const char* name,
00600                             GLuint width    ,
00601                             GLuint inFormat , GLuint format,
00602                             GLuint clampS   , GLuint clampT,
00603                             GLuint magFilter, GLuint minFilter)
00604 {
00605   if(!name)
00606     return Logger::writeErrorLog("1D Texture Shell must have a valid name");
00607   destroy();
00608   target = GL_TEXTURE_1D;
00609 
00610 
00611   Logger::writeInfoLog(std::string("Loading new 1D Shell: ") + name);
00612 
00613   glGenTextures(1, &id);
00614   glBindTexture(target, id);
00615 
00616   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, getValidMagFilter(magFilter));
00617   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, getValidMinFilter(minFilter));
00618   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     getValidWrapMode(clampS));
00619   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T,     getValidWrapMode(clampT));
00620   glTexImage1D   (GL_TEXTURE_1D, 0, inFormat, width, 0, format, GL_UNSIGNED_BYTE, NULL);
00621 
00622   this->width  = width;
00623   height       = 1;
00624   depth        = 1;
00625 
00626   return finalizeLoading(name);
00627 }
00628 
00629 bool Texture::create3DShell(const char* name,
00630                             GLuint width, GLuint height, GLuint depth,
00631                             GLuint inFormat , GLuint format,
00632                             GLuint clampS   , GLuint clampT, GLuint clampR,
00633                             GLuint magFilter, GLuint minFilter)
00634 {
00635   if(!name)
00636     return Logger::writeErrorLog("3D Texture Shell must have a valid name");
00637   destroy();
00638   target = GL_TEXTURE_3D;
00639 
00640 
00641   Logger::writeInfoLog(std::string("Loading new 3D Shell: ") + name);
00642 
00643   glGenTextures(1, &id);
00644   glBindTexture(target, id);
00645 
00646   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, getValidMagFilter(magFilter));
00647   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, getValidMinFilter(minFilter));
00648   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,     getValidWrapMode(clampS));
00649   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,     getValidWrapMode(clampT));
00650   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,     getValidWrapMode(clampR));
00651   glTexImage3D   (GL_TEXTURE_3D, 0, inFormat, width, height, depth, 0, format, GL_UNSIGNED_BYTE, NULL);
00652 
00653   this->height = height;
00654   this->width  = width;
00655   this->depth  = depth;
00656 
00657   return finalizeLoading(name);
00658 }
00659 
00660 bool Texture::createCubeShell(const char* name,
00661                               GLuint size     ,
00662                               GLuint inFormat , GLuint format,
00663                               GLuint clampS   , GLuint clampT,
00664                               GLuint magFilter, GLuint minFilter)
00665 {
00666   if(!name)
00667     return Logger::writeErrorLog("Cube Texture Shell must have a valid name");
00668 
00669   if(checkForRepeat(name))
00670     return true;
00671 
00672   destroy();
00673   target = GL_TEXTURE_CUBE_MAP;
00674 
00675   glGenTextures(1, &id);
00676   glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, id);
00677 
00678   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, getValidMagFilter(magFilter));
00679   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, getValidMinFilter(minFilter));
00680   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S,     getValidWrapMode(clampS));
00681   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T,     getValidWrapMode(clampT));
00682 
00683   Logger::writeInfoLog(std::string("Loading Cube Shell: ") + name);
00684 
00685   for(int i = 0; i < 6; i++)
00686    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i,
00687                 0,
00688                 inFormat,
00689                 size,
00690                 size,
00691                 0,
00692                 format,
00693                 GL_UNSIGNED_BYTE,
00694                 NULL);
00695 
00696   this->height = size;
00697   this->width  = size;
00698   depth        = 1;
00699 
00700   return finalizeLoading(name);
00701 }
00702 
00703 bool Texture::createNormalizingCube(const char* name,
00704                                     GLuint size,
00705                                     bool   buildMipmaps)
00706 {
00707   size = getClosestPowerOfTwo(size);
00708 
00709   if(!name)
00710     return Logger::writeErrorLog("Normalized Cube Texture must have a valid name");
00711 
00712   if(checkForRepeat(name))
00713     return true;
00714 
00715   destroy();
00716 
00717   int levels = buildMipmaps ? int(log(double(size))/log(2.0)) : 1;
00718   target = GL_TEXTURE_CUBE_MAP;
00719   Logger::writeInfoLog(std::string("Creating Normalization Texture Cube Map: ") + name);
00720 
00721   GLuint minFilter = buildMipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
00722 
00723   glGenTextures(1, &id);
00724   glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, id);
00725 
00726   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00727   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00728   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00729   glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, minFilter);
00730 
00731 
00732   for(int currentLevel = 0; currentLevel < levels; currentLevel++)
00733   {
00734     float fX    = 0.0,
00735           fY    = 0.0,
00736                             fZ    = 0.0,
00737           oolen = 1.0;
00738           int x            =    0,
00739         y            =    0,
00740         z            =    0,
00741         mapSize      = size/(currentLevel + 1),
00742         halfMapSize  = mapSize/2;
00743 
00744         GLubyte *dataContainer = new GLubyte[mapSize*mapSize*3];
00745 
00746           for(y=0;y<mapSize;y++)
00747           {
00748                   for(z=0;z<mapSize;z++)
00749                 {
00750                     fX    = (float)halfMapSize;
00751         fY    = (float)halfMapSize-y;
00752         fZ    = (float)halfMapSize-z;
00753                     oolen = 1.0f/fastSquareRoot(fX*fX+fY*fY+fZ*fZ);
00754 
00755                           fX*=oolen;
00756                           fY*=oolen;
00757                           fZ*=oolen;
00758 
00759                         dataContainer[y*3*mapSize+z*3+0] = GLubyte((((fX)+1.0f)/2.0f)*255.0f);
00760                         dataContainer[y*3*mapSize+z*3+1] = GLubyte((((fY)+1.0f)/2.0f)*255.0f);
00761                           dataContainer[y*3*mapSize+z*3+2] = GLubyte((((fZ)+1.0f)/2.0f)*255.0f);
00762                 }
00763           }
00764 
00765           glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + 0,
00766                  currentLevel, GL_RGB8, mapSize, mapSize,
00767                  0, GL_RGB, GL_UNSIGNED_BYTE, dataContainer);
00768 
00769     for(y=0;y<mapSize;y++)
00770                 {
00771                         for(z=0;z<mapSize;z++)
00772                         {
00773                                 fX    =(float)-halfMapSize;
00774                                 fY    =(float)halfMapSize-y;
00775                                 fZ    =(float)z-halfMapSize;
00776                                 oolen = 1.0f/fastSquareRoot(fX*fX+fY*fY+fZ*fZ);
00777 
00778                                 fX*=oolen;
00779                                 fY*=oolen;
00780                                 fZ*=oolen;
00781                                 dataContainer[y*3*mapSize+z*3+0] = GLubyte((((fX)+1.0f)/2.0f)*255.0f);
00782                                 dataContainer[y*3*mapSize+z*3+1] = GLubyte((((fY)+1.0f)/2.0f)*255.0f);
00783                                 dataContainer[y*3*mapSize+z*3+2] = GLubyte((((fZ)+1.0f)/2.0f)*255.0f);
00784                         }
00785                 }
00786 
00787     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + 1,
00788                  currentLevel, GL_RGB8, mapSize, mapSize,
00789                  0, GL_RGB, GL_UNSIGNED_BYTE, dataContainer);
00790 
00791                 for(z=0;z<mapSize;z++)
00792                 {
00793                         for(x=0;x<mapSize;x++)
00794                         {
00795                                 fX    = (float)x-halfMapSize;
00796                                 fY    = (float)halfMapSize;
00797                                 fZ    = (float)z-halfMapSize;
00798                                 oolen = 1.0f/fastSquareRoot(fX*fX+fY*fY+fZ*fZ);
00799 
00800                                 fX*=oolen;
00801                                 fY*=oolen;
00802                                 fZ*=oolen;
00803                                 dataContainer[z*3*mapSize+x*3+0] = GLubyte((((fX)+1.0f)/2.0f)*255.0f);
00804                                 dataContainer[z*3*mapSize+x*3+1] = GLubyte((((fY)+1.0f)/2.0f)*255.0f);
00805                                 dataContainer[z*3*mapSize+x*3+2] = GLubyte((((fZ)+1.0f)/2.0f)*255.0f);
00806                         }
00807                 }
00808 
00809           glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + 2,
00810                  currentLevel, GL_RGB8, mapSize, mapSize,
00811                  0, GL_RGB, GL_UNSIGNED_BYTE, dataContainer);
00812 
00813                 for(z=0;z<mapSize;z++)
00814                 {
00815                         for(x=0;x<mapSize;x++)
00816                         {
00817                                 fX    = (float)x-halfMapSize;
00818                                 fY    = (float)-halfMapSize;
00819                                 fZ    = (float)halfMapSize-z;
00820                                 oolen = 1.0f/fastSquareRoot(fX*fX+fY*fY+fZ*fZ);
00821 
00822                                 fX*=oolen;
00823                                 fY*=oolen;
00824                                 fZ*=oolen;
00825 
00826                                 dataContainer[z*3*mapSize+x*3+0] = GLubyte((((fX)+1.0f)/2.0f)*255.0f);
00827                           dataContainer[z*3*mapSize+x*3+1] = GLubyte((((fY)+1.0f)/2.0f)*255.0f);
00828                                 dataContainer[z*3*mapSize+x*3+2] = GLubyte((((fZ)+1.0f)/2.0f)*255.0f);
00829                         }
00830                 }
00831 
00832     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + 3,
00833                  currentLevel, GL_RGB8, mapSize, mapSize,
00834                  0, GL_RGB, GL_UNSIGNED_BYTE, dataContainer);
00835 
00836                 for(y=0;y<mapSize;y++)
00837                 {
00838                         for(x=0;x<mapSize;x++)
00839                         {
00840                                 fX    = (float)x-halfMapSize;
00841                                 fY    = (float)halfMapSize - y;
00842                                 fZ    = (float)halfMapSize;
00843                                 oolen = 1.0f/fastSquareRoot(fX*fX+fY*fY+fZ*fZ);
00844 
00845                                 fX*=oolen;
00846                                 fY*=oolen;
00847                                 fZ*=oolen;
00848 
00849                                 dataContainer[y*3*mapSize+x*3+0] = GLubyte((((fX)+1.0f)/2.0f)*255.0f);
00850               dataContainer[y*3*mapSize+x*3+1] = GLubyte((((fY)+1.0f)/2.0f)*255.0f);
00851                                 dataContainer[y*3*mapSize+x*3+2] = GLubyte((((fZ)+1.0f)/2.0f)*255.0f);
00852                         }
00853                 }
00854 
00855     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + 4,
00856                  currentLevel, GL_RGB8, mapSize, mapSize,
00857                  0, GL_RGB, GL_UNSIGNED_BYTE, dataContainer);
00858 
00859                 for(y=0;y<mapSize;y++)
00860                 {
00861                         for(x=0;x<mapSize;x++)
00862                         {
00863                                 fX    = (float)halfMapSize - x;
00864                                 fY    = (float)halfMapSize - y;
00865                                 fZ    = (float)-halfMapSize;
00866                                 oolen = 1.0f/fastSquareRoot(fX*fX+fY*fY+fZ*fZ);
00867 
00868                                 fX*=oolen;
00869                                 fY*=oolen;
00870                                 fZ*=oolen;
00871 
00872                                 dataContainer[y*3*mapSize+x*3+0] = GLubyte((((fX)+1.0f)/2.0f)*255.0f);
00873                                 dataContainer[y*3*mapSize+x*3+1] = GLubyte((((fY)+1.0f)/2.0f)*255.0f);
00874                                 dataContainer[y*3*mapSize+x*3+2] = GLubyte((((fZ)+1.0f)/2.0f)*255.0f);
00875                         }
00876                 }
00877           glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + 5,
00878                  currentLevel, GL_RGB8, mapSize, mapSize,
00879                  0, GL_RGB, GL_UNSIGNED_BYTE, dataContainer);
00880 
00881           deleteArray(dataContainer);
00882   }
00883   this->height = size;
00884   this->width  = size;
00885   depth        = 1;
00886   return finalizeLoading(name);
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) )//&&  (this->target != GL_TEXTURE_CUBE_MAP))
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 //    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
00907 //    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
00908 //    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
00909 //    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
00910 //    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
00911  //   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
00912 //      quickFix = GL_TEXTURE_CUBE_MAP_ARB;
00913 //     break;
00914   }
00915 
00916   /*switch(image.getInternalFormat())
00917   {
00918     case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
00919       if(GLEE_ARB_texture_compression &&
00920          GLEE_EXT_texture_compression_s3tc)
00921       {
00922 
00923         if(GLEE_SGIS_generate_mipmap && mipmap)
00924         {
00925           glTexParameteri(quickFix, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
00926           glTexParameteri(quickFix, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
00927         }
00928 
00929         glCompressedTexImage2DARB(target,
00930                                   0,
00931                                   GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
00932                                   image.getWidth(), image.getHeight(),
00933                                   0,
00934                                   ((image.getWidth() +3)/4)*((image.getHeight() +3)/4)*16,
00935                                   image.getDataBuffer());
00936       }
00937       else
00938       {
00939         destroy();
00940         return Logger::writeErrorLog("GL_EXT_texture_compression_s3tc not supported");
00941       }
00942     break;
00943 
00944     case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
00945       if(GLEE_ARB_texture_compression &&
00946          GLEE_EXT_texture_compression_s3tc)
00947       {
00948 
00949         if(GLEE_SGIS_generate_mipmap && mipmap)
00950         {
00951           glTexParameteri(quickFix, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
00952           glTexParameteri(quickFix, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
00953         }
00954 
00955         glCompressedTexImage2DARB(target,
00956                                   0,
00957                                   GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
00958                                   image.getWidth(), image.getHeight(),
00959                                   0,
00960                                   ((image.getWidth() +3)/4)*((image.getHeight() +3)/4)*16,
00961                                   image.getDataBuffer());
00962       }
00963       else
00964       {
00965         destroy();
00966         return Logger::writeErrorLog("GL_EXT_texture_compression_s3tc not supported");
00967       }
00968     break;
00969 
00970     case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
00971       if(GLEE_ARB_texture_compression &&
00972          GLEE_EXT_texture_compression_s3tc)
00973       {
00974         if(GLEE_SGIS_generate_mipmap && mipmap)
00975         {
00976           glTexParameteri(quickFix, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
00977           glTexParameteri(quickFix, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
00978         }
00979 
00980         glCompressedTexImage2DARB(target,
00981                                   0,
00982                                   GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
00983                                   image.getWidth(), image.getHeight(),
00984                                   0,
00985                                   ((image.getWidth() +3)/4)*((image.getHeight() +3)/4)*8,
00986                                   image.getDataBuffer());
00987       }
00988       else
00989       {
00990         destroy();
00991         return Logger::writeErrorLog("GL_EXT_texture_compression_s3tc not supported");
00992       }
00993     break;
00994 
00995     default:*/
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 /*TexturesManager                                                                          */
01015 /*Info:                                                                                    */
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 /*Image                                                                                    */
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 /*JPEG Loader                                                                              */
01260 /*Info:                                                                                    */
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 /*PNG Loader                                                                               */
01980 /*Info:                                                                                    */
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         // Here is some code to save the loaded png as a custom ppma file.
02003         FILE * inFile = fopen("ElementsPPMA.ppm", "wb");
02004     fprintf( inFile, "P6A\n%u %u \n255\n", info.Width, info.Height );
02005         int memSize = info.Width * info.Height * 4;
02006         for (int i = 0; i < memSize; i++) fputc( info.Data[i], inFile);
02007     fclose(inFile);*/
02008 
02009   delete info.Data;
02010   delete info.Palette;
02011 
02012   return true;
02013 }
02014 
02015 #endif //GLWX_PNG_SUPPORT
02016 
02017 /*******************************************************************************************/
02018 /*PPM Loader                                                                               */
02019 /*Info:                                                                                    */
02020 /*                                                                                         */
02021 /*******************************************************************************************/
02022 
02023 bool Image::loadPPM(const char* filename)
02024 {
02025 
02026 
02027         char buffer[100]; //Input buffer
02028     GLubyte *theTexture; //Texture buffer pointer
02029         unsigned char c; //Input character
02030         int w, h, maxVal, pixelSize; //Image characteristics from ppm file
02031 
02032 
02033         //Try to open the file for reading
02034         FILE * inFile = fopen(filename, "rb");
02035         if (inFile == NULL)
02036         return Logger::writeErrorLog(std::string("Could not find file -> ") + filename);
02037 
02038         //Read file type identifier (magic number)
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         //Read image size
02049         do fgets(buffer, sizeof (buffer), inFile);
02050         while (buffer[0] == '#');
02051         sscanf (buffer, "%d %d", &w, &h);
02052 
02053         //Read maximum pixel value (usually 255)
02054         do fgets (buffer, sizeof (buffer), inFile);
02055         while (buffer[0] == '#');
02056         sscanf (buffer, "%d", &maxVal);
02057 
02058         //Allocate RGBA texture buffer
02059         int memSize = w * h * 4;
02060         theTexture = new unsigned char[memSize];
02061 
02062         // read RGB data and set alpha value
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; //Set alpha to opaque
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 /*TGA loader                                                                               */
02086 /*Info:                                                                                    */
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];           //Used to compare TGA header
02097 
02098   FILE * file = fopen(filename, "rb");    //Open the TGA file
02099 
02100   if(file==NULL )                         //Does the file exist?
02101     return Logger::writeErrorLog(std::string("Could not find file -> ") + filename);
02102 
02103 
02104   //read the header
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];           //Used to compare TGA header
02130   unsigned char   header[6];              //First 6 useful bytes of the header
02131 
02132   FILE * file = fopen(filename, "rb");        //Open the TGA file
02133 
02134   if(file == NULL)                //Does the file exist?
02135     return Logger::writeErrorLog(std::string("Could not find file at -> ") + filename);
02136 
02137   if(fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)|| //Are there 12 bytes to read?
02138     memcmp(TGAHeader, TGAcompare, sizeof(TGAHeader))!=0 ||          //Is the header correct?
02139     fread(header, 1, sizeof(header), file)!=sizeof(header))   //Read next 6 bytes
02140   {
02141     fclose(file);               //If anything else failed, close the file
02142     return Logger::writeErrorLog(std::string("Could not process file at -> ") + filename);
02143   }
02144 
02145   //save data into class member variables
02146   setWidth(header[1]*256+header[0]);
02147   setHeight(header[3]*256+header[2]);
02148   setComponentsCount(header[4]/8);
02149 
02150   if(width  <=0 || //if width <=0
02151      height <=0 || //or height<=0
02152      header[4] != 8)    //bpp not 8
02153   {
02154     fclose(file);                     //close the 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   //make space for palette
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   //load the palette
02168   fread(palette, 256*3, 1, file);
02169 
02170   //allocate space for color indices
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   //load indices
02177   fread(indices, 1, width*height, file);
02178 
02179   //close the file
02180   fclose(file);
02181 
02182   if(dataBuffer)
02183     deleteArray(dataBuffer);
02184 
02185   //allocate space for the image data
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   //calculate the color values
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];//BGR
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}; //Uncompressed TGA header
02210   unsigned char TGAcompare[12];           //Used to compare TGA header
02211   unsigned char header[6];              //First 6 useful bytes of the header
02212   unsigned int  imageSize;              //Stores Image size when in RAM
02213 
02214   FILE * file = fopen(filename, "rb");        //Open the TGA file
02215 
02216   if(file == NULL)                //Does the file exist?
02217     return Logger::writeErrorLog(std::string("Could not load file at -> ") + filename);
02218 
02219   if( fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)||  //Are there 12 bytes to read?
02220     memcmp(TGAheader, TGAcompare, sizeof(TGAheader))!=0 ||          //Is the header correct?
02221     fread(header, 1, sizeof(header), file)!=sizeof(header))   //Read next 6 bytes
02222   {
02223     fclose(file);               //If anything else failed, close the file
02224     return Logger::writeErrorLog(std::string("Could not process file at -> ") + filename);
02225   }
02226 
02227   //save data into class member variables
02228   setWidth(header[1]*256+header[0]);           //determine the image width
02229   setHeight(header[3]*256+header[2]);            //determine image height
02230   setComponentsCount(header[4]/3);
02231 
02232   if(width <=0 ||                      //if width <=0
02233      height<=0 ||                      //or height<=0
02234      (header[4] !=24 && header[4]!=32))                   //bpp not 24 or 32
02235   {
02236     fclose(file);                     //close the 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   //set format
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)                     //Does the storage memory exist?
02258   {
02259     fclose(file);
02260     return Logger::writeErrorLog(std::string("Unable to allocate memory for image ->") + filename);
02261   }
02262 
02263   //read in the image data
02264   fread(dataBuffer, 1, imageSize, file);
02265   fclose(file);
02266   return true;
02267 }
02268 
02269 //load a compressed TGA texture (24 or 32 bpp)
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};  //Compressed TGA header
02273   unsigned char TGAcompare[12];           //Used to compare TGA header
02274   unsigned char header[6];              //First 6 useful bytes of the header
02275   unsigned int  bytesPerPixel;            //bytes per pixel
02276   unsigned int  imageSize;              //Stores Image size when in RAM
02277 
02278   FILE * file = fopen(filename, "rb");        //Open the TGA file
02279 
02280   if(file == NULL)                //Does the file exist?
02281     return Logger::writeErrorLog(std::string("Could not load file at -> ") + filename);
02282 
02283 
02284   if( fread(TGAcompare, 1, sizeof(TGAcompare), file)!=sizeof(TGAcompare)||  //Are there 12 bytes to read?
02285     memcmp(TGAheader, TGAcompare, sizeof(TGAheader))!=0 ||          //Is the header correct?
02286     fread(header, 1, sizeof(header), file)!=sizeof(header))   //Read next 6 bytes
02287   {
02288     fclose(file);               //If anything else failed, close the file
02289     return Logger::writeErrorLog(std::string("Could not process file at -> ") + filename);
02290   }
02291 
02292   //save data into class member variables
02293   setWidth(header[1]*256+header[0]);            //determine the image width
02294   setHeight(header[3]*256+header[2]);            //determine image height
02295   setComponentsCount(header[4]/8);
02296   bytesPerPixel = getComponentsCount();
02297 
02298   if(width  <=0 ||                      //if width <=0
02299      height <=0 ||                      //or height<=0
02300      (header[4] !=24 && header[4] !=32))                   //bpp not 24 or 32
02301   {
02302     fclose(file);                     //close the 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   //set format
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)                         //Does the storage memory exist?
02325   {
02326     fclose(file);
02327     return Logger::writeErrorLog(std::string("Unable to allocate memory for image -> ") + filename);
02328   }
02329 
02330   //read in the image data
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) //Read raw color values
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         //transfer pixel color to data (swapping r and b values)
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  //chunkHeader>=128
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         //transfer pixel color to data (swapping r and b values)
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 }

Generated on Wed Dec 5 20:32:03 2007 for GLWX by  doxygen 1.5.3