]> git.mxchange.org Git - flightgear.git/blob - Scenery/texload.c
Incorporated code changes contributed by Charlie Hotchkiss
[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
73     ImageRec *image;
74     int swapFlag;
75     int x;
76
77     endianTest.testWord = 1;
78     if (endianTest.testByte[0] == 1) {
79         swapFlag = 1;
80     } else {
81         swapFlag = 0;
82     }
83
84     image = (ImageRec *)malloc(sizeof(ImageRec));
85     if (image == NULL) {
86         fprintf(stderr, "Out of memory!\n");
87         exit(1);
88     }
89     if ((image->file = fopen(fileName, "rb")) == NULL) {
90       return NULL;
91     }
92
93     fread(image, 1, 12, image->file);
94
95     if (swapFlag) {
96         ConvertShort(&image->imagic, 6);
97     }
98
99     image->tmp = (unsigned char *)malloc(image->xsize*256);
100     if (image->tmp == NULL) {
101         fprintf(stderr, "\nOut of memory!\n");
102         exit(1);
103     }
104
105     if ((image->type & 0xFF00) == 0x0100) {
106         x = image->ysize * image->zsize * (int) sizeof(unsigned);
107         image->rowStart = (unsigned *)malloc(x);
108         image->rowSize = (int *)malloc(x);
109         if (image->rowStart == NULL || image->rowSize == NULL) {
110             fprintf(stderr, "\nOut of memory!\n");
111             exit(1);
112         }
113         image->rleEnd = 512 + (2 * x);
114         fseek(image->file, 512, SEEK_SET);
115         fread(image->rowStart, 1, x, image->file);
116         fread(image->rowSize, 1, x, image->file);
117         if (swapFlag) {
118             ConvertUint(image->rowStart, x/(int) sizeof(unsigned));
119             ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int));
120         }
121     }
122     return image;
123 }
124
125 static void
126 ImageClose(ImageRec *image) {
127     fclose(image->file);
128     free(image->tmp);
129     free(image);
130 }
131
132 static void
133 ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z) {
134     unsigned char *iPtr, *oPtr, pixel;
135     int count;
136
137     if ((image->type & 0xFF00) == 0x0100) {
138         fseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET);
139         fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize],
140               image->file);
141
142         iPtr = image->tmp;
143         oPtr = buf;
144         for (;;) {
145             pixel = *iPtr++;
146             count = (int)(pixel & 0x7F);
147             if (!count) {
148                 return;
149             }
150             if (pixel & 0x80) {
151                 while (count--) {
152                     *oPtr++ = *iPtr++;
153                 }
154             } else {
155                 pixel = *iPtr++;
156                 while (count--) {
157                     *oPtr++ = pixel;
158                 }
159             }
160         }
161     } else {
162         fseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
163               SEEK_SET);
164         fread(buf, 1, image->xsize, image->file);
165     }
166 }
167
168 GLubyte *
169 read_alpha_texture(char *name, int *width, int *height)
170 {
171     unsigned char *base, *lptr;
172     ImageRec *image;
173     int y;
174
175     image = ImageOpen(name);
176     if(!image) {
177         return NULL;
178     }
179
180     (*width)=image->xsize;
181     (*height)=image->ysize;
182     if (image->zsize != 1) {
183       ImageClose(image);
184       return NULL;
185     }
186
187     base = (unsigned char *)malloc(image->xsize*image->ysize*sizeof(unsigned char));
188     lptr = base;
189     for(y=0; y<image->ysize; y++) {
190         ImageGetRow(image,lptr,y,0);
191         lptr += image->xsize;
192     }
193     ImageClose(image);
194
195     return (unsigned char *) base;
196 }
197
198 GLubyte *
199 read_rgb_texture(char *name, int *width, int *height)
200 {
201     unsigned char *base, *ptr;
202     unsigned char *rbuf, *gbuf, *bbuf, *abuf;
203     ImageRec *image;
204     int y;
205
206     image = ImageOpen(name);
207     
208     if(!image)
209         return NULL;
210     (*width)=image->xsize;
211     (*height)=image->ysize;
212     if (image->zsize != 3 && image->zsize != 4) {
213       ImageClose(image);
214       return NULL;
215     }
216
217     base = (unsigned char*)malloc(image->xsize*image->ysize*sizeof(unsigned int)*3);
218     rbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
219     gbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
220     bbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
221     abuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
222     if(!base || !rbuf || !gbuf || !bbuf || !abuf) {
223       if (base) free(base);
224       if (rbuf) free(rbuf);
225       if (gbuf) free(gbuf);
226       if (bbuf) free(bbuf);
227       if (abuf) free(abuf);
228       return NULL;
229     }
230     ptr = base;
231     for(y=0; y<image->ysize; y++) {
232         if(image->zsize == 4) {
233             ImageGetRow(image,rbuf,y,0);
234             ImageGetRow(image,gbuf,y,1);
235             ImageGetRow(image,bbuf,y,2);
236             ImageGetRow(image,abuf,y,3);  /* Discard. */
237             rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
238             ptr += (image->xsize * 3);
239         } else {
240             ImageGetRow(image,rbuf,y,0);
241             ImageGetRow(image,gbuf,y,1);
242             ImageGetRow(image,bbuf,y,2);
243             rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
244             ptr += (image->xsize * 3);
245         }
246     }
247     ImageClose(image);
248     free(rbuf);
249     free(gbuf);
250     free(bbuf);
251     free(abuf);
252
253     return (GLubyte *) base;
254 }