ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ppm.c
Revision: 2.16
Committed: Tue Mar 20 18:45:04 2018 UTC (6 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2
Changes since 2.15: +2 -1 lines
Log Message:
Added missing rtio.h include to redefine getc, putc, etc.

File Contents

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