Merge branch '7.8'
[mesa.git] / progs / samples / rgbtoppm.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 <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include <GL/glut.h>
12
13 typedef struct _ImageRec {
14 unsigned short imagic;
15 unsigned short type;
16 unsigned short dim;
17 unsigned short xsize, ysize, zsize;
18 unsigned int min, max;
19 unsigned int wasteBytes;
20 char name[80];
21 unsigned long colorMap;
22 FILE *file;
23 unsigned char *tmp;
24 unsigned long rleEnd;
25 unsigned int *rowStart;
26 int *rowSize;
27 } ImageRec;
28
29 static void
30 rgbtorgb(unsigned char *r,unsigned char *g,unsigned char *b,unsigned char *l,int n) {
31 while(n--) {
32 l[0] = r[0];
33 l[1] = g[0];
34 l[2] = b[0];
35 l += 3; r++; g++; b++;
36 }
37 }
38
39 static void
40 ConvertShort(unsigned short *array, unsigned int length) {
41 unsigned short b1, b2;
42 unsigned char *ptr;
43
44 ptr = (unsigned char *)array;
45 while (length--) {
46 b1 = *ptr++;
47 b2 = *ptr++;
48 *array++ = (b1 << 8) | (b2);
49 }
50 }
51
52 static void
53 ConvertUint(unsigned *array, unsigned int length) {
54 unsigned int b1, b2, b3, b4;
55 unsigned char *ptr;
56
57 ptr = (unsigned char *)array;
58 while (length--) {
59 b1 = *ptr++;
60 b2 = *ptr++;
61 b3 = *ptr++;
62 b4 = *ptr++;
63 *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
64 }
65 }
66
67 static ImageRec *ImageOpen(char *fileName)
68 {
69 union {
70 int testWord;
71 char testByte[4];
72 } endianTest;
73 ImageRec *image;
74 int swapFlag;
75 int x;
76 int result;
77
78 endianTest.testWord = 1;
79 if (endianTest.testByte[0] == 1) {
80 swapFlag = 1;
81 } else {
82 swapFlag = 0;
83 }
84
85 image = (ImageRec *)malloc(sizeof(ImageRec));
86 if (image == NULL) {
87 fprintf(stderr, "Out of memory!\n");
88 exit(1);
89 }
90 if ((image->file = fopen(fileName, "rb")) == NULL) {
91 free(image);
92 return NULL;
93 }
94
95 result = fread(image, 1, 12, image->file);
96 assert(result == 12);
97
98 if (swapFlag) {
99 ConvertShort(&image->imagic, 1);
100 ConvertShort(&image->type, 1);
101 ConvertShort(&image->dim, 1);
102 ConvertShort(&image->xsize, 1);
103 ConvertShort(&image->ysize, 1);
104 ConvertShort(&image->zsize, 1);
105 }
106
107 image->tmp = (unsigned char *)malloc(image->xsize*256);
108 if (image->tmp == NULL) {
109 fprintf(stderr, "\nOut of memory!\n");
110 exit(1);
111 }
112
113 if ((image->type & 0xFF00) == 0x0100) {
114 x = image->ysize * image->zsize * (int) sizeof(unsigned);
115 image->rowStart = (unsigned *)malloc(x);
116 image->rowSize = (int *)malloc(x);
117 if (image->rowStart == NULL || image->rowSize == NULL) {
118 fprintf(stderr, "\nOut of memory!\n");
119 exit(1);
120 }
121 image->rleEnd = 512 + (2 * x);
122 fseek(image->file, 512, SEEK_SET);
123 result = fread(image->rowStart, 1, x, image->file);
124 assert(result == x);
125 result = fread(image->rowSize, 1, x, image->file);
126 assert(result == x);
127 if (swapFlag) {
128 ConvertUint(image->rowStart, x/(int) sizeof(unsigned));
129 ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int));
130 }
131 }
132 return image;
133 }
134
135 static void
136 ImageClose(ImageRec *image) {
137 fclose(image->file);
138 free(image->tmp);
139 free(image);
140 }
141
142 static void
143 ImageGetRow(ImageRec *image, unsigned char *buf, int y, int z) {
144 unsigned char *iPtr, *oPtr, pixel;
145 int count;
146 int result;
147
148 if ((image->type & 0xFF00) == 0x0100) {
149 fseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET);
150 result = fread(image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize],
151 image->file);
152 assert(result == (unsigned int)image->rowSize[y+z*image->ysize]);
153
154 iPtr = image->tmp;
155 oPtr = buf;
156 for (;;) {
157 pixel = *iPtr++;
158 count = (int)(pixel & 0x7F);
159 if (!count) {
160 return;
161 }
162 if (pixel & 0x80) {
163 while (count--) {
164 *oPtr++ = *iPtr++;
165 }
166 } else {
167 pixel = *iPtr++;
168 while (count--) {
169 *oPtr++ = pixel;
170 }
171 }
172 }
173 } else {
174 fseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
175 SEEK_SET);
176 result = fread(buf, 1, image->xsize, image->file);
177 assert(result == image->xsize);
178 }
179 }
180
181 #if 0
182 static GLubyte *
183 read_alpha_texture(char *name, int *width, int *height)
184 {
185 unsigned char *base, *lptr;
186 ImageRec *image;
187 int y;
188
189 image = ImageOpen(name);
190 if(!image) {
191 return NULL;
192 }
193
194 (*width)=image->xsize;
195 (*height)=image->ysize;
196 if (image->zsize != 1) {
197 ImageClose(image);
198 return NULL;
199 }
200
201 base = (unsigned char *)malloc(image->xsize*image->ysize*sizeof(unsigned char));
202 lptr = base;
203 for(y=0; y<image->ysize; y++) {
204 ImageGetRow(image,lptr,y,0);
205 lptr += image->xsize;
206 }
207 ImageClose(image);
208
209 return (unsigned char *) base;
210 }
211 #endif
212
213 static GLubyte *
214 read_rgb_texture(char *name, int *width, int *height)
215 {
216 unsigned char *base, *ptr;
217 unsigned char *rbuf, *gbuf, *bbuf, *abuf;
218 ImageRec *image;
219 int y;
220
221 image = ImageOpen(name);
222
223 if(!image)
224 return NULL;
225 (*width)=image->xsize;
226 (*height)=image->ysize;
227 if (image->zsize != 3 && image->zsize != 4) {
228 ImageClose(image);
229 return NULL;
230 }
231
232 base = (unsigned char*)malloc(image->xsize*image->ysize*sizeof(unsigned int)*3);
233 rbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
234 gbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
235 bbuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
236 abuf = (unsigned char *)malloc(image->xsize*sizeof(unsigned char));
237 if(!base || !rbuf || !gbuf || !bbuf || !abuf) {
238 if (base) free(base);
239 if (rbuf) free(rbuf);
240 if (gbuf) free(gbuf);
241 if (bbuf) free(bbuf);
242 if (abuf) free(abuf);
243 ImageClose(image);
244 return NULL;
245 }
246 ptr = base;
247 for(y=0; y<image->ysize; y++) {
248 if(image->zsize == 4) {
249 ImageGetRow(image,rbuf,y,0);
250 ImageGetRow(image,gbuf,y,1);
251 ImageGetRow(image,bbuf,y,2);
252 ImageGetRow(image,abuf,y,3); /* Discard. */
253 rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
254 ptr += (image->xsize * 3);
255 } else {
256 ImageGetRow(image,rbuf,y,0);
257 ImageGetRow(image,gbuf,y,1);
258 ImageGetRow(image,bbuf,y,2);
259 rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
260 ptr += (image->xsize * 3);
261 }
262 }
263 ImageClose(image);
264 free(rbuf);
265 free(gbuf);
266 free(bbuf);
267 free(abuf);
268
269 return (GLubyte *) base;
270 }
271
272 int main(int argc, char **argv)
273 {
274 int width = 0;
275 int height = 0;
276 GLubyte *data;
277 char buff[32];
278 int n;
279 FILE *fo;
280
281 if (argc != 3)
282 {
283 fprintf(stderr, "usage: %s <infile.rgb> <outfile.p6>\n", argv[0]);
284 return 1;
285 }
286
287 data = read_rgb_texture(argv[1], &width, &height);
288
289 n = sprintf(buff, "P6\n%d %d\n255\n", width, height);
290
291 /* [dBorca] avoid LF to CRLF conversion */
292 if ((fo = fopen(argv[2], "wb")) == NULL) {
293 fprintf(stderr, "Cannot open output file!\n");
294 exit(1);
295 }
296
297 fwrite(buff, n, 1, fo);
298 fwrite(data, width * 3, height, fo);
299
300 fclose(fo);
301
302 return 0;
303 }