]> git.mxchange.org Git - flightgear.git/blob - utils/fgpanel/FGRGBTextureLoader.cxx
Fix Win32 build, hopefully.
[flightgear.git] / utils / fgpanel / FGRGBTextureLoader.cxx
1 //
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.
6 // 
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.
11 //
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.
15 //
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
19
20 #ifdef HAVE_CONFIG_H
21 #  include <config.h>
22 #endif
23
24 #ifdef HAVE_WINDOWS_H
25 #include <windows.h>
26 #endif
27
28 #include "FGRGBTextureLoader.hxx"
29 #if defined (SG_MAC)
30 #include <OpenGL/gl.h>
31 #include <GLUT/glut.h>
32 #else
33 #include <GL/gl.h>
34 #include <GL/glut.h>
35 #endif
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <iostream>
41 #include <fstream>
42
43 typedef struct _rawImageRec
44 {
45     unsigned short imagic;
46     unsigned short type;
47     unsigned short dim;
48     unsigned short sizeX, sizeY, sizeZ;
49     unsigned long min, max;
50     unsigned long wasteBytes;
51     char name[80];
52     unsigned long colorMap;
53     std::istream *file;
54     unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
55     unsigned long rleEnd;
56     GLuint *rowStart;
57     GLint *rowSize;
58     GLenum swapFlag;
59     short bpc;
60   
61     typedef unsigned char * BytePtr;
62
63     bool needsBytesSwapped()
64     {
65         union {
66             int testWord;
67             char testByte[sizeof(int)];
68         }endianTest; 
69         endianTest.testWord = 1;
70         if( endianTest.testByte[0] == 1 )
71             return true;
72         else
73             return false;
74     }
75
76     template <class T>
77     inline void swapBytes(  T &s )
78     {
79         if( sizeof( T ) == 1 ) 
80             return;
81
82         T d = s;
83         BytePtr sptr = (BytePtr)&s;
84         BytePtr dptr = &(((BytePtr)&d)[sizeof(T)-1]);
85
86         for( unsigned int i = 0; i < sizeof(T); i++ )
87             *(sptr++) = *(dptr--);
88     }
89
90     void swapBytes()
91     {
92         swapBytes( imagic );
93         swapBytes( type );
94         swapBytes( dim );
95         swapBytes( sizeX );
96         swapBytes( sizeY );
97         swapBytes( sizeZ );
98         swapBytes( wasteBytes );
99         swapBytes( min );
100         swapBytes( max );
101         swapBytes( colorMap );
102     }
103 } rawImageRec;
104
105 static void ConvertShort(unsigned short *array, long length)
106 {
107     unsigned long b1, b2;
108     unsigned char *ptr;
109
110     ptr = (unsigned char *)array;
111     while (length--)
112     {
113         b1 = *ptr++;
114         b2 = *ptr++;
115         *array++ = (unsigned short) ((b1 << 8) | (b2));
116     }
117 }
118
119 static void ConvertLong(GLuint *array, long length)
120 {
121     unsigned long b1, b2, b3, b4;
122     unsigned char *ptr;
123
124     ptr = (unsigned char *)array;
125     while (length--)
126     {
127         b1 = *ptr++;
128         b2 = *ptr++;
129         b3 = *ptr++;
130         b4 = *ptr++;
131         *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
132     }
133 }
134
135
136 static void RawImageClose(rawImageRec *raw)
137 {
138     if (raw)
139     {
140         
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;
146
147         if (raw->rowStart) delete [] raw->rowStart;        
148         if (raw->rowSize) delete [] raw->rowSize;        
149
150         delete raw;
151     }
152 }
153
154
155 static rawImageRec *RawImageOpen(std::istream& fin)
156 {
157     union
158     {
159         int testWord;
160         char testByte[4];
161     } endianTest;
162     rawImageRec *raw;
163     int x;
164
165     raw = new rawImageRec;
166     if (raw == NULL)
167     {
168 //        notify(WARN)<< "Out of memory!"<< std::endl;
169         return NULL;
170     }
171
172     //Set istream pointer
173     raw->file = &fin;
174
175     endianTest.testWord = 1;
176     if (endianTest.testByte[0] == 1)
177     {
178         raw->swapFlag = GL_TRUE;
179     }
180     else
181     {
182         raw->swapFlag = GL_FALSE;
183     }
184
185     fin.read((char*)raw,12);
186     if (!fin.good())
187         return NULL;
188
189     if (raw->swapFlag)
190     {
191         ConvertShort(&raw->imagic, 6);
192     }
193
194     raw->tmp = raw->tmpR = raw->tmpG = raw->tmpB = raw->tmpA = 0L;
195     raw->rowStart = 0;
196     raw->rowSize = 0;
197     raw->bpc = (raw->type & 0x00FF);
198
199     raw->tmp = new unsigned char [raw->sizeX*256*raw->bpc];
200     if (raw->tmp == NULL )
201     {
202 //        notify(FATAL)<< "Out of memory!"<< std::endl;
203         RawImageClose(raw);
204         return NULL;
205     }
206
207     if( raw->sizeZ >= 1 )
208     {
209         if( (raw->tmpR = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
210         {
211 //            notify(FATAL)<< "Out of memory!"<< std::endl;
212             RawImageClose(raw);
213             return NULL;
214         }
215     }
216     if( raw->sizeZ >= 2 )
217     {
218         if( (raw->tmpG = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
219         {
220 //            notify(FATAL)<< "Out of memory!"<< std::endl;
221             RawImageClose(raw);
222             return NULL;
223         }
224     }
225     if( raw->sizeZ >= 3 )
226     {
227         if( (raw->tmpB = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
228         {
229 //            notify(FATAL)<< "Out of memory!"<< std::endl;
230             RawImageClose(raw);
231             return NULL;
232         }
233     }
234     if (raw->sizeZ >= 4)
235     {
236         if( (raw->tmpA = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
237         {
238 //            notify(FATAL)<< "Out of memory!"<< std::endl;
239             RawImageClose(raw);
240             return NULL;
241         }
242     }
243     
244     if ((raw->type & 0xFF00) == 0x0100)
245     {
246         unsigned int ybyz = raw->sizeY * raw->sizeZ;
247         if ( (raw->rowStart = new GLuint [ybyz]) == NULL )
248         {
249 //            notify(FATAL)<< "Out of memory!"<< std::endl;
250             RawImageClose(raw);
251             return NULL;
252         }
253
254         if ( (raw->rowSize = new GLint [ybyz]) == NULL )
255         {
256 //            notify(FATAL)<< "Out of memory!"<< std::endl;
257             RawImageClose(raw);
258             return NULL;
259         }
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);
265         if (raw->swapFlag)
266         {
267             ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
268             ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
269         }
270     }
271     return raw;
272 }
273
274
275 static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
276 {
277     unsigned char *iPtr, *oPtr;
278     unsigned short pixel;
279     int count, done = 0;
280     unsigned short *tempShort;
281
282     if ((raw->type & 0xFF00) == 0x0100)
283     {
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]);
286
287         iPtr = raw->tmp;
288         oPtr = buf;
289         while (!done)
290         {
291             if (raw->bpc == 1)
292                 pixel = *iPtr++;
293             else
294             {
295                 tempShort = reinterpret_cast<unsigned short*>(iPtr);
296                 pixel = *tempShort;
297                 tempShort++;
298                 iPtr = reinterpret_cast<unsigned char *>(tempShort);
299             }
300             
301             if(raw->bpc != 1)
302                 ConvertShort(&pixel, 1);
303
304             count = (int)(pixel & 0x7F);
305             
306             // limit the count value to the remiaing row size
307             if (oPtr + count*raw->bpc > buf + raw->sizeX*raw->bpc)
308             {
309                 count = ( (buf + raw->sizeX*raw->bpc) - oPtr ) / raw->bpc;
310             }
311                 
312             if (count<=0)
313             {
314                 done = 1;
315                 return;
316             }
317             
318             if (pixel & 0x80)
319             {
320                 while (count--)
321                 {
322                     if(raw->bpc == 1)
323                         *oPtr++ = *iPtr++;
324                     else{
325                         tempShort = reinterpret_cast<unsigned short*>(iPtr);
326                         pixel = *tempShort;
327                         tempShort++;
328                         iPtr = reinterpret_cast<unsigned char *>(tempShort);
329                         
330                         ConvertShort(&pixel, 1);
331
332                         tempShort = reinterpret_cast<unsigned short*>(oPtr);
333                         *tempShort = pixel;
334                         tempShort++;
335                         oPtr = reinterpret_cast<unsigned char *>(tempShort);
336                     }
337                 }
338             }
339             else
340             {
341                 if (raw->bpc == 1)
342                 {
343                     pixel = *iPtr++;
344                 }
345                 else
346                 {
347                     tempShort = reinterpret_cast<unsigned short*>(iPtr);
348                     pixel = *tempShort;
349                     tempShort++;
350                     iPtr = reinterpret_cast<unsigned char *>(tempShort);
351                 }
352                 if(raw->bpc != 1)
353                     ConvertShort(&pixel, 1);
354                 while (count--)
355                 {
356                     if(raw->bpc == 1)
357                         *oPtr++ = pixel;
358                     else
359                     {
360                         tempShort = reinterpret_cast<unsigned short*>(oPtr);
361                         *tempShort = pixel;
362                         tempShort++;
363                         oPtr = reinterpret_cast<unsigned char *>(tempShort);
364                     }
365                 }
366             }
367         }
368     }
369     else
370     {
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);
375         }
376     }
377 }
378
379
380 static void RawImageGetData(rawImageRec *raw, unsigned char **data )
381 {
382     unsigned char *ptr;
383     int i, j;
384     unsigned short *tempShort;
385
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;
389
390     // byte aligned.
391     
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;
396     
397     *data = new unsigned char [(raw->sizeX)*(raw->sizeY)*(raw->sizeZ)*(raw->bpc)];
398
399     ptr = *data;
400     for (i = 0; i < (int)(raw->sizeY); i++)
401     {
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++)
411         {
412           if(raw->bpc == 1){
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);
421           }else{
422             if( raw->sizeZ >= 1 )
423             {
424                 tempShort = reinterpret_cast<unsigned short*>(ptr);
425                 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpR) + j);
426                 tempShort++;
427                 ptr = reinterpret_cast<unsigned char *>(tempShort);
428             }
429             if( raw->sizeZ >= 2 )
430             {
431                 tempShort = reinterpret_cast<unsigned short*>(ptr);
432                 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpG) + j);
433                 tempShort++;
434                 ptr = reinterpret_cast<unsigned char *>(tempShort);
435             }
436             if( raw->sizeZ >= 3 )
437             {
438                 tempShort = reinterpret_cast<unsigned short*>(ptr);
439                 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpB) + j);
440                 tempShort++;
441                 ptr = reinterpret_cast<unsigned char *>(tempShort);
442             }
443             if( raw->sizeZ >= 4 )
444             {
445                 tempShort = reinterpret_cast<unsigned short*>(ptr);
446                 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpA) + j);
447                 tempShort++;
448                 ptr = reinterpret_cast<unsigned char *>(tempShort);
449             }
450           }
451         }
452         //         // pad the image width with blanks to bring it up to the rounded width.
453         //         for(;j<width;++j) *ptr++ = 0;
454     }
455 }
456
457
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");
464         
465         GLuint readRGBStream(std::istream& fin)
466         {
467             rawImageRec *raw;
468
469             if( (raw = RawImageOpen(fin)) == NULL )
470             {
471                 return 0;
472             }
473
474             int s = raw->sizeX;
475             int t = raw->sizeY;
476 //            int r = 1;
477
478         #if 0
479             int internalFormat = raw->sizeZ == 3 ? GL_RGB5 :
480             raw->sizeZ == 4 ? GL_RGB5_A1 : GL_RGB;
481         #else
482 //            int internalFormat = raw->sizeZ;
483         #endif
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;
490
491             unsigned int dataType = raw->bpc == 1 ? GL_UNSIGNED_BYTE :
492               GL_UNSIGNED_SHORT;
493
494             unsigned char *data;
495             RawImageGetData(raw, &data);
496             RawImageClose(raw);
497
498   GLuint texture;
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 );
504
505             delete []data;
506             return texture;
507         }
508
509 GLuint FGRGBTextureLoader::loadTexture( const std::string & filename )
510 {
511   GLuint texture = NOTEXTURE;
512   std::ifstream istream(filename.c_str(), std::ios::in | std::ios::binary );
513   texture = readRGBStream(istream);
514   istream.close();
515   return texture;
516 }
517