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

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