ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ppm.c
Revision: 2.19
Committed: Sat Jun 7 05:09:46 2025 UTC (13 days, 23 hours ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.18: +1 -2 lines
Log Message:
refactor: Put some declarations into "paths.h" and included in "platform.h"

File Contents

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