ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ppm.c
Revision: 2.12
Committed: Sun Mar 28 20:33:14 2004 UTC (20 years, 1 month ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1
Changes since 2.11: +115 -72 lines
Log Message:
Continued ANSIfication, and other fixes and clarifications.

File Contents

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