]> git.mxchange.org Git - flightgear.git/blob - Simulator/Objects/texload.c
Updated for 0.6.2
[flightgear.git] / Simulator / Objects / texload.c
1
2 /* texture.c - by David Blythe, SGI */
3
4 /* texload is a simplistic routine for reading an SGI .rgb image file. */
5
6 #ifdef HAVE_CONFIG_H
7 #  include <config.h>
8 #endif
9
10 #ifdef HAVE_WINDOWS_H
11 #  include <windows.h>
12 #endif
13
14 #include <stdio.h>
15 #include <stdlib.h> 
16 #include <string.h>
17
18 #include <Include/fg_zlib.h>
19
20 #include "texload.h"
21 #include "colours.h"
22
23 typedef struct _ImageRec {
24     unsigned short imagic;
25     unsigned short type;
26     unsigned short dim;
27     unsigned short xsize, ysize, zsize;
28     unsigned int min, max;
29     unsigned int wasteBytes;
30     char name[80];
31     unsigned long colorMap;
32     fgFile file;
33     unsigned char *tmp;
34     unsigned long rleEnd;
35     unsigned int *rowStart;
36     int *rowSize;
37 } ImageRec;
38
39 void
40 rgbtorgb(unsigned char *r,unsigned char *g,unsigned char *b,unsigned char *l,int n) {
41     while(n--) {
42         l[0] = r[0];
43         l[1] = g[0];
44         l[2] = b[0];
45         l += 3; r++; g++; b++;
46     }
47 }
48
49 static void
50 ConvertShort(unsigned short *array, unsigned int length) {
51     unsigned short b1, b2;
52     unsigned char *ptr;
53
54     ptr = (unsigned char *)array;
55     while (length--) {
56         b1 = *ptr++;
57         b2 = *ptr++;
58         *array++ = (b1 << 8) | (b2);
59     }
60 }
61
62 static void
63 ConvertUint(unsigned *array, unsigned int length) {
64     unsigned int b1, b2, b3, b4;
65     unsigned char *ptr;
66
67     ptr = (unsigned char *)array;
68     while (length--) {
69         b1 = *ptr++;
70         b2 = *ptr++;
71         b3 = *ptr++;
72         b4 = *ptr++;
73         *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
74     }
75 }
76
77 static ImageRec *ImageOpen(const char *fileName)
78 {
79      union {
80        int testWord;
81        char testByte[4];
82      } endianTest;
83
84     ImageRec *image;
85     int swapFlag;
86     int x;
87
88     endianTest.testWord = 1;
89     if (endianTest.testByte[0] == 1) {
90         swapFlag = 1;
91     } else {
92         swapFlag = 0;
93     }
94
95     image = (ImageRec *)malloc(sizeof(ImageRec));
96     if (image == NULL) {
97         fprintf(stderr, "Out of memory!\n");
98         exit(1);
99     }
100     if ((image->file = fgopen(fileName, "rb")) == NULL) {
101       return NULL;
102     }
103
104     // fread(image, 1, 12, image->file);
105     fgread(image->file, image, 12);
106
107     if (swapFlag) {
108         ConvertShort(&image->imagic, 6);
109     }
110
111     image->tmp = (unsigned char *)malloc(image->xsize*256);
112     if (image->tmp == NULL) {
113         fprintf(stderr, "\nOut of memory!\n");
114         exit(1);
115     }
116
117     if ((image->type & 0xFF00) == 0x0100) {
118         x = image->ysize * image->zsize * (int) sizeof(unsigned);
119         image->rowStart = (unsigned *)malloc(x);
120         image->rowSize = (int *)malloc(x);
121         if (image->rowStart == NULL || image->rowSize == NULL) {
122             fprintf(stderr, "\nOut of memory!\n");
123             exit(1);
124         }
125         image->rleEnd = 512 + (2 * x);
126         fgseek(image->file, 512, SEEK_SET);
127         // fread(image->rowStart, 1, x, image->file);
128         fgread(image->file, image->rowStart, x);
129         // fread(image->rowSize, 1, x, image->file);
130         fgread(image->file, image->rowSize, x);
131         if (swapFlag) {
132             ConvertUint(image->rowStart, x/(int) sizeof(unsigned));
133             ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int));
134         }
135     }
136     return image;
137 }
138
139 static void
140 ImageClose(ImageRec *image) {
141     fgclose(image->file);
142     free(image->tmp);
143     free(image);
144 }
145
146 static void
147 ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z) {
148     unsigned char *iPtr, *oPtr, pixel;
149     int count;
150
151     if ((image->type & 0xFF00) == 0x0100) {
152         fgseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET);
153         // fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize],
154         //      image->file);
155         fgread(image->file, image->tmp, 
156                (unsigned int)image->rowSize[y+z*image->ysize]);
157
158         iPtr = image->tmp;
159         oPtr = buf;
160         for (;;) {
161             pixel = *iPtr++;
162             count = (int)(pixel & 0x7F);
163             if (!count) {
164                 return;
165             }
166             if (pixel & 0x80) {
167                 while (count--) {
168                     *oPtr++ = *iPtr++;
169                 }
170             } else {
171                 pixel = *iPtr++;
172                 while (count--) {
173                     *oPtr++ = pixel;
174                 }
175             }
176         }
177     } else {
178         fgseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
179               SEEK_SET);
180         // fread(buf, 1, image->xsize, image->file);
181         fgread(image->file, buf, image->xsize);
182     }
183 }
184
185 GLubyte *
186 read_alpha_texture(const char *name, int *width, int *height)
187 {
188     unsigned char *base, *lptr;
189     ImageRec *image;
190     int y;
191
192     image = ImageOpen(name);
193     if(!image) {
194         return NULL;
195     }
196
197     (*width)=image->xsize;
198     (*height)=image->ysize;
199
200     printf("image->zsize = %d\n", image->zsize);
201
202     if (image->zsize != 1) {
203       ImageClose(image);
204       return NULL;
205     }
206
207     base = (unsigned char *)malloc(image->xsize*image->ysize*sizeof(unsigned char));
208     lptr = base;
209     for(y=0; y<image->ysize; y++) {
210         ImageGetRow(image,lptr,y,0);
211         lptr += image->xsize;
212     }
213     ImageClose(image);
214
215     return (unsigned char *) base;
216 }
217
218 GLubyte *
219 read_rgb_texture(const char *name, int *width, int *height)
220 {
221     unsigned char *base, *ptr;
222     unsigned char *rbuf, *gbuf, *bbuf, *abuf;
223     ImageRec *image;
224     int y;
225
226     image = ImageOpen(name);
227     
228     if(!image)
229         return NULL;
230     (*width)=image->xsize;
231     (*height)=image->ysize;
232     if (image->zsize != 3 && image->zsize != 4) {
233       ImageClose(image);
234       return NULL;
235     }
236
237     base = (unsigned char*)malloc(image->xsize*image->ysize*sizeof(unsigned int)*3);
238     rbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
239     gbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
240     bbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
241     abuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
242     if(!base || !rbuf || !gbuf || !bbuf || !abuf) {
243       if (base) free(base);
244       if (rbuf) free(rbuf);
245       if (gbuf) free(gbuf);
246       if (bbuf) free(bbuf);
247       if (abuf) free(abuf);
248       return NULL;
249     }
250     ptr = base;
251     for(y=0; y<image->ysize; y++) {
252         if(image->zsize == 4) {
253             ImageGetRow(image,rbuf,y,0);
254             ImageGetRow(image,gbuf,y,1);
255             ImageGetRow(image,bbuf,y,2);
256             ImageGetRow(image,abuf,y,3);  /* Discard. */
257             rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
258             ptr += (image->xsize * 3);
259         } else {
260             ImageGetRow(image,rbuf,y,0);
261             ImageGetRow(image,gbuf,y,1);
262             ImageGetRow(image,bbuf,y,2);
263             rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
264             ptr += (image->xsize * 3);
265         }
266     }
267     ImageClose(image);
268     free(rbuf);
269     free(gbuf);
270     free(bbuf);
271     free(abuf);
272
273     return (GLubyte *) base;
274 }
275
276
277 static ImageRec *RawImageOpen(const char *fileName)
278 {
279      union {
280        int testWord;
281        char testByte[4];
282      } endianTest;
283
284     ImageRec *image;
285     int swapFlag;
286
287     endianTest.testWord = 1;
288     if (endianTest.testByte[0] == 1) {
289         swapFlag = 1;
290     } else {
291         swapFlag = 0;
292     }
293
294     image = (ImageRec *)malloc(sizeof(ImageRec));
295     if (image == NULL) {
296         fprintf(stderr, "Out of memory!\n");
297         exit(1);
298     }
299     if ((image->file = fgopen(fileName, "rb")) == NULL) {
300       return NULL;
301     }
302
303     fgread(image->file, image, 12);
304
305     if (swapFlag) {
306         ConvertShort(&image->imagic, 6);
307     }
308
309     
310         image->tmp = (unsigned char *)malloc(1);        //just allocate a pseudo value as I'm too lazy to change ImageClose()...
311     if (image->tmp == NULL) {
312         fprintf(stderr, "\nOut of memory!\n");
313         exit(1);
314     }
315
316     return image;
317 }
318
319
320 GLubyte *
321 read_raw_texture(const char *name, int *width, int *height)
322 {
323     unsigned char *base, *ptr;
324     ImageRec *image;
325     int y;
326
327     image = RawImageOpen(name);
328     
329     if(!image)
330         return NULL;
331     (*width)=256; 
332     (*height)=256; 
333
334     base = (unsigned char*)malloc(256*256*sizeof(unsigned char)*3);
335     if(!base) {
336       if (base) free(base);
337       return NULL;
338     }
339     ptr = base;
340     for(y=0; y<256; y++) {
341                 fgread(image->file, ptr, 256*3);
342                 ptr+=256*3;
343     }
344     ImageClose(image);
345
346     return (GLubyte *) base;
347 }
348
349
350 GLubyte *
351 read_r8_texture(const char *name, int *width, int *height)
352 {
353     unsigned char *base, *ptr;
354     ImageRec *image;
355     int xy;
356         unsigned char c[1];
357
358     image = RawImageOpen(name); //it wouldn't make sense to write a new function...
359     
360     if(!image)
361         return NULL;
362     (*width)=256; 
363     (*height)=256; 
364
365     base = (unsigned char*)malloc(256*256*sizeof(unsigned char)*3);
366     if(!base) {
367       if (base) free(base);
368       return NULL;
369     }
370     ptr = base;
371     for(xy=0; xy<(256*256); xy++) {
372                 fgread(image->file,c,1);
373                 ptr[0]=msfs_colour[c[0]][0];    //look in the table for the right colours
374                 ptr[1]=msfs_colour[c[0]][1];
375                 ptr[2]=msfs_colour[c[0]][2];
376                 
377                 ptr+=3;
378     }
379     ImageClose(image);
380
381     return (GLubyte *) base;
382 }