ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ppm.c
Revision: 2.16
Committed: Tue Mar 20 18:45:04 2018 UTC (6 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2
Changes since 2.15: +2 -1 lines
Log Message:
Added missing rtio.h include to redefine getc, putc, etc.

File Contents

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