ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ppm.c
Revision: 2.11
Committed: Sun Jul 27 22:12:03 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.10: +3 -3 lines
Log Message:
Added grouping parens to reduce ambiguity warnings.

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 schorsch 2.11 static const char RCSid[] = "$Id: ra_ppm.c,v 2.10 2003/06/05 19:29:34 schorsch Exp $";
3 greg 1.1 #endif
4     /*
5     * program to convert between RADIANCE and Poskanzer Pixmaps
6     */
7    
8     #include <stdio.h>
9 greg 2.4 #include <math.h>
10 greg 1.1 #include <ctype.h>
11 greg 2.9 #include <time.h>
12    
13 schorsch 2.10 #include "platform.h"
14 greg 1.1 #include "color.h"
15 greg 1.2 #include "resolu.h"
16    
17 greg 1.1
18     int agryscan(), bgryscan(), aclrscan(), bclrscan();
19 gwlarson 2.8 int agryscan2(), bgryscan2(), aclrscan2(), bclrscan2();
20     int normval();
21     unsigned int scanint(), intv(), getby2();
22 greg 1.1
23 gwlarson 2.8 #define fltv(i) (((i)+.5)/(maxval+1.))
24    
25 greg 1.1 int bradj = 0; /* brightness adjustment */
26    
27 gwlarson 2.8 double gamcor = 2.2; /* gamma correction value */
28    
29 greg 1.1 int maxval = 255; /* maximum primary value */
30    
31     char *progname;
32    
33     int xmax, ymax;
34    
35    
36     main(argc, argv)
37     int argc;
38     char *argv[];
39     {
40 greg 2.3 char inpbuf[2];
41 gwlarson 2.8 int gryflag = 0;
42 greg 1.1 int binflag = 1;
43     int reverse = 0;
44     int ptype;
45     int i;
46    
47     progname = argv[0];
48    
49     for (i = 1; i < argc; i++)
50     if (argv[i][0] == '-')
51     switch (argv[i][1]) {
52 gwlarson 2.8 case 's':
53     maxval = atoi(argv[++i]) & 0xffff;
54     break;
55     case 'b':
56     gryflag = 1;
57     break;
58 greg 1.1 case 'g':
59 greg 2.5 gamcor = atof(argv[++i]);
60 greg 1.1 break;
61     case 'e':
62     if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
63     goto userr;
64     bradj = atoi(argv[++i]);
65     break;
66     case 'a':
67     binflag = 0;
68     break;
69     case 'r':
70     reverse = !reverse;
71     break;
72     default:
73     goto userr;
74     }
75     else
76     break;
77    
78     if (i < argc-2)
79     goto userr;
80     if (i <= argc-1 && freopen(argv[i], "r", stdin) == NULL) {
81     fprintf(stderr, "%s: can't open input \"%s\"\n",
82     progname, argv[i]);
83     exit(1);
84     }
85     if (i == argc-2 && freopen(argv[i+1], "w", stdout) == NULL) {
86 greg 2.6 fprintf(stderr, "%s: can't open output \"%s\"\n",
87 greg 1.1 progname, argv[i+1]);
88     exit(1);
89     }
90 gwlarson 2.8 if (maxval < 256)
91     setcolrgam(gamcor);
92 greg 1.1 if (reverse) {
93     /* get header */
94 greg 2.3 if (read(fileno(stdin), inpbuf, 2) != 2 || inpbuf[0] != 'P')
95 greg 1.1 quiterr("input not a Poskanzer Pixmap");
96 greg 2.3 ptype = inpbuf[1];
97 schorsch 2.10 #ifdef _WIN32
98 greg 2.3 if (ptype > 4)
99 schorsch 2.10 SET_FILE_BINARY(stdin);
100     SET_FILE_BINARY(stdout);
101 greg 2.3 #endif
102 greg 1.1 xmax = scanint(stdin);
103     ymax = scanint(stdin);
104     maxval = scanint(stdin);
105     /* put header */
106 greg 2.7 newheader("RADIANCE", stdout);
107 greg 1.1 printargs(i, argv, stdout);
108     fputformat(COLRFMT, stdout);
109     putchar('\n');
110 greg 1.2 fprtresolu(xmax, ymax, stdout);
111 greg 1.1 /* convert file */
112 gwlarson 2.8 if (maxval >= 256)
113     switch (ptype) {
114     case '2':
115     ppm2ra2(agryscan2);
116     break;
117     case '5':
118     ppm2ra2(bgryscan2);
119     break;
120     case '3':
121     ppm2ra2(aclrscan2);
122     break;
123     case '6':
124     ppm2ra2(bclrscan2);
125     break;
126     default:
127     quiterr("unsupported Pixmap type");
128     }
129     else
130     switch (ptype) {
131     case '2':
132     ppm2ra(agryscan);
133     break;
134     case '5':
135     ppm2ra(bgryscan);
136     break;
137     case '3':
138     ppm2ra(aclrscan);
139     break;
140     case '6':
141     ppm2ra(bclrscan);
142     break;
143     default:
144     quiterr("unsupported Pixmap type");
145     }
146 greg 1.1 } else {
147 schorsch 2.10 #ifdef _WIN32
148     SET_FILE_BINARY(stdin);
149 greg 2.3 if (binflag)
150 schorsch 2.10 SET_FILE_BINARY(stdout);
151 greg 2.3 #endif
152 greg 1.1 /* get header info. */
153     if (checkheader(stdin, COLRFMT, NULL) < 0 ||
154 greg 1.2 fgetresolu(&xmax, &ymax, stdin) < 0)
155 greg 1.1 quiterr("bad picture format");
156     /* write PPM header */
157 gwlarson 2.8 printf("P%1d\n%d %d\n%u\n", (gryflag?2:3)+(binflag?3:0),
158 greg 1.1 xmax, ymax, maxval);
159     /* convert file */
160 gwlarson 2.8 if (maxval >= 256)
161     ra2ppm2(binflag, gryflag);
162     else
163     ra2ppm(binflag, gryflag);
164 greg 1.1 }
165     exit(0);
166     userr:
167     fprintf(stderr,
168 gwlarson 2.8 "Usage: %s [-r][-a][-b][-s maxv][-g gamma][-e +/-stops] [input [output]]\n",
169 greg 1.1 progname);
170     exit(1);
171     }
172    
173    
174     quiterr(err) /* print message and exit */
175     char *err;
176     {
177     if (err != NULL) {
178     fprintf(stderr, "%s: %s\n", progname, err);
179     exit(1);
180     }
181     exit(0);
182     }
183    
184    
185 gwlarson 2.8 ppm2ra(getscan) /* convert 1-byte Pixmap to Radiance picture */
186 greg 1.1 int (*getscan)();
187     {
188     COLR *scanout;
189     int y;
190     /* allocate scanline */
191     scanout = (COLR *)malloc(xmax*sizeof(COLR));
192     if (scanout == NULL)
193     quiterr("out of memory in ppm2ra");
194     /* convert image */
195     for (y = ymax-1; y >= 0; y--) {
196     if ((*getscan)(scanout, xmax, stdin) < 0)
197     quiterr("error reading Pixmap");
198     gambs_colrs(scanout, xmax);
199     if (bradj)
200     shiftcolrs(scanout, xmax, bradj);
201     if (fwritecolrs(scanout, xmax, stdout) < 0)
202     quiterr("error writing Radiance picture");
203     }
204     /* free scanline */
205 greg 2.9 free((void *)scanout);
206 greg 1.1 }
207    
208    
209 gwlarson 2.8 ra2ppm(binary, grey) /* convert Radiance picture to Pixmap */
210     int binary, grey;
211 greg 1.1 {
212     COLR *scanin;
213     register int x;
214     int y;
215     /* allocate scanline */
216     scanin = (COLR *)malloc(xmax*sizeof(COLR));
217     if (scanin == NULL)
218 gwlarson 2.8 quiterr("out of memory in ra2ppm");
219 greg 1.1 /* convert image */
220     for (y = ymax-1; y >= 0; y--) {
221     if (freadcolrs(scanin, xmax, stdin) < 0)
222     quiterr("error reading Radiance picture");
223     if (bradj)
224     shiftcolrs(scanin, xmax, bradj);
225 gwlarson 2.8 for (x = grey?xmax:0; x--; )
226     scanin[x][GRN] = normbright(scanin[x]);
227 greg 1.1 colrs_gambs(scanin, xmax);
228 gwlarson 2.8 if (grey)
229     if (binary)
230     for (x = 0; x < xmax; x++)
231     putc(scanin[x][GRN], stdout);
232     else
233     for (x = 0; x < xmax; x++)
234     printf("%d\n", scanin[x][GRN]);
235     else
236     if (binary)
237     for (x = 0; x < xmax; x++) {
238     putc(scanin[x][RED], stdout);
239     putc(scanin[x][GRN], stdout);
240     putc(scanin[x][BLU], stdout);
241     }
242     else
243     for (x = 0; x < xmax; x++)
244     printf("%d %d %d\n", scanin[x][RED],
245     scanin[x][GRN],
246     scanin[x][BLU]);
247     if (ferror(stdout))
248     quiterr("error writing Pixmap");
249     }
250     /* free scanline */
251 greg 2.9 free((void *)scanin);
252 gwlarson 2.8 }
253    
254    
255     ppm2ra2(getscan) /* convert 2-byte Pixmap to Radiance picture */
256     int (*getscan)();
257     {
258     COLOR *scanout;
259     double mult;
260     int y;
261     register int x;
262     /* allocate scanline */
263     scanout = (COLOR *)malloc(xmax*sizeof(COLOR));
264     if (scanout == NULL)
265     quiterr("out of memory in ppm2ra2");
266     if (bradj)
267     mult = pow(2., (double)bradj);
268     /* convert image */
269     for (y = ymax-1; y >= 0; y--) {
270     if ((*getscan)(scanout, xmax, stdin) < 0)
271     quiterr("error reading Pixmap");
272 schorsch 2.11 for (x = (gamcor>1.01)|(gamcor<0.99)?xmax:0; x--; ) {
273 gwlarson 2.8 colval(scanout[x],RED) =
274     pow(colval(scanout[x],RED), gamcor);
275     colval(scanout[x],GRN) =
276     pow(colval(scanout[x],GRN), gamcor);
277     colval(scanout[x],BLU) =
278     pow(colval(scanout[x],BLU), gamcor);
279     }
280     for (x = bradj?xmax:0; x--; )
281     scalecolor(scanout[x], mult);
282     if (fwritescan(scanout, xmax, stdout) < 0)
283     quiterr("error writing Radiance picture");
284     }
285     /* free scanline */
286 greg 2.9 free((void *)scanout);
287 gwlarson 2.8 }
288    
289    
290     ra2ppm2(binary, grey) /* convert Radiance picture to Pixmap (2-byte) */
291     int binary, grey;
292     {
293     COLOR *scanin;
294     double mult, d;
295     register int x;
296     int y;
297     /* allocate scanline */
298     scanin = (COLOR *)malloc(xmax*sizeof(COLOR));
299     if (scanin == NULL)
300     quiterr("out of memory in ra2ppm2");
301     if (bradj)
302     mult = pow(2., (double)bradj);
303     /* convert image */
304     for (y = ymax-1; y >= 0; y--) {
305     if (freadscan(scanin, xmax, stdin) < 0)
306     quiterr("error reading Radiance picture");
307     for (x = bradj?xmax:0; x--; )
308     scalecolor(scanin[x], mult);
309     for (x = grey?xmax:0; x--; )
310     colval(scanin[x],GRN) = bright(scanin[x]);
311     d = 1./gamcor;
312 schorsch 2.11 for (x = (d>1.01)|(d<0.99)?xmax:0; x--; ) {
313 gwlarson 2.8 colval(scanin[x],GRN) = pow(colval(scanin[x],GRN), d);
314     if (!grey) {
315     colval(scanin[x],RED) =
316     pow(colval(scanin[x],RED), d);
317     colval(scanin[x],BLU) =
318     pow(colval(scanin[x],BLU), d);
319 greg 1.1 }
320 gwlarson 2.8 }
321     if (grey)
322     if (binary)
323     for (x = 0; x < xmax; x++)
324     putby2(intv(colval(scanin[x],GRN)),
325     stdout);
326     else
327     for (x = 0; x < xmax; x++)
328     printf("%u\n",
329     intv(colval(scanin[x],GRN)));
330 greg 1.1 else
331 gwlarson 2.8 if (binary)
332     for (x = 0; x < xmax; x++) {
333     putby2(intv(colval(scanin[x],RED)),
334     stdout);
335     putby2(intv(colval(scanin[x],GRN)),
336     stdout);
337     putby2(intv(colval(scanin[x],BLU)),
338     stdout);
339     }
340     else
341     for (x = 0; x < xmax; x++)
342     printf("%u %u %u\n",
343     intv(colval(scanin[x],RED)),
344     intv(colval(scanin[x],GRN)),
345     intv(colval(scanin[x],BLU)));
346 greg 1.1 if (ferror(stdout))
347     quiterr("error writing Pixmap");
348     }
349     /* free scanline */
350 greg 2.9 free((void *)scanin);
351 greg 1.1 }
352    
353    
354     agryscan(scan, len, fp) /* get an ASCII greyscale scanline */
355     register COLR *scan;
356     register int len;
357     FILE *fp;
358     {
359     while (len-- > 0) {
360     scan[0][RED] =
361     scan[0][GRN] =
362     scan[0][BLU] = normval(scanint(fp));
363     scan++;
364     }
365     return(0);
366     }
367    
368    
369     bgryscan(scan, len, fp) /* get a binary greyscale scanline */
370     register COLR *scan;
371     int len;
372     register FILE *fp;
373     {
374     register int c;
375    
376     while (len-- > 0) {
377     if ((c = getc(fp)) == EOF)
378     return(-1);
379     if (maxval != 255)
380     c = normval(c);
381     scan[0][RED] =
382     scan[0][GRN] =
383     scan[0][BLU] = c;
384     scan++;
385     }
386     return(0);
387     }
388    
389    
390     aclrscan(scan, len, fp) /* get an ASCII color scanline */
391     register COLR *scan;
392     register int len;
393     FILE *fp;
394     {
395     while (len-- > 0) {
396     scan[0][RED] = normval(scanint(fp));
397     scan[0][GRN] = normval(scanint(fp));
398     scan[0][BLU] = normval(scanint(fp));
399     scan++;
400     }
401     return(0);
402     }
403    
404    
405     bclrscan(scan, len, fp) /* get a binary color scanline */
406     register COLR *scan;
407     int len;
408     register FILE *fp;
409     {
410     int r, g, b;
411    
412     while (len-- > 0) {
413     r = getc(fp);
414     g = getc(fp);
415     if ((b = getc(fp)) == EOF)
416     return(-1);
417     if (maxval == 255) {
418     scan[0][RED] = r;
419     scan[0][GRN] = g;
420     scan[0][BLU] = b;
421     } else {
422     scan[0][RED] = normval(r);
423     scan[0][GRN] = normval(g);
424     scan[0][BLU] = normval(b);
425     }
426     scan++;
427     }
428     return(0);
429     }
430    
431    
432 gwlarson 2.8 agryscan2(scan, len, fp) /* get an ASCII greyscale scanline */
433     register COLOR *scan;
434     register int len;
435     FILE *fp;
436     {
437     while (len-- > 0) {
438     colval(scan[0],RED) =
439     colval(scan[0],GRN) =
440     colval(scan[0],BLU) = fltv(scanint(fp));
441     scan++;
442     }
443     return(0);
444     }
445    
446    
447     bgryscan2(scan, len, fp) /* get a binary greyscale scanline */
448     register COLOR *scan;
449     int len;
450     register FILE *fp;
451     {
452     register int c;
453    
454     while (len-- > 0) {
455     if ((c = getby2(fp)) == EOF)
456     return(-1);
457     colval(scan[0],RED) =
458     colval(scan[0],GRN) =
459     colval(scan[0],BLU) = fltv(c);
460     scan++;
461     }
462     return(0);
463     }
464    
465    
466     aclrscan2(scan, len, fp) /* get an ASCII color scanline */
467     register COLOR *scan;
468     register int len;
469     FILE *fp;
470     {
471     while (len-- > 0) {
472     colval(scan[0],RED) = fltv(scanint(fp));
473     colval(scan[0],GRN) = fltv(scanint(fp));
474     colval(scan[0],BLU) = fltv(scanint(fp));
475     scan++;
476     }
477     return(0);
478     }
479    
480    
481     bclrscan2(scan, len, fp) /* get a binary color scanline */
482     register COLOR *scan;
483     int len;
484     register FILE *fp;
485     {
486     int r, g, b;
487    
488     while (len-- > 0) {
489     r = getby2(fp);
490     g = getby2(fp);
491     if ((b = getby2(fp)) == EOF)
492     return(-1);
493     scan[0][RED] = fltv(r);
494     scan[0][GRN] = fltv(g);
495     scan[0][BLU] = fltv(b);
496     scan++;
497     }
498     return(0);
499     }
500    
501    
502     unsigned int
503 greg 1.1 scanint(fp) /* scan the next positive integer value */
504     register FILE *fp;
505     {
506 gwlarson 2.8 register int c;
507     register unsigned int i;
508 greg 1.1 tryagain:
509     while (isspace(c = getc(fp)))
510     ;
511     if (c == EOF)
512     quiterr("unexpected end of file");
513     if (c == '#') { /* comment */
514     while ((c = getc(fp)) != EOF && c != '\n')
515     ;
516     goto tryagain;
517     }
518     /* should be integer */
519     i = 0;
520     do {
521     if (!isdigit(c))
522     quiterr("error reading integer");
523     i = 10*i + c - '0';
524     c = getc(fp);
525     } while (c != EOF && !isspace(c));
526     return(i);
527     }
528    
529    
530     int
531     normval(v) /* normalize a value to [0,255] */
532 gwlarson 2.8 register unsigned int v;
533 greg 1.1 {
534     if (v >= maxval)
535     return(255);
536     if (maxval == 255)
537     return(v);
538     return(v*255L/maxval);
539 gwlarson 2.8 }
540    
541    
542     unsigned int
543     getby2(fp) /* return 2-byte quantity from fp */
544     register FILE *fp;
545     {
546     register int lowerb, upperb;
547    
548     lowerb = getc(fp);
549     upperb = getc(fp);
550     if (upperb == EOF)
551     return(EOF);
552     return(upperb<<8 | lowerb);
553     }
554    
555    
556     putby2(w, fp) /* put 2-byte quantity to fp */
557     register unsigned int w;
558     register FILE *fp;
559     {
560     putc(w & 0xff, fp);
561     putc(w>>8 & 0xff, fp);
562     if (ferror(fp)) {
563     fprintf(stderr, "%s: write error on PPM output\n", progname);
564     exit(1);
565     }
566     }
567    
568    
569     unsigned int
570     intv(v) /* return integer quantity for v */
571     register double v;
572     {
573     if (v >= 0.99999)
574     return(maxval);
575     if (v <= 0.)
576     return(0);
577     return((int)(v*(maxval+1)));
578 greg 1.1 }