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