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