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"
30 #include <OpenGL/gl.h>
31 #include <GLUT/glut.h>
43 typedef struct _rawImageRec
45 unsigned short imagic;
48 unsigned short sizeX, sizeY, sizeZ;
49 unsigned long min, max;
50 unsigned long wasteBytes;
52 unsigned long colorMap;
54 unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
61 typedef unsigned char * BytePtr;
63 bool needsBytesSwapped()
67 char testByte[sizeof(int)];
69 endianTest.testWord = 1;
70 if( endianTest.testByte[0] == 1 )
77 inline void swapBytes( T &s )
79 if( sizeof( T ) == 1 )
83 BytePtr sptr = (BytePtr)&s;
84 BytePtr dptr = &(((BytePtr)&d)[sizeof(T)-1]);
86 for( unsigned int i = 0; i < sizeof(T); i++ )
87 *(sptr++) = *(dptr--);
98 swapBytes( wasteBytes );
101 swapBytes( colorMap );
105 static void ConvertShort(unsigned short *array, long length)
107 unsigned long b1, b2;
110 ptr = (unsigned char *)array;
115 *array++ = (unsigned short) ((b1 << 8) | (b2));
119 static void ConvertLong(GLuint *array, long length)
121 unsigned long b1, b2, b3, b4;
124 ptr = (unsigned char *)array;
131 *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
136 static void RawImageClose(rawImageRec *raw)
141 if (raw->tmp) delete [] raw->tmp;
142 if (raw->tmpR) delete [] raw->tmpR;
143 if (raw->tmpG) delete [] raw->tmpG;
144 if (raw->tmpB) delete [] raw->tmpB;
145 if (raw->tmpA) delete [] raw->tmpA;
147 if (raw->rowStart) delete [] raw->rowStart;
148 if (raw->rowSize) delete [] raw->rowSize;
155 static rawImageRec *RawImageOpen(std::istream& fin)
165 raw = new rawImageRec;
168 // notify(WARN)<< "Out of memory!"<< std::endl;
172 //Set istream pointer
175 endianTest.testWord = 1;
176 if (endianTest.testByte[0] == 1)
178 raw->swapFlag = GL_TRUE;
182 raw->swapFlag = GL_FALSE;
185 fin.read((char*)raw,12);
191 ConvertShort(&raw->imagic, 6);
194 raw->tmp = raw->tmpR = raw->tmpG = raw->tmpB = raw->tmpA = 0L;
197 raw->bpc = (raw->type & 0x00FF);
199 raw->tmp = new unsigned char [raw->sizeX*256*raw->bpc];
200 if (raw->tmp == NULL )
202 // notify(FATAL)<< "Out of memory!"<< std::endl;
207 if( raw->sizeZ >= 1 )
209 if( (raw->tmpR = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
211 // notify(FATAL)<< "Out of memory!"<< std::endl;
216 if( raw->sizeZ >= 2 )
218 if( (raw->tmpG = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
220 // notify(FATAL)<< "Out of memory!"<< std::endl;
225 if( raw->sizeZ >= 3 )
227 if( (raw->tmpB = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
229 // notify(FATAL)<< "Out of memory!"<< std::endl;
236 if( (raw->tmpA = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
238 // notify(FATAL)<< "Out of memory!"<< std::endl;
244 if ((raw->type & 0xFF00) == 0x0100)
246 unsigned int ybyz = raw->sizeY * raw->sizeZ;
247 if ( (raw->rowStart = new GLuint [ybyz]) == NULL )
249 // notify(FATAL)<< "Out of memory!"<< std::endl;
254 if ( (raw->rowSize = new GLint [ybyz]) == NULL )
256 // notify(FATAL)<< "Out of memory!"<< std::endl;
260 x = ybyz * sizeof(GLuint);
261 raw->rleEnd = 512 + (2 * x);
262 fin.seekg(512,std::ios::beg);
263 fin.read((char*)raw->rowStart,x);
264 fin.read((char*)raw->rowSize,x);
267 ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
268 ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
275 static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
277 unsigned char *iPtr, *oPtr;
278 unsigned short pixel;
280 unsigned short *tempShort;
282 if ((raw->type & 0xFF00) == 0x0100)
284 raw->file->seekg((long) raw->rowStart[y+z*raw->sizeY], std::ios::beg);
285 raw->file->read((char*)raw->tmp, (unsigned int)raw->rowSize[y+z*raw->sizeY]);
295 tempShort = reinterpret_cast<unsigned short*>(iPtr);
298 iPtr = reinterpret_cast<unsigned char *>(tempShort);
302 ConvertShort(&pixel, 1);
304 count = (int)(pixel & 0x7F);
306 // limit the count value to the remiaing row size
307 if (oPtr + count*raw->bpc > buf + raw->sizeX*raw->bpc)
309 count = ( (buf + raw->sizeX*raw->bpc) - oPtr ) / raw->bpc;
325 tempShort = reinterpret_cast<unsigned short*>(iPtr);
328 iPtr = reinterpret_cast<unsigned char *>(tempShort);
330 ConvertShort(&pixel, 1);
332 tempShort = reinterpret_cast<unsigned short*>(oPtr);
335 oPtr = reinterpret_cast<unsigned char *>(tempShort);
347 tempShort = reinterpret_cast<unsigned short*>(iPtr);
350 iPtr = reinterpret_cast<unsigned char *>(tempShort);
353 ConvertShort(&pixel, 1);
360 tempShort = reinterpret_cast<unsigned short*>(oPtr);
363 oPtr = reinterpret_cast<unsigned char *>(tempShort);
371 raw->file->seekg(512+(y*raw->sizeX*raw->bpc)+(z*raw->sizeX*raw->sizeY*raw->bpc),std::ios::beg);
372 raw->file->read((char*)buf, raw->sizeX*raw->bpc);
373 if(raw->swapFlag && raw->bpc != 1){
374 ConvertShort(reinterpret_cast<unsigned short*>(buf), raw->sizeX);
380 static void RawImageGetData(rawImageRec *raw, unsigned char **data )
384 unsigned short *tempShort;
386 // // round the width to a factor 4
387 // int width = (int)(floorf((float)raw->sizeX/4.0f)*4.0f);
388 // if (width!=raw->sizeX) width += 4;
392 // osg::notify(osg::INFO)<<"raw->sizeX = "<<raw->sizeX<<std::endl;
393 // osg::notify(osg::INFO)<<"raw->sizeY = "<<raw->sizeY<<std::endl;
394 // osg::notify(osg::INFO)<<"raw->sizeZ = "<<raw->sizeZ<<std::endl;
395 // osg::notify(osg::INFO)<<"raw->bpc = "<<raw->bpc<<std::endl;
397 *data = new unsigned char [(raw->sizeX)*(raw->sizeY)*(raw->sizeZ)*(raw->bpc)];
400 for (i = 0; i < (int)(raw->sizeY); i++)
402 if( raw->sizeZ >= 1 )
403 RawImageGetRow(raw, raw->tmpR, i, 0);
404 if( raw->sizeZ >= 2 )
405 RawImageGetRow(raw, raw->tmpG, i, 1);
406 if( raw->sizeZ >= 3 )
407 RawImageGetRow(raw, raw->tmpB, i, 2);
408 if( raw->sizeZ >= 4 )
409 RawImageGetRow(raw, raw->tmpA, i, 3);
410 for (j = 0; j < (int)(raw->sizeX); j++)
413 if( raw->sizeZ >= 1 )
414 *ptr++ = *(raw->tmpR + j);
415 if( raw->sizeZ >= 2 )
416 *ptr++ = *(raw->tmpG + j);
417 if( raw->sizeZ >= 3 )
418 *ptr++ = *(raw->tmpB + j);
419 if( raw->sizeZ >= 4 )
420 *ptr++ = *(raw->tmpA + j);
422 if( raw->sizeZ >= 1 )
424 tempShort = reinterpret_cast<unsigned short*>(ptr);
425 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpR) + j);
427 ptr = reinterpret_cast<unsigned char *>(tempShort);
429 if( raw->sizeZ >= 2 )
431 tempShort = reinterpret_cast<unsigned short*>(ptr);
432 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpG) + j);
434 ptr = reinterpret_cast<unsigned char *>(tempShort);
436 if( raw->sizeZ >= 3 )
438 tempShort = reinterpret_cast<unsigned short*>(ptr);
439 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpB) + j);
441 ptr = reinterpret_cast<unsigned char *>(tempShort);
443 if( raw->sizeZ >= 4 )
445 tempShort = reinterpret_cast<unsigned short*>(ptr);
446 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpA) + j);
448 ptr = reinterpret_cast<unsigned char *>(tempShort);
452 // // pad the image width with blanks to bring it up to the rounded width.
453 // for(;j<width;++j) *ptr++ = 0;
458 // supportsExtension("rgb","rgb image format");
459 // supportsExtension("rgba","rgba image format");
460 // supportsExtension("sgi","sgi image format");
461 // supportsExtension("int","int image format");
462 // supportsExtension("inta","inta image format");
463 // supportsExtension("bw","bw image format");
465 GLuint readRGBStream(std::istream& fin)
469 if( (raw = RawImageOpen(fin)) == NULL )
479 int internalFormat = raw->sizeZ == 3 ? GL_RGB5 :
480 raw->sizeZ == 4 ? GL_RGB5_A1 : GL_RGB;
482 // int internalFormat = raw->sizeZ;
484 unsigned int pixelFormat =
485 raw->sizeZ == 1 ? GL_LUMINANCE :
486 raw->sizeZ == 2 ? GL_LUMINANCE_ALPHA :
487 raw->sizeZ == 3 ? GL_RGB :
488 raw->sizeZ == 4 ? GL_RGBA : (GLenum)-1;
489 GLint component = raw->sizeZ;
491 unsigned int dataType = raw->bpc == 1 ? GL_UNSIGNED_BYTE :
495 RawImageGetData(raw, &data);
499 glGenTextures(1, &texture);
500 glBindTexture(GL_TEXTURE_2D, texture);
501 gluBuild2DMipmaps( GL_TEXTURE_2D, component, s, t, pixelFormat, dataType, (GLvoid*)data );
502 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
503 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );
509 GLuint FGRGBTextureLoader::loadTexture( const std::string & filename )
511 GLuint texture = NOTEXTURE;
512 std::ifstream istream(filename.c_str(), std::ios::in | std::ios::binary );
513 texture = readRGBStream(istream);