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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: ra_ppm.c,v 2.17 2019/12/28 18:05:14 greg Exp $";
3 #endif
4 /*
5 * program to convert between RADIANCE and Poskanzer Pixmaps
6 */
7
8 #include <math.h>
9 #include <ctype.h>
10 #include "paths.h"
11 #include "platform.h"
12 #include "rtio.h"
13 #include "color.h"
14 #include "resolu.h"
15
16 #define fltv(i) (((i)+.5)/(maxval+1.))
17 int bradj = 0; /* brightness adjustment */
18 double gamcor = 2.2; /* gamma correction value */
19 int maxval = 255; /* maximum primary value */
20 int xmax, ymax;
21
22 typedef int colrscanf_t(COLR *scan, int len, FILE *fp);
23 typedef int colorscanf_t(COLOR *scan, int len, FILE *fp);
24
25 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
40
41 int
42 main(
43 int argc,
44 char *argv[]
45 )
46 {
47 char inpbuf[2];
48 int gryflag = 0;
49 int binflag = 1;
50 int reverse = 0;
51 int ptype;
52 int i;
53
54 fixargv0(argv[0]);
55
56 for (i = 1; i < argc; i++)
57 if (argv[i][0] == '-')
58 switch (argv[i][1]) {
59 case 's':
60 maxval = atoi(argv[++i]) & 0xffff;
61 break;
62 case 'b':
63 gryflag = 1;
64 break;
65 case 'g':
66 gamcor = atof(argv[++i]);
67 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 fprintf(stderr, "%s: can't open output \"%s\"\n",
94 progname, argv[i+1]);
95 exit(1);
96 }
97 if (maxval < 256)
98 setcolrgam(gamcor);
99 if (reverse) {
100 /* get header */
101 if (read(fileno(stdin), inpbuf, 2) != 2 || inpbuf[0] != 'P')
102 quiterr("input not a Poskanzer Pixmap");
103 ptype = inpbuf[1];
104 #if defined(_WIN32) || defined(_WIN64)
105 if (ptype > 4)
106 SET_FILE_BINARY(stdin);
107 SET_FILE_BINARY(stdout);
108 #endif
109 xmax = scanint(stdin);
110 ymax = scanint(stdin);
111 maxval = scanint(stdin);
112 /* put header */
113 newheader("RADIANCE", stdout);
114 printargs(i, argv, stdout);
115 fputformat(COLRFMT, stdout);
116 putchar('\n');
117 fprtresolu(xmax, ymax, stdout);
118 /* convert file */
119 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 } else {
154 #if defined(_WIN32) || defined(_WIN64)
155 SET_FILE_BINARY(stdin);
156 if (binflag)
157 SET_FILE_BINARY(stdout);
158 #endif
159 /* get header info. */
160 if (checkheader(stdin, COLRFMT, NULL) < 0 ||
161 fgetresolu(&xmax, &ymax, stdin) < 0)
162 quiterr("bad picture format");
163 /* write PPM header */
164 printf("P%1d\n%d %d\n%u\n", (gryflag?2:3)+(binflag?3:0),
165 xmax, ymax, maxval);
166 /* convert file */
167 if (maxval >= 256)
168 ra2ppm2(binflag, gryflag);
169 else
170 ra2ppm(binflag, gryflag);
171 }
172 exit(0);
173 userr:
174 fprintf(stderr,
175 "Usage: %s [-r][-a][-b][-s maxv][-g gamma][-e +/-stops] [input [output]]\n",
176 progname);
177 exit(1);
178 }
179
180
181 static void
182 quiterr( /* print message and exit */
183 char *err
184 )
185 {
186 if (err != NULL) {
187 fprintf(stderr, "%s: %s\n", progname, err);
188 exit(1);
189 }
190 exit(0);
191 }
192
193
194 static void
195 ppm2ra( /* convert 1-byte Pixmap to Radiance picture */
196 colrscanf_t *getscan
197 )
198 {
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 free((void *)scanout);
217 }
218
219
220 static void
221 ra2ppm( /* convert Radiance picture to 1-byte/sample Pixmap */
222 int binary,
223 int grey
224 )
225 {
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 quiterr("out of memory in ra2ppm");
233 /* 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 for (x = grey?xmax:0; x--; )
240 scanin[x][GRN] = normbright(scanin[x]);
241 colrs_gambs(scanin, xmax);
242 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 free((void *)scanin);
266 }
267
268
269 static void
270 ppm2ra2( /* convert 2-byte Pixmap to Radiance picture */
271 colorscanf_t *getscan
272 )
273 {
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 for (x = (gamcor>1.01)|(gamcor<0.99)?xmax:0; x--; ) {
289 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 free((void *)scanout);
303 }
304
305
306 static void
307 ra2ppm2( /* convert Radiance picture to Pixmap (2-byte) */
308 int binary,
309 int grey
310 )
311 {
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 for (x = (d>1.01)|(d<0.99)?xmax:0; x--; ) {
332 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 }
339 }
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 else
350 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 if (ferror(stdout))
366 quiterr("error writing Pixmap");
367 }
368 /* free scanline */
369 free((void *)scanin);
370 }
371
372
373 static int
374 agryscan( /* get an ASCII greyscale scanline */
375 register COLR *scan,
376 register int len,
377 FILE *fp
378 )
379 {
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 static int
391 bgryscan( /* get a binary greyscale scanline */
392 register COLR *scan,
393 int len,
394 register FILE *fp
395 )
396 {
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 static int
414 aclrscan( /* get an ASCII color scanline */
415 register COLR *scan,
416 register int len,
417 FILE *fp
418 )
419 {
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 static int
431 bclrscan( /* get a binary color scanline */
432 register COLR *scan,
433 int len,
434 register FILE *fp
435 )
436 {
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 static int
460 agryscan2( /* get an ASCII greyscale scanline */
461 register COLOR *scan,
462 register int len,
463 FILE *fp
464 )
465 {
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 static int
477 bgryscan2( /* get a binary greyscale scanline */
478 register COLOR *scan,
479 int len,
480 register FILE *fp
481 )
482 {
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 static int
498 aclrscan2( /* get an ASCII color scanline */
499 register COLOR *scan,
500 register int len,
501 FILE *fp
502 )
503 {
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 static int
515 bclrscan2( /* get a binary color scanline */
516 register COLOR *scan,
517 int len,
518 register FILE *fp
519 )
520 {
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 static unsigned int
538 scanint( /* scan the next positive integer value */
539 register FILE *fp
540 )
541 {
542 register int c;
543 register unsigned int i;
544 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 static int
567 normval( /* normalize a value to [0,255] */
568 register unsigned int v
569 )
570 {
571 if (v >= maxval)
572 return(255);
573 if (maxval == 255)
574 return(v);
575 return(v*255L/maxval);
576 }
577
578
579 static unsigned int
580 getby2( /* return 2-byte quantity from fp */
581 register FILE *fp
582 )
583 {
584 register int lowerb, upperb;
585
586 upperb = getc(fp);
587 lowerb = getc(fp);
588 if (lowerb == EOF)
589 return(EOF);
590 return(upperb<<8 | lowerb);
591 }
592
593
594 static void
595 putby2( /* put 2-byte quantity to fp */
596 register unsigned int w,
597 register FILE *fp
598 )
599 {
600 putc(w>>8 & 0xff, fp);
601 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 static unsigned int
610 intv( /* return integer quantity for v */
611 register double v
612 )
613 {
614 if (v >= 0.99999)
615 return(maxval);
616 if (v <= 0.)
617 return(0);
618 return((int)(v*(maxval+1)));
619 }