]> git.mxchange.org Git - flightgear.git/blob - Scenery/texload.c
0995f1654c0fb8498bae6d4df1e3230a16a1d012
[flightgear.git] / Scenery / 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 #include <stdio.h>
7 #include <stdlib.h> 
8 #include <string.h>
9
10 #include "texload.h"
11
12 typedef struct _ImageRec {
13     unsigned short imagic;
14     unsigned short type;
15     unsigned short dim;
16     unsigned short xsize, ysize, zsize;
17     unsigned int min, max;
18     unsigned int wasteBytes;
19     char name[80];
20     unsigned long colorMap;
21     FILE *file;
22     unsigned char *tmp;
23     unsigned long rleEnd;
24     unsigned int *rowStart;
25     int *rowSize;
26 } ImageRec;
27
28 void
29 rgbtorgb(unsigned char *r,unsigned char *g,unsigned char *b,unsigned char *l,int n) {
30     while(n--) {
31         l[0] = r[0];
32         l[1] = g[0];
33         l[2] = b[0];
34         l += 3; r++; g++; b++;
35     }
36 }
37
38 static void
39 ConvertShort(unsigned short *array, unsigned int length) {
40     unsigned short b1, b2;
41     unsigned char *ptr;
42
43     ptr = (unsigned char *)array;
44     while (length--) {
45         b1 = *ptr++;
46         b2 = *ptr++;
47         *array++ = (b1 << 8) | (b2);
48     }
49 }
50
51 static void
52 ConvertUint(unsigned *array, unsigned int length) {
53     unsigned int b1, b2, b3, b4;
54     unsigned char *ptr;
55
56     ptr = (unsigned char *)array;
57     while (length--) {
58         b1 = *ptr++;
59         b2 = *ptr++;
60         b3 = *ptr++;
61         b4 = *ptr++;
62         *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
63     }
64 }
65
66 static ImageRec *ImageOpen(char *fileName)
67 {
68     union {
69         int testWord;
70         char testByte[4];
71     } endianTest;
72     ImageRec *image;
73     int swapFlag;
74     int x;
75
76     endianTest.testWord = 1;
77     if (endianTest.testByte[0] == 1) {
78         swapFlag = 1;
79     } else {
80         swapFlag = 0;
81     }
82
83     image = (ImageRec *)malloc(sizeof(ImageRec));
84     if (image == NULL) {
85         fprintf(stderr, "Out of memory!\n");
86         exit(1);
87     }
88     if ((image->file = fopen(fileName, "rb")) == NULL) {
89         return NULL;
90     }
91
92     fread(image, 1, 12, image->file);
93
94     if (swapFlag) {
95         ConvertShort(&image->imagic, 6);
96     }
97
98     image->tmp = (unsigned char *)malloc(image->xsize*256);
99     if (image->tmp == NULL) {
100         fprintf(stderr, "\nOut of memory!\n");
101         exit(1);
102     }
103
104     if ((image->type & 0xFF00) == 0x0100) {
105         x = image->ysize * image->zsize * (int) sizeof(unsigned);
106         image->rowStart = (unsigned *)malloc(x);
107         image->rowSize = (int *)malloc(x);
108         if (image->rowStart == NULL || image->rowSize == NULL) {
109             fprintf(stderr, "\nOut of memory!\n");
110             exit(1);
111         }
112         image->rleEnd = 512 + (2 * x);
113         fseek(image->file, 512, SEEK_SET);
114         fread(image->rowStart, 1, x, image->file);
115         fread(image->rowSize, 1, x, image->file);
116         if (swapFlag) {
117             ConvertUint(image->rowStart, x/(int) sizeof(unsigned));
118             ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int));
119         }
120     }
121     return image;
122 }
123
124 static void
125 ImageClose(ImageRec *image) {
126     fclose(image->file);
127     free(image->tmp);
128     free(image);
129 }
130
131 static void
132 ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z) {
133     unsigned char *iPtr, *oPtr, pixel;
134     int count;
135
136     if ((image->type & 0xFF00) == 0x0100) {
137         fseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET);
138         fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize],
139               image->file);
140
141         iPtr = image->tmp;
142         oPtr = buf;
143         for (;;) {
144             pixel = *iPtr++;
145             count = (int)(pixel & 0x7F);
146             if (!count) {
147                 return;
148             }
149             if (pixel & 0x80) {
150                 while (count--) {
151                     *oPtr++ = *iPtr++;
152                 }
153             } else {
154                 pixel = *iPtr++;
155                 while (count--) {
156                     *oPtr++ = pixel;
157                 }
158             }
159         }
160     } else {
161         fseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
162               SEEK_SET);
163         fread(buf, 1, image->xsize, image->file);
164     }
165 }
166
167 GLubyte *
168 read_alpha_texture(char *name, int *width, int *height)
169 {
170     unsigned char *base, *lptr;
171     ImageRec *image;
172     int y;
173
174     image = ImageOpen(name);
175     if(!image) {
176         return NULL;
177     }
178
179     (*width)=image->xsize;
180     (*height)=image->ysize;
181     if (image->zsize != 1) {
182       ImageClose(image);
183       return NULL;
184     }
185
186     base = (unsigned char *)malloc(image->xsize*image->ysize*sizeof(unsigned char));
187     lptr = base;
188     for(y=0; y<image->ysize; y++) {
189         ImageGetRow(image,lptr,y,0);
190         lptr += image->xsize;
191     }
192     ImageClose(image);
193
194     return (unsigned char *) base;
195 }
196
197 GLubyte *
198 read_rgb_texture(char *name, int *width, int *height)
199 {
200     unsigned char *base, *ptr;
201     unsigned char *rbuf, *gbuf, *bbuf, *abuf;
202     ImageRec *image;
203     int y;
204
205     image = ImageOpen(name);
206     
207     if(!image)
208         return NULL;
209     (*width)=image->xsize;
210     (*height)=image->ysize;
211     if (image->zsize != 3 && image->zsize != 4) {
212       ImageClose(image);
213       return NULL;
214     }
215
216     base = (unsigned char*)malloc(image->xsize*image->ysize*sizeof(unsigned int)*3);
217     rbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
218     gbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
219     bbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
220     abuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
221     if(!base || !rbuf || !gbuf || !bbuf || !abuf) {
222       if (base) free(base);
223       if (rbuf) free(rbuf);
224       if (gbuf) free(gbuf);
225       if (bbuf) free(bbuf);
226       if (abuf) free(abuf);
227       return NULL;
228     }
229     ptr = base;
230     for(y=0; y<image->ysize; y++) {
231         if(image->zsize == 4) {
232             ImageGetRow(image,rbuf,y,0);
233             ImageGetRow(image,gbuf,y,1);
234             ImageGetRow(image,bbuf,y,2);
235             ImageGetRow(image,abuf,y,3);  /* Discard. */
236             rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
237             ptr += (image->xsize * 3);
238         } else {
239             ImageGetRow(image,rbuf,y,0);
240             ImageGetRow(image,gbuf,y,1);
241             ImageGetRow(image,bbuf,y,2);
242             rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
243             ptr += (image->xsize * 3);
244         }
245     }
246     ImageClose(image);
247     free(rbuf);
248     free(gbuf);
249     free(bbuf);
250     free(abuf);
251
252     return (GLubyte *) base;
253 }