ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ppm.c
Revision: 2.18
Committed: Fri Jun 6 19:11:21 2025 UTC (2 weeks, 5 days ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.17: +3 -4 lines
Log Message:
refactor: Making use of printargs() more consistent with fixargv0()

File Contents

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