00001 #include "texture.h"
00002
00015 #include <glt/gl.h>
00016 #include <glt/glu.h>
00017 #include <glt/error.h>
00018
00019 #include <misc/compress.h>
00020 #include <misc/image.h>
00021
00022 #if !defined(NDEBUG)
00023 #include <iostream>
00024 #endif
00025
00026 #include <cassert>
00027 #include <cstdio>
00028 #include <string>
00029 using namespace std;
00030
00032
00033 GltTexture::GltTexture(const GLenum target)
00034 :
00035 _target(target),
00036 _components(0),
00037 _width(0),
00038 _height(0),
00039 _border(0),
00040 _format(0),
00041 _type(0),
00042 _alignment(0),
00043 _wrapS(GL_REPEAT),
00044 _wrapT(GL_REPEAT),
00045 _filterMin(GL_LINEAR),
00046 _filterMag(GL_LINEAR),
00047 _gamma(1.0),
00048 _hue(0.0),
00049 _saturation(0.0),
00050 _value(0.0),
00051
00052 _id(0)
00053 {
00054 }
00055
00056 GltTexture::GltTexture(const GltTexture &)
00057 {
00058
00059 assert(0);
00060 }
00061
00062 GltTexture::~GltTexture()
00063 {
00064 #if !defined(NDEBUG)
00065 if (_id)
00066 cerr << "WARNING: Potential OpenGL texture leak (" << this << ")" << endl;
00067 #endif
00068
00069 clear();
00070 }
00071
00072 GltTexture &
00073 GltTexture::operator=(const GltTexture &)
00074 {
00075
00076 assert(0);
00077 return *this;
00078 }
00079
00080 void
00081 GltTexture::setWrap(const GLenum s,const GLenum t)
00082 {
00083 _wrapS = s;
00084 _wrapT = t;
00085
00086 if (_id!=0)
00087 {
00088 glPushAttrib(GL_TEXTURE_BIT);
00089 glBindTexture(_target,_id);
00090 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,_wrapS);
00091 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,_wrapT);
00092 glPopAttrib();
00093 }
00094 }
00095
00096 void
00097 GltTexture::setFilter(const GLenum min,const GLenum mag)
00098 {
00099 _filterMin = min;
00100 _filterMag = mag;
00101
00102 if (_id!=0)
00103 {
00104 glPushAttrib(GL_TEXTURE_BIT);
00105 glBindTexture(_target,_id);
00106 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,_filterMin);
00107 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,_filterMag);
00108 glPopAttrib();
00109 }
00110 }
00111
00112 void
00113 GltTexture::setGamma(const real gamma)
00114 {
00115 _gamma = gamma;
00116 }
00117
00118 void
00119 GltTexture::setHSVAdjust(const real hue,const real saturation,const real value)
00120 {
00121 _hue = hue;
00122 _saturation = saturation;
00123 _value = value;
00124 }
00125
00126 bool
00127 GltTexture::init(const void *data,const bool mipmap)
00128 {
00129 GLERROR
00130
00131 clear();
00132
00133 if (!data)
00134 return true;
00135
00136
00137
00138 int type,width,height,alignment,compressed;
00139 void *pixels = getHeader((const byte *) data,type,width,height,alignment,compressed);
00140 bool deletePixels = false;
00141
00142
00143
00144 assert(pixels);
00145
00146 if (pixels)
00147 {
00148 switch (type)
00149 {
00150 case TEXTURE_TYPE_RGB: _components = 3; _format = GL_RGB; break;
00151 case TEXTURE_TYPE_RGBA: _components = 4; _format = GL_RGBA; break;
00152 case TEXTURE_TYPE_GREY: _components = 1; _format = GL_LUMINANCE; break;
00153 case TEXTURE_TYPE_GREYA: _components = 2; _format = GL_LUMINANCE_ALPHA; break;
00154 case TEXTURE_TYPE_ALPHA: _components = 1; _format = GL_ALPHA; break;
00155 case TEXTURE_TYPE_BITMAP: _components = 1; _format = TEXTURE_TYPE_BITMAP;break;
00156 case TEXTURE_TYPE_INDEXED_RGB: _components = 3; _format = GL_RGB; break;
00157 case TEXTURE_TYPE_INDEXED_RGBA: _components = 4; _format = GL_RGBA; break;
00158 default: assert(0); break;
00159 }
00160
00161 if (compressed)
00162 {
00163 string tmp;
00164 bool ok = decompress(tmp,pixels);
00165
00166 assert(ok);
00167 assert(tmp.size());
00168
00169 if (ok && tmp.size())
00170 {
00171 const int n = width*height*_components;
00172 pixels = new unsigned char[n];
00173 deletePixels = true;
00174
00175 if (type==TEXTURE_TYPE_INDEXED_RGB)
00176 {
00177 string rgb;
00178 indexed2rgb(rgb,tmp);
00179
00180 if (_gamma!=1.0)
00181 adjustGamma(rgb,_gamma);
00182
00183 if (_hue!=0.0 || _saturation!=0.0 || _value!=0.0)
00184 adjustHSV(rgb,width,height,_hue,_saturation,_value);
00185
00186 memcpy(pixels,rgb.c_str(),n);
00187
00188
00189 }
00190 else
00191 {
00192 if (_gamma!=1.0)
00193 adjustGamma(tmp,_gamma);
00194
00195 if (_hue!=0.0 || _saturation!=0.0 || _value!=0.0)
00196 adjustHSV(tmp,width,height,_hue,_saturation,_value);
00197
00198 memcpy(pixels,tmp.c_str(),n);
00199 }
00200 }
00201 }
00202
00203
00204
00205 _width = width;
00206 _height = height;
00207
00208 _type = GL_UNSIGNED_BYTE;
00209 }
00210
00211 assert(_components!=0);
00212
00213 if (pixels && _components!=0)
00214 {
00215 GLERROR
00216
00217 if (_target==GL_TEXTURE_2D)
00218 {
00219 glGenTextures(1,&_id);
00220 glBindTexture(GL_TEXTURE_2D,_id);
00221 glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
00222 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,_filterMin);
00223 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,_filterMag);
00224 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _wrapS);
00225 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _wrapT);
00226 }
00227
00228 if (mipmap)
00229 gluBuild2DMipmaps(_target,_components,_width,_height,_format,_type,pixels);
00230 else
00231 glTexImage2D(_target,0,_components,_width,_height,_border,_format,_type,pixels);
00232
00233 if (deletePixels)
00234 delete [] (unsigned char *) pixels;
00235
00236 GLERROR
00237
00238 return true;
00239 }
00240
00241 GLERROR
00242
00243 return false;
00244 }
00245
00246 bool
00247 GltTexture::init(const GLsizei width,const GLsizei height,const std::string &image,const bool mipmap)
00248 {
00249 clear();
00250
00251 GLenum mode = 0;
00252 int channels = 0;
00253
00254 if (width*height == (GLsizei)image.size()) { mode = GL_LUMINANCE; channels = 1; }
00255 if (width*height*2== (GLsizei)image.size()) { mode = GL_LUMINANCE_ALPHA; channels = 2; }
00256 if (width*height*3== (GLsizei)image.size()) { mode = GL_RGB; channels = 3; }
00257 if (width*height*4== (GLsizei)image.size()) { mode = GL_RGBA; channels = 3; }
00258
00259 if (!mode || !channels)
00260 return false;
00261
00262 if (_target==GL_TEXTURE_2D)
00263 {
00264 glGenTextures(1,&_id);
00265 glBindTexture(GL_TEXTURE_2D,_id);
00266 glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
00267 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,_filterMin);
00268 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,_filterMag);
00269 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _wrapS);
00270 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _wrapT);
00271 }
00272
00273 if (mipmap)
00274 gluBuild2DMipmaps(_target,channels,width,height,mode,GL_UNSIGNED_BYTE,image.data());
00275 else
00276 glTexImage2D(_target,0,channels,width,height,0,mode,GL_UNSIGNED_BYTE,image.data());
00277
00278 return true;
00279 }
00280
00281 bool
00282 GltTexture::init(const GLsizei width,const GLsizei height,const byte *image,const GLsizei channels,const bool mipmap)
00283 {
00284 clear();
00285
00286 GLenum mode = 0;
00287
00288 switch (channels)
00289 {
00290 case 1: mode = GL_LUMINANCE; break;
00291 case 2: mode = GL_LUMINANCE_ALPHA; break;
00292 case 3: mode = GL_RGB; break;
00293 case 4: mode = GL_RGBA; break;
00294 default: return false;
00295 }
00296
00297 if (_target==GL_TEXTURE_2D)
00298 {
00299 glGenTextures(1,&_id);
00300 glBindTexture(GL_TEXTURE_2D,_id);
00301 glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
00302 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,_filterMin);
00303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,_filterMag);
00304 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _wrapS);
00305 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _wrapT);
00306 }
00307
00308 if (mipmap)
00309 gluBuild2DMipmaps(_target,channels,width,height,mode,GL_UNSIGNED_BYTE,image);
00310 else
00311 glTexImage2D(_target,0,channels,width,height,0,mode,GL_UNSIGNED_BYTE,image);
00312
00313 return true;
00314 }
00315
00316 void
00317 GltTexture::clear()
00318 {
00319 if (_id)
00320 glDeleteTextures(1,&_id);
00321
00322 _id = 0;
00323 _components = 0;
00324 _width = 0;
00325 _height = 0;
00326 _border = 0;
00327 _format = 0;
00328 _type = 0;
00329 _alignment = 0;
00330 }
00331
00332 void
00333 GltTexture::set() const
00334 {
00335 if (_id!=0 && _target==GL_TEXTURE_2D)
00336 glBindTexture(_target,_id);
00337 }
00338
00339 const GLsizei &GltTexture::width() const { return _width; }
00340 const GLsizei &GltTexture::height() const { return _height; }
00341 const GLuint GltTexture::id() const { return _id; }
00342
00344
00345
00346
00347 bool GltTexture::makeHeader
00348 (
00349 string &header,
00350 const int type,
00351 const int width,
00352 const int height,
00353 const int alignment,
00354 const int compressed
00355 )
00356 {
00357
00358
00359 char buffer[5+11+11+11+11+11];
00360 sprintf(buffer,"GLTT %u %u %u %u %u",type,width,height,alignment,compressed);
00361 header = buffer;
00362 header += '\0';
00363
00364 return true;
00365 }
00366
00367
00368
00369 void *GltTexture::getHeader
00370 (
00371 const void * const data,
00372 int &type,
00373 int &width,
00374 int &height,
00375 int &alignment,
00376 int &compressed
00377 )
00378 {
00379 const char * const h = (const char * const) data;
00380
00381 if (h[0]=='G' && h[1]=='L' && h[2]=='T' && h[3]=='T' && h[4]==' ')
00382 {
00383 if (sscanf(h+5,"%i %i %i %i %i",&type,&width,&height,&alignment,&compressed)==5)
00384 return (void *) (h + strlen(h) + 1);
00385 }
00386
00387 return NULL;
00388 }
00389