ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ppm.c
Revision: 2.12
Committed: Sun Mar 28 20:33:14 2004 UTC (20 years ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1
Changes since 2.11: +115 -72 lines
Log Message:
Continued ANSIfication, and other fixes and clarifications.

File Contents

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