2 // This program is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU General Public License as
4 // published by the Free Software Foundation; either version 2 of the
5 // License, or (at your option) any later version.
7 // This program is distributed in the hope that it will be useful, but
8 // WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 // General Public License for more details.
12 // You should have received a copy of the GNU General Public License
13 // along with this program; if not, write to the Free Software
14 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 // From the OpenSceneGraph distribution ReaderWriterRGB.cpp
17 // Reader for sgi's .rgb format.
18 // specification can be found at http://local.wasp.uwa.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html
28 #include "FGRGBTextureLoader.hxx"
38 typedef struct _rawImageRec
40 unsigned short imagic;
43 unsigned short sizeX, sizeY, sizeZ;
44 unsigned long min, max;
45 unsigned long wasteBytes;
47 unsigned long colorMap;
49 unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
56 typedef unsigned char * BytePtr;
58 bool needsBytesSwapped()
62 char testByte[sizeof(int)];
64 endianTest.testWord = 1;
65 if( endianTest.testByte[0] == 1 )
72 inline void swapBytes( T &s )
74 if( sizeof( T ) == 1 )
78 BytePtr sptr = (BytePtr)&s;
79 BytePtr dptr = &(((BytePtr)&d)[sizeof(T)-1]);
81 for( unsigned int i = 0; i < sizeof(T); i++ )
82 *(sptr++) = *(dptr--);
93 swapBytes( wasteBytes );
96 swapBytes( colorMap );
100 static void ConvertShort(unsigned short *array, long length)
102 unsigned long b1, b2;
105 ptr = (unsigned char *)array;
110 *array++ = (unsigned short) ((b1 << 8) | (b2));
114 static void ConvertLong(GLuint *array, long length)
116 unsigned long b1, b2, b3, b4;
119 ptr = (unsigned char *)array;
126 *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
131 static void RawImageClose(rawImageRec *raw)
136 if (raw->tmp) delete [] raw->tmp;
137 if (raw->tmpR) delete [] raw->tmpR;
138 if (raw->tmpG) delete [] raw->tmpG;
139 if (raw->tmpB) delete [] raw->tmpB;
140 if (raw->tmpA) delete [] raw->tmpA;
142 if (raw->rowStart) delete [] raw->rowStart;
143 if (raw->rowSize) delete [] raw->rowSize;
150 static rawImageRec *RawImageOpen(std::istream& fin)
160 raw = new rawImageRec;
163 // notify(WARN)<< "Out of memory!"<< std::endl;
167 //Set istream pointer
170 endianTest.testWord = 1;
171 if (endianTest.testByte[0] == 1)
173 raw->swapFlag = GL_TRUE;
177 raw->swapFlag = GL_FALSE;
180 fin.read((char*)raw,12);
186 ConvertShort(&raw->imagic, 6);
189 raw->tmp = raw->tmpR = raw->tmpG = raw->tmpB = raw->tmpA = 0L;
192 raw->bpc = (raw->type & 0x00FF);
194 raw->tmp = new unsigned char [raw->sizeX*256*raw->bpc];
195 if (raw->tmp == NULL )
197 // notify(FATAL)<< "Out of memory!"<< std::endl;
202 if( raw->sizeZ >= 1 )
204 if( (raw->tmpR = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
206 // notify(FATAL)<< "Out of memory!"<< std::endl;
211 if( raw->sizeZ >= 2 )
213 if( (raw->tmpG = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
215 // notify(FATAL)<< "Out of memory!"<< std::endl;
220 if( raw->sizeZ >= 3 )
222 if( (raw->tmpB = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
224 // notify(FATAL)<< "Out of memory!"<< std::endl;
231 if( (raw->tmpA = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
233 // notify(FATAL)<< "Out of memory!"<< std::endl;
239 if ((raw->type & 0xFF00) == 0x0100)
241 unsigned int ybyz = raw->sizeY * raw->sizeZ;
242 if ( (raw->rowStart = new GLuint [ybyz]) == NULL )
244 // notify(FATAL)<< "Out of memory!"<< std::endl;
249 if ( (raw->rowSize = new GLint [ybyz]) == NULL )
251 // notify(FATAL)<< "Out of memory!"<< std::endl;
255 x = ybyz * sizeof(GLuint);
256 raw->rleEnd = 512 + (2 * x);
257 fin.seekg(512,std::ios::beg);
258 fin.read((char*)raw->rowStart,x);
259 fin.read((char*)raw->rowSize,x);
262 ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
263 ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
270 static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
272 unsigned char *iPtr, *oPtr;
273 unsigned short pixel;
275 unsigned short *tempShort;
277 if ((raw->type & 0xFF00) == 0x0100)
279 raw->file->seekg((long) raw->rowStart[y+z*raw->sizeY], std::ios::beg);
280 raw->file->read((char*)raw->tmp, (unsigned int)raw->rowSize[y+z*raw->sizeY]);
290 tempShort = reinterpret_cast<unsigned short*>(iPtr);
293 iPtr = reinterpret_cast<unsigned char *>(tempShort);
297 ConvertShort(&pixel, 1);
299 count = (int)(pixel & 0x7F);
301 // limit the count value to the remiaing row size
302 if (oPtr + count*raw->bpc > buf + raw->sizeX*raw->bpc)
304 count = ( (buf + raw->sizeX*raw->bpc) - oPtr ) / raw->bpc;
320 tempShort = reinterpret_cast<unsigned short*>(iPtr);
323 iPtr = reinterpret_cast<unsigned char *>(tempShort);
325 ConvertShort(&pixel, 1);
327 tempShort = reinterpret_cast<unsigned short*>(oPtr);
330 oPtr = reinterpret_cast<unsigned char *>(tempShort);
342 tempShort = reinterpret_cast<unsigned short*>(iPtr);
345 iPtr = reinterpret_cast<unsigned char *>(tempShort);
348 ConvertShort(&pixel, 1);
355 tempShort = reinterpret_cast<unsigned short*>(oPtr);
358 oPtr = reinterpret_cast<unsigned char *>(tempShort);
366 raw->file->seekg(512+(y*raw->sizeX*raw->bpc)+(z*raw->sizeX*raw->sizeY*raw->bpc),std::ios::beg);
367 raw->file->read((char*)buf, raw->sizeX*raw->bpc);
368 if(raw->swapFlag && raw->bpc != 1){
369 ConvertShort(reinterpret_cast<unsigned short*>(buf), raw->sizeX);
375 static void RawImageGetData(rawImageRec *raw, unsigned char **data )
379 unsigned short *tempShort;
381 // // round the width to a factor 4
382 // int width = (int)(floorf((float)raw->sizeX/4.0f)*4.0f);
383 // if (width!=raw->sizeX) width += 4;
387 // osg::notify(osg::INFO)<<"raw->sizeX = "<<raw->sizeX<<std::endl;
388 // osg::notify(osg::INFO)<<"raw->sizeY = "<<raw->sizeY<<std::endl;
389 // osg::notify(osg::INFO)<<"raw->sizeZ = "<<raw->sizeZ<<std::endl;
390 // osg::notify(osg::INFO)<<"raw->bpc = "<<raw->bpc<<std::endl;
392 *data = new unsigned char [(raw->sizeX)*(raw->sizeY)*(raw->sizeZ)*(raw->bpc)];
395 for (i = 0; i < (int)(raw->sizeY); i++)
397 if( raw->sizeZ >= 1 )
398 RawImageGetRow(raw, raw->tmpR, i, 0);
399 if( raw->sizeZ >= 2 )
400 RawImageGetRow(raw, raw->tmpG, i, 1);
401 if( raw->sizeZ >= 3 )
402 RawImageGetRow(raw, raw->tmpB, i, 2);
403 if( raw->sizeZ >= 4 )
404 RawImageGetRow(raw, raw->tmpA, i, 3);
405 for (j = 0; j < (int)(raw->sizeX); j++)
408 if( raw->sizeZ >= 1 )
409 *ptr++ = *(raw->tmpR + j);
410 if( raw->sizeZ >= 2 )
411 *ptr++ = *(raw->tmpG + j);
412 if( raw->sizeZ >= 3 )
413 *ptr++ = *(raw->tmpB + j);
414 if( raw->sizeZ >= 4 )
415 *ptr++ = *(raw->tmpA + j);
417 if( raw->sizeZ >= 1 )
419 tempShort = reinterpret_cast<unsigned short*>(ptr);
420 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpR) + j);
422 ptr = reinterpret_cast<unsigned char *>(tempShort);
424 if( raw->sizeZ >= 2 )
426 tempShort = reinterpret_cast<unsigned short*>(ptr);
427 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpG) + j);
429 ptr = reinterpret_cast<unsigned char *>(tempShort);
431 if( raw->sizeZ >= 3 )
433 tempShort = reinterpret_cast<unsigned short*>(ptr);
434 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpB) + j);
436 ptr = reinterpret_cast<unsigned char *>(tempShort);
438 if( raw->sizeZ >= 4 )
440 tempShort = reinterpret_cast<unsigned short*>(ptr);
441 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpA) + j);
443 ptr = reinterpret_cast<unsigned char *>(tempShort);
447 // // pad the image width with blanks to bring it up to the rounded width.
448 // for(;j<width;++j) *ptr++ = 0;
453 // supportsExtension("rgb","rgb image format");
454 // supportsExtension("rgba","rgba image format");
455 // supportsExtension("sgi","sgi image format");
456 // supportsExtension("int","int image format");
457 // supportsExtension("inta","inta image format");
458 // supportsExtension("bw","bw image format");
460 GLuint readRGBStream(std::istream& fin)
464 if( (raw = RawImageOpen(fin)) == NULL )
474 int internalFormat = raw->sizeZ == 3 ? GL_RGB5 :
475 raw->sizeZ == 4 ? GL_RGB5_A1 : GL_RGB;
477 // int internalFormat = raw->sizeZ;
479 unsigned int pixelFormat =
480 raw->sizeZ == 1 ? GL_LUMINANCE :
481 raw->sizeZ == 2 ? GL_LUMINANCE_ALPHA :
482 raw->sizeZ == 3 ? GL_RGB :
483 raw->sizeZ == 4 ? GL_RGBA : (GLenum)-1;
484 GLint component = raw->sizeZ;
486 unsigned int dataType = raw->bpc == 1 ? GL_UNSIGNED_BYTE :
490 RawImageGetData(raw, &data);
494 glGenTextures(1, &texture);
495 glBindTexture(GL_TEXTURE_2D, texture);
496 gluBuild2DMipmaps( GL_TEXTURE_2D, component, s, t, pixelFormat, dataType, (GLvoid*)data );
497 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
498 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );
504 GLuint FGRGBTextureLoader::loadTexture( const std::string & filename )
506 GLuint texture = NOTEXTURE;
507 std::ifstream istream(filename.c_str(), std::ios::in | std::ios::binary );
508 texture = readRGBStream(istream);