ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ppm.c
Revision: 2.8
Committed: Wed Feb 10 08:43:41 1999 UTC (25 years, 2 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 2.7: +291 -37 lines
Log Message:
added -s and -b options for greyscale and high-precision output

File Contents

# Content
1 /* Copyright (c) 1992 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * program to convert between RADIANCE and Poskanzer Pixmaps
9 */
10
11 #include <stdio.h>
12
13 #ifdef MSDOS
14 #include <fcntl.h>
15 #endif
16
17 #include <math.h>
18
19 #include <ctype.h>
20
21 #include "color.h"
22
23 #include "resolu.h"
24
25
26 extern char *malloc();
27
28 int agryscan(), bgryscan(), aclrscan(), bclrscan();
29 int agryscan2(), bgryscan2(), aclrscan2(), bclrscan2();
30 int normval();
31 unsigned int scanint(), intv(), getby2();
32
33 #define fltv(i) (((i)+.5)/(maxval+1.))
34
35 int bradj = 0; /* brightness adjustment */
36
37 double gamcor = 2.2; /* gamma correction value */
38
39 int maxval = 255; /* maximum primary value */
40
41 char *progname;
42
43 int xmax, ymax;
44
45
46 main(argc, argv)
47 int argc;
48 char *argv[];
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 #ifdef MSDOS
108 if (ptype > 4)
109 setmode(fileno(stdin), O_BINARY);
110 setmode(fileno(stdout), O_BINARY);
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 #ifdef MSDOS
158 setmode(fileno(stdin), O_BINARY);
159 if (binflag)
160 setmode(fileno(stdout), O_BINARY);
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 quiterr(err) /* print message and exit */
185 char *err;
186 {
187 if (err != NULL) {
188 fprintf(stderr, "%s: %s\n", progname, err);
189 exit(1);
190 }
191 exit(0);
192 }
193
194
195 ppm2ra(getscan) /* convert 1-byte Pixmap to Radiance picture */
196 int (*getscan)();
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((char *)scanout);
216 }
217
218
219 ra2ppm(binary, grey) /* convert Radiance picture to Pixmap */
220 int binary, grey;
221 {
222 COLR *scanin;
223 register int x;
224 int y;
225 /* allocate scanline */
226 scanin = (COLR *)malloc(xmax*sizeof(COLR));
227 if (scanin == NULL)
228 quiterr("out of memory in ra2ppm");
229 /* convert image */
230 for (y = ymax-1; y >= 0; y--) {
231 if (freadcolrs(scanin, xmax, stdin) < 0)
232 quiterr("error reading Radiance picture");
233 if (bradj)
234 shiftcolrs(scanin, xmax, bradj);
235 for (x = grey?xmax:0; x--; )
236 scanin[x][GRN] = normbright(scanin[x]);
237 colrs_gambs(scanin, xmax);
238 if (grey)
239 if (binary)
240 for (x = 0; x < xmax; x++)
241 putc(scanin[x][GRN], stdout);
242 else
243 for (x = 0; x < xmax; x++)
244 printf("%d\n", scanin[x][GRN]);
245 else
246 if (binary)
247 for (x = 0; x < xmax; x++) {
248 putc(scanin[x][RED], stdout);
249 putc(scanin[x][GRN], stdout);
250 putc(scanin[x][BLU], stdout);
251 }
252 else
253 for (x = 0; x < xmax; x++)
254 printf("%d %d %d\n", scanin[x][RED],
255 scanin[x][GRN],
256 scanin[x][BLU]);
257 if (ferror(stdout))
258 quiterr("error writing Pixmap");
259 }
260 /* free scanline */
261 free((char *)scanin);
262 }
263
264
265 ppm2ra2(getscan) /* convert 2-byte Pixmap to Radiance picture */
266 int (*getscan)();
267 {
268 COLOR *scanout;
269 double mult;
270 int y;
271 register int x;
272 /* allocate scanline */
273 scanout = (COLOR *)malloc(xmax*sizeof(COLOR));
274 if (scanout == NULL)
275 quiterr("out of memory in ppm2ra2");
276 if (bradj)
277 mult = pow(2., (double)bradj);
278 /* convert image */
279 for (y = ymax-1; y >= 0; y--) {
280 if ((*getscan)(scanout, xmax, stdin) < 0)
281 quiterr("error reading Pixmap");
282 for (x = gamcor>1.01|gamcor<0.99?xmax:0; x--; ) {
283 colval(scanout[x],RED) =
284 pow(colval(scanout[x],RED), gamcor);
285 colval(scanout[x],GRN) =
286 pow(colval(scanout[x],GRN), gamcor);
287 colval(scanout[x],BLU) =
288 pow(colval(scanout[x],BLU), gamcor);
289 }
290 for (x = bradj?xmax:0; x--; )
291 scalecolor(scanout[x], mult);
292 if (fwritescan(scanout, xmax, stdout) < 0)
293 quiterr("error writing Radiance picture");
294 }
295 /* free scanline */
296 free((char *)scanout);
297 }
298
299
300 ra2ppm2(binary, grey) /* convert Radiance picture to Pixmap (2-byte) */
301 int binary, grey;
302 {
303 COLOR *scanin;
304 double mult, d;
305 register int x;
306 int y;
307 /* allocate scanline */
308 scanin = (COLOR *)malloc(xmax*sizeof(COLOR));
309 if (scanin == NULL)
310 quiterr("out of memory in ra2ppm2");
311 if (bradj)
312 mult = pow(2., (double)bradj);
313 /* convert image */
314 for (y = ymax-1; y >= 0; y--) {
315 if (freadscan(scanin, xmax, stdin) < 0)
316 quiterr("error reading Radiance picture");
317 for (x = bradj?xmax:0; x--; )
318 scalecolor(scanin[x], mult);
319 for (x = grey?xmax:0; x--; )
320 colval(scanin[x],GRN) = bright(scanin[x]);
321 d = 1./gamcor;
322 for (x = d>1.01|d<0.99?xmax:0; x--; ) {
323 colval(scanin[x],GRN) = pow(colval(scanin[x],GRN), d);
324 if (!grey) {
325 colval(scanin[x],RED) =
326 pow(colval(scanin[x],RED), d);
327 colval(scanin[x],BLU) =
328 pow(colval(scanin[x],BLU), d);
329 }
330 }
331 if (grey)
332 if (binary)
333 for (x = 0; x < xmax; x++)
334 putby2(intv(colval(scanin[x],GRN)),
335 stdout);
336 else
337 for (x = 0; x < xmax; x++)
338 printf("%u\n",
339 intv(colval(scanin[x],GRN)));
340 else
341 if (binary)
342 for (x = 0; x < xmax; x++) {
343 putby2(intv(colval(scanin[x],RED)),
344 stdout);
345 putby2(intv(colval(scanin[x],GRN)),
346 stdout);
347 putby2(intv(colval(scanin[x],BLU)),
348 stdout);
349 }
350 else
351 for (x = 0; x < xmax; x++)
352 printf("%u %u %u\n",
353 intv(colval(scanin[x],RED)),
354 intv(colval(scanin[x],GRN)),
355 intv(colval(scanin[x],BLU)));
356 if (ferror(stdout))
357 quiterr("error writing Pixmap");
358 }
359 /* free scanline */
360 free((char *)scanin);
361 }
362
363
364 agryscan(scan, len, fp) /* get an ASCII greyscale scanline */
365 register COLR *scan;
366 register int len;
367 FILE *fp;
368 {
369 while (len-- > 0) {
370 scan[0][RED] =
371 scan[0][GRN] =
372 scan[0][BLU] = normval(scanint(fp));
373 scan++;
374 }
375 return(0);
376 }
377
378
379 bgryscan(scan, len, fp) /* get a binary greyscale scanline */
380 register COLR *scan;
381 int len;
382 register FILE *fp;
383 {
384 register int c;
385
386 while (len-- > 0) {
387 if ((c = getc(fp)) == EOF)
388 return(-1);
389 if (maxval != 255)
390 c = normval(c);
391 scan[0][RED] =
392 scan[0][GRN] =
393 scan[0][BLU] = c;
394 scan++;
395 }
396 return(0);
397 }
398
399
400 aclrscan(scan, len, fp) /* get an ASCII color scanline */
401 register COLR *scan;
402 register int len;
403 FILE *fp;
404 {
405 while (len-- > 0) {
406 scan[0][RED] = normval(scanint(fp));
407 scan[0][GRN] = normval(scanint(fp));
408 scan[0][BLU] = normval(scanint(fp));
409 scan++;
410 }
411 return(0);
412 }
413
414
415 bclrscan(scan, len, fp) /* get a binary color scanline */
416 register COLR *scan;
417 int len;
418 register FILE *fp;
419 {
420 int r, g, b;
421
422 while (len-- > 0) {
423 r = getc(fp);
424 g = getc(fp);
425 if ((b = getc(fp)) == EOF)
426 return(-1);
427 if (maxval == 255) {
428 scan[0][RED] = r;
429 scan[0][GRN] = g;
430 scan[0][BLU] = b;
431 } else {
432 scan[0][RED] = normval(r);
433 scan[0][GRN] = normval(g);
434 scan[0][BLU] = normval(b);
435 }
436 scan++;
437 }
438 return(0);
439 }
440
441
442 agryscan2(scan, len, fp) /* get an ASCII greyscale scanline */
443 register COLOR *scan;
444 register int len;
445 FILE *fp;
446 {
447 while (len-- > 0) {
448 colval(scan[0],RED) =
449 colval(scan[0],GRN) =
450 colval(scan[0],BLU) = fltv(scanint(fp));
451 scan++;
452 }
453 return(0);
454 }
455
456
457 bgryscan2(scan, len, fp) /* get a binary greyscale scanline */
458 register COLOR *scan;
459 int len;
460 register FILE *fp;
461 {
462 register int c;
463
464 while (len-- > 0) {
465 if ((c = getby2(fp)) == EOF)
466 return(-1);
467 colval(scan[0],RED) =
468 colval(scan[0],GRN) =
469 colval(scan[0],BLU) = fltv(c);
470 scan++;
471 }
472 return(0);
473 }
474
475
476 aclrscan2(scan, len, fp) /* get an ASCII color scanline */
477 register COLOR *scan;
478 register int len;
479 FILE *fp;
480 {
481 while (len-- > 0) {
482 colval(scan[0],RED) = fltv(scanint(fp));
483 colval(scan[0],GRN) = fltv(scanint(fp));
484 colval(scan[0],BLU) = fltv(scanint(fp));
485 scan++;
486 }
487 return(0);
488 }
489
490
491 bclrscan2(scan, len, fp) /* get a binary color scanline */
492 register COLOR *scan;
493 int len;
494 register FILE *fp;
495 {
496 int r, g, b;
497
498 while (len-- > 0) {
499 r = getby2(fp);
500 g = getby2(fp);
501 if ((b = getby2(fp)) == EOF)
502 return(-1);
503 scan[0][RED] = fltv(r);
504 scan[0][GRN] = fltv(g);
505 scan[0][BLU] = fltv(b);
506 scan++;
507 }
508 return(0);
509 }
510
511
512 unsigned int
513 scanint(fp) /* scan the next positive integer value */
514 register FILE *fp;
515 {
516 register int c;
517 register unsigned int i;
518 tryagain:
519 while (isspace(c = getc(fp)))
520 ;
521 if (c == EOF)
522 quiterr("unexpected end of file");
523 if (c == '#') { /* comment */
524 while ((c = getc(fp)) != EOF && c != '\n')
525 ;
526 goto tryagain;
527 }
528 /* should be integer */
529 i = 0;
530 do {
531 if (!isdigit(c))
532 quiterr("error reading integer");
533 i = 10*i + c - '0';
534 c = getc(fp);
535 } while (c != EOF && !isspace(c));
536 return(i);
537 }
538
539
540 int
541 normval(v) /* normalize a value to [0,255] */
542 register unsigned int v;
543 {
544 if (v >= maxval)
545 return(255);
546 if (maxval == 255)
547 return(v);
548 return(v*255L/maxval);
549 }
550
551
552 unsigned int
553 getby2(fp) /* return 2-byte quantity from fp */
554 register FILE *fp;
555 {
556 register int lowerb, upperb;
557
558 lowerb = getc(fp);
559 upperb = getc(fp);
560 if (upperb == EOF)
561 return(EOF);
562 return(upperb<<8 | lowerb);
563 }
564
565
566 putby2(w, fp) /* put 2-byte quantity to fp */
567 register unsigned int w;
568 register FILE *fp;
569 {
570 putc(w & 0xff, fp);
571 putc(w>>8 & 0xff, fp);
572 if (ferror(fp)) {
573 fprintf(stderr, "%s: write error on PPM output\n", progname);
574 exit(1);
575 }
576 }
577
578
579 unsigned int
580 intv(v) /* return integer quantity for v */
581 register double v;
582 {
583 if (v >= 0.99999)
584 return(maxval);
585 if (v <= 0.)
586 return(0);
587 return((int)(v*(maxval+1)));
588 }