ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ppm.c
Revision: 2.17
Committed: Sat Dec 28 18:05:14 2019 UTC (4 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R3, HEAD
Changes since 2.16: +1 -3 lines
Log Message:
Removed redundant include files

File Contents

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