Imported Upstream version 2.3
[xfishtank.git] / rasttofish / rasttofish.c
1 /* rasttofish.c - read a Sun rasterfile and produce an xfish header file
2 **
3 ** All code to read sun rasters came from rasttopnm, his copyright follows.
4 **
5 ** Copyright (C) 1989, 1991 by Jef Poskanzer.
6 **
7 ** Permission to use, copy, modify, and distribute this software and its
8 ** documentation for any purpose and without fee is hereby granted, provided
9 ** that the above copyright notice appear in all copies and that both that
10 ** copyright notice and this permission notice appear in supporting
11 ** documentation. This software is provided "as is" without express or
12 ** implied warranty.
13 */
14
15 #ifdef __STDC__
16 #define ARGS(alist) alist
17 #else /*__STDC__*/
18 #define ARGS(alist) ()
19 #define const
20 #endif /*__STDC__*/
21
22
23 #include <stdio.h>
24 #include "rast.h"
25
26 #define MAXCOLORS 256
27 #define DEFAULT_NAME "fish"
28
29 struct rgb_color {
30 unsigned int red, green, blue;
31 };
32
33
34 int
35 pm_readbiglong(in, lP)
36 FILE *in;
37 long *lP;
38 {
39 int c;
40
41 if ((c = getc(in)) == EOF)
42 return -1;
43 *lP = (c & 0xff) << 24;
44 if ((c = getc(in)) == EOF)
45 return -1;
46 *lP |= (c & 0xff) << 16;
47 if ((c = getc(in)) == EOF)
48 return -1;
49 *lP |= (c & 0xff) << 8;
50 if ((c = getc(in)) == EOF)
51 return -1;
52 *lP |= c & 0xff;
53 return 0;
54 }
55
56 int
57 pr_load_header(in, hP)
58 FILE *in;
59 struct rasterfile *hP;
60 {
61 if (pm_readbiglong(in, &(hP->ras_magic)) == -1)
62 return PIX_ERR;
63 if (hP->ras_magic != RAS_MAGIC)
64 return PIX_ERR;
65 if (pm_readbiglong(in, &(hP->ras_width)) == -1)
66 return PIX_ERR;
67 if (pm_readbiglong(in, &(hP->ras_height)) == -1)
68 return PIX_ERR;
69 if (pm_readbiglong(in, &(hP->ras_depth)) == -1)
70 return PIX_ERR;
71 if (pm_readbiglong(in, &(hP->ras_length)) == -1)
72 return PIX_ERR;
73 if (pm_readbiglong(in, &(hP->ras_type)) == -1)
74 return PIX_ERR;
75 if (pm_readbiglong(in, &(hP->ras_maptype)) == -1)
76 return PIX_ERR;
77 if (pm_readbiglong(in, &(hP->ras_maplength)) == -1)
78 return PIX_ERR;
79 return 0;
80 }
81
82 int
83 pr_load_colormap(in, hP, colormap)
84 FILE *in;
85 struct rasterfile *hP;
86 colormap_t *colormap;
87 {
88 if (colormap == NULL || hP->ras_maptype == RMT_NONE) {
89 char junk[30000];
90
91 if (fread(junk, 1, hP->ras_maplength, in) != hP->ras_maplength)
92 return PIX_ERR;
93 } else {
94 colormap->type = hP->ras_maptype;
95 switch (hP->ras_maptype) {
96 case RMT_EQUAL_RGB:
97 colormap->length = hP->ras_maplength / 3;
98 colormap->map[0] = (unsigned char *) malloc(colormap->length);
99 if (colormap->map[0] == NULL)
100 return PIX_ERR;
101 colormap->map[1] = (unsigned char *) malloc(colormap->length);
102 if (colormap->map[1] == NULL) {
103 free(colormap->map[0]);
104 return PIX_ERR;
105 }
106 colormap->map[2] = (unsigned char *) malloc(colormap->length);
107 if (colormap->map[2] == NULL) {
108 free(colormap->map[0]);
109 free(colormap->map[1]);
110 return PIX_ERR;
111 }
112 if (fread(colormap->map[0], 1, colormap->length, in) != colormap->length ||
113 fread(colormap->map[1], 1, colormap->length, in) != colormap->length ||
114 fread(colormap->map[2], 1, colormap->length, in) != colormap->length) {
115 free(colormap->map[0]);
116 free(colormap->map[1]);
117 free(colormap->map[2]);
118 return PIX_ERR;
119 }
120 break;
121
122 case RMT_RAW:
123 colormap->length = hP->ras_maplength;
124 colormap->map[0] = (unsigned char *) malloc(colormap->length);
125 if (colormap->map[0] == NULL)
126 return PIX_ERR;
127 colormap->map[2] = colormap->map[1] = colormap->map[0];
128 if (fread(colormap->map[0], 1, hP->ras_maplength, in) != hP->ras_maplength) {
129 free(colormap->map[0]);
130 return PIX_ERR;
131 }
132 break;
133
134 default:
135 fprintf(stderr, "unknown colormap type\n");
136 exit(1);
137 }
138 }
139 return 0;
140 }
141
142
143 struct pixrect *
144 mem_create(w, h, depth)
145 int w, h, depth;
146 {
147 struct pixrect *p;
148 struct mpr_data *m;
149
150 p = (struct pixrect *) malloc(sizeof(struct pixrect));
151 if (p == NULL)
152 return NULL;
153 p->pr_ops = NULL;
154 p->pr_size.x = w;
155 p->pr_size.y = h;
156 p->pr_depth = depth;
157 m = p->pr_data = (struct mpr_data *) malloc(sizeof(struct mpr_data));
158 if (m == NULL) {
159 free(p);
160 return NULL;
161 }
162 /* According to the documentation, linebytes is supposed to be rounded
163 ** up to a longword (except on 386 boxes). However, this turns out
164 ** not to be the case. In reality, all of Sun's code rounds up to
165 ** a short, not a long.
166 */
167 m->md_linebytes = (w * depth + 15) / 16 * 2;
168 m->md_offset.x = 0;
169 m->md_offset.y = 0;
170 m->md_flags = 0;
171 m->md_image = (unsigned char *) malloc(m->md_linebytes * h);
172 if (m->md_image == NULL) {
173 free(m);
174 free(p);
175 return NULL;
176 }
177
178 return p;
179 }
180
181
182 void
183 mem_free(p)
184 struct pixrect *p;
185 {
186 free(p->pr_data->md_image);
187 free(p->pr_data);
188 free(p);
189 }
190
191
192
193
194 struct pixrect *
195 pr_load_image(in, hP, colormap)
196 FILE *in;
197 struct rasterfile *hP;
198 colormap_t *colormap;
199 {
200 struct pixrect *p;
201 unsigned char *beimage;
202 register unsigned char *bep;
203 register unsigned char *bp;
204 register unsigned char c;
205 int i;
206 register int j, count;
207
208 p = mem_create(hP->ras_width, hP->ras_height, hP->ras_depth);
209 if (p == NULL)
210 return NULL;
211
212 switch (hP->ras_type) {
213 case RT_OLD:
214 fprintf(stderr, "old rasterfile type is not supported\n");
215 exit(1);
216
217 case RT_FORMAT_TIFF:
218 fprintf(stderr, "tiff rasterfile type is not supported\n");
219 exit(1);
220
221 case RT_FORMAT_IFF:
222 fprintf(stderr, "iff rasterfile type is not supported\n");
223 exit(1);
224
225 case RT_EXPERIMENTAL:
226 fprintf(stderr, "experimental rasterfile type is not supported\n");
227 exit(1);
228
229 case RT_STANDARD:
230 case RT_FORMAT_RGB:
231 /* Ignore hP->ras_length. */
232 i = p->pr_size.y * p->pr_data->md_linebytes;
233 if (fread(p->pr_data->md_image, 1, i, in) != i) {
234 mem_free(p);
235 return NULL;
236 }
237 break;
238
239 case RT_BYTE_ENCODED:
240 beimage = (unsigned char *) malloc(hP->ras_length);
241 if (beimage == NULL) {
242 mem_free(p);
243 return NULL;
244 }
245 if (fread(beimage, 1, hP->ras_length, in) != hP->ras_length) {
246 mem_free(p);
247 free(beimage);
248 return NULL;
249 }
250 bep = beimage;
251 bp = p->pr_data->md_image;
252 for (i = 0; i < hP->ras_length;) {
253 c = *bep++;
254 if (c == 128) {
255 count = (*bep++) + 1;
256 if (count == 1) {
257 *bp++ = 128;
258 i += 2;
259 } else {
260 c = *bep++;
261 for (j = 0; j < count; ++j)
262 *bp++ = c;
263 i += 3;
264 }
265 } else {
266 *bp++ = c;
267 ++i;
268 }
269 }
270 free(beimage);
271 break;
272
273 default:
274 fprintf(stderr, "unknown rasterfile type\n");
275 exit(1);
276 }
277
278 return p;
279 }
280
281
282 unsigned char *
283 ReadRaster(ifp, w, h, colrs)
284 FILE *ifp;
285 int *w, *h;
286 struct rgb_color *colrs;
287 {
288 struct rasterfile header;
289 colormap_t pr_colormap;
290 struct pixrect *pr;
291 unsigned char *data;
292 unsigned char *dptr;
293 unsigned char *rdata;
294 unsigned char *ptr;
295 int linesize;
296 int depth;
297 int maxval;
298 int i, j;
299
300 /* Read in the rasterfile. First the header. */
301 if (pr_load_header(ifp, &header) != 0) {
302 fprintf(stderr, "unable to read in rasterfile header\n");
303 exit(1);
304 }
305
306 *w = header.ras_width;
307 *h = header.ras_height;
308
309 depth = header.ras_depth;
310
311 if (*w <= 0) {
312 fprintf(stderr, "invalid width\n");
313 exit(1);
314 }
315 if (*h <= 0) {
316 fprintf(stderr, "invalid height\n");
317 exit(1);
318 }
319
320 /* If there is a color map, read it. */
321 if (header.ras_maplength != 0) {
322 if (pr_load_colormap(ifp, &header, &pr_colormap) != 0) {
323 fprintf(stderr, "no colormap\n");
324 exit(1);
325 }
326 }
327
328 /* Check the depth and color map. */
329 switch (depth) {
330 case 8:
331 if (header.ras_maptype != RMT_EQUAL_RGB) {
332 fprintf(stderr, "not an RGB colormap\n");
333 exit(1);
334 }
335 maxval = 255;
336 break;
337 default:
338 fprintf(stderr, "Can only handle depth 8 images\n");
339 exit(1);
340 }
341
342 for (i = 0; i < maxval; i++) {
343 colrs[i].red = pr_colormap.map[0][i];
344 colrs[i].green = pr_colormap.map[1][i];
345 colrs[i].blue = pr_colormap.map[2][i];
346 }
347
348 /* Now load the data. The pixrect returned is a memory pixrect. */
349 if ((pr = pr_load_image(ifp, &header, NULL)) == NULL) {
350 fprintf(stderr, "unable to read image from the rasterfile\n");
351 exit(1);
352 }
353
354 linesize = ((struct mpr_data *) pr->pr_data)->md_linebytes;
355 data = ((struct mpr_data *) pr->pr_data)->md_image;
356
357 rdata = (unsigned char *) malloc((*w) * (*h));
358 ptr = rdata;
359 for (j = 0; j < (*h); j++) {
360 dptr = (unsigned char *) data;
361 for (i = 0; i < (*w); i++) {
362 *ptr++ = *dptr++;
363 }
364 data += linesize;
365 }
366 return (rdata);
367 }
368
369
370 struct rgb_color
371 *
372 MapColors(data1, colrs1, data2, colrs2, width, height, Cnt)
373 unsigned char *data1;
374 struct rgb_color *colrs1;
375 unsigned char *data2;
376 struct rgb_color *colrs2;
377 int width, height;
378 int *Cnt;
379 {
380 int i, j;
381 int fcnt, indx;
382 int Mapping[MAXCOLORS];
383 unsigned char *ptr;
384 struct rgb_color *fcolrs;
385
386 fcolrs = (struct rgb_color *) malloc((MAXCOLORS + 1) * sizeof(struct rgb_color));
387
388 fcnt = 0;
389 ptr = data1;
390 for (i = 0; i < (width * height); i++) {
391 indx = (int) *ptr;
392 for (j = 0; j < fcnt; j++) {
393 if ((fcolrs[j].red == colrs1[indx].red) &&
394 (fcolrs[j].green == colrs1[indx].green) &&
395 (fcolrs[j].blue == colrs1[indx].blue)) {
396 break;
397 }
398 }
399 if (j == fcnt) {
400 fcolrs[j].red = colrs1[indx].red;
401 fcolrs[j].green = colrs1[indx].green;
402 fcolrs[j].blue = colrs1[indx].blue;
403 Mapping[indx] = j;
404 fcnt++;
405 if (fcnt > MAXCOLORS) {
406 fprintf(stderr, "Error: cannot use more than %d colors in your fish\n",
407 MAXCOLORS);
408 exit(1);
409 }
410 }
411 ptr++;
412 }
413 ptr = data1;
414 for (i = 0; i < (width * height); i++) {
415 indx = (int) *ptr;
416 *ptr = (unsigned char) (Mapping[indx]);
417 ptr++;
418 }
419
420 ptr = data2;
421 for (i = 0; i < (width * height); i++) {
422 indx = (int) *ptr;
423 for (j = 0; j < fcnt; j++) {
424 if ((fcolrs[j].red == colrs2[indx].red) &&
425 (fcolrs[j].green == colrs2[indx].green) &&
426 (fcolrs[j].blue == colrs2[indx].blue)) {
427 break;
428 }
429 }
430 if (j == fcnt) {
431 fcolrs[j].red = colrs2[indx].red;
432 fcolrs[j].green = colrs2[indx].green;
433 fcolrs[j].blue = colrs2[indx].blue;
434 Mapping[indx] = j;
435 fcnt++;
436 if (fcnt > MAXCOLORS) {
437 fprintf(stderr, "Error: cannot use more than %d colors in your fish\n",
438 MAXCOLORS);
439 exit(1);
440 }
441 }
442 ptr++;
443 }
444 ptr = data2;
445 for (i = 0; i < (width * height); i++) {
446 indx = (int) *ptr;
447 *ptr = (unsigned char) (Mapping[indx]);
448 ptr++;
449 }
450
451 for (i = 0; i < fcnt; i++) {
452 fcolrs[i].red = fcolrs[i].red * 256;
453 fcolrs[i].green = fcolrs[i].green * 256;
454 fcolrs[i].blue = fcolrs[i].blue * 256;
455 }
456 for (i = fcnt; i < 16; i++) {
457 fcolrs[i].red = 0;
458 fcolrs[i].green = 0;
459 fcolrs[i].blue = 0;
460 }
461
462 if (fcnt < 16) {
463 fcnt = 16;
464 }
465 *Cnt = fcnt;
466 return (fcolrs);
467 }
468
469
470 main(argc, argv)
471 int argc;
472 char *argv[];
473 {
474 FILE *ifp;
475 FILE *ofd;
476 int i, j, cnt, fcnt;
477 struct rgb_color colrs1[MAXCOLORS];
478 struct rgb_color colrs2[MAXCOLORS];
479 struct rgb_color *fcolrs;
480 unsigned char *data;
481 unsigned char *ptr, *ptr1, *ptr2;
482 unsigned char *data1, *data2;
483 int width1, height1, width2, height2;
484 char outfile[256];
485 char *outname;
486
487 ifp = NULL;
488 if (argc > 1) {
489 ifp = fopen(argv[1], "r");
490 }
491 if (ifp == NULL) {
492 ifp = stdin;
493 }
494
495 data = ReadRaster(ifp, &width1, &height1, colrs1);
496
497 /* Mirror around Y axis, and copy */
498 for (i = 0; i < MAXCOLORS; i++) {
499 colrs2[i].red = colrs1[i].red;
500 colrs2[i].green = colrs1[i].green;
501 colrs2[i].blue = colrs1[i].blue;
502 }
503 width2 = width1;
504 height2 = height1;
505 data1 = (unsigned char *) malloc(width1 * height1);
506 data2 = (unsigned char *) malloc(width1 * height1);
507 ptr1 = data1;
508 ptr2 = data2;
509 for (j = 0; j < height1; j++) {
510 ptr = (unsigned char *) (data + ((j + 1) * width1) - 1);
511 for (i = 0; i < width1; i++) {
512 *ptr1++ = *ptr;
513 *ptr2++ = *ptr;
514 ptr--;
515 }
516 }
517
518 fcolrs = MapColors(data1, colrs1, data2, colrs2, width1, height1, &fcnt);
519
520 if (argc > 2) {
521 outname = argv[2];
522 } else {
523 cnt = 0;
524 if (argc > 1) {
525 while ((argv[1][cnt] != '.') && (argv[1][cnt] != '\0')) {
526 cnt++;
527 }
528 }
529 if (cnt == 0) {
530 outname = (char *) malloc(strlen(DEFAULT_NAME) + 1);
531 strcpy(outname, DEFAULT_NAME);
532 } else {
533 outname = (char *) malloc(cnt + 1);
534 strncpy(outname, argv[1], cnt);
535 outname[cnt] = '\0';
536 }
537 }
538 sprintf(outfile, "%s.h", outname);
539
540 ofd = fopen(outfile, "w");
541 if (ofd == NULL) {
542 fprintf(stderr, "Error: cannot open (%s) for writing\n", outfile);
543 exit(1);
544 }
545
546 fprintf(ofd, "#define %s_width\t\t%d\n", outname, width1);
547 fprintf(ofd, "#define %s_height\t\t%d\n", outname, height1);
548 fprintf(ofd, "#define %s_colors\t\t%d\n", outname, fcnt);
549 fprintf(ofd, "#define %s_back\t\t%d\n", outname, (int) data1[0]);
550 fprintf(ofd, "int\t%s_reds[] = {", outname);
551 for (i = 0; i < fcnt; i++) {
552 if (i == (fcnt - 1)) {
553 fprintf(ofd, "%d};\n", fcolrs[i].red);
554 } else {
555 fprintf(ofd, "%d, ", fcolrs[i].red);
556 }
557 }
558 fprintf(ofd, "int\t%s_greens[] = {", outname);
559 for (i = 0; i < fcnt; i++) {
560 if (i == (fcnt - 1)) {
561 fprintf(ofd, "%d};\n", fcolrs[i].green);
562 } else {
563 fprintf(ofd, "%d, ", fcolrs[i].green);
564 }
565 }
566 fprintf(ofd, "int\t%s_blues[] = {", outname);
567 for (i = 0; i < fcnt; i++) {
568 if (i == (fcnt - 1)) {
569 fprintf(ofd, "%d};\n", fcolrs[i].blue);
570 } else {
571 fprintf(ofd, "%d, ", fcolrs[i].blue);
572 }
573 }
574 fprintf(ofd, "unsigned char\t%s_rasterA[] = {\n", outname);
575 for (i = 0; i < (width1 * height1); i++) {
576 fprintf(ofd, "0x%02x,", data1[i]);
577 }
578 fprintf(ofd, "};\n");
579 fprintf(ofd, "unsigned char\t%s_rasterB[] = {\n", outname);
580 for (i = 0; i < (width1 * height1); i++) {
581 fprintf(ofd, "0x%02x,", data2[i]);
582 }
583 fprintf(ofd, "};\n");
584
585 fclose(ofd);
586
587 exit(0);
588 }
This page took 0.040558 seconds and 4 git commands to generate.