ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ps.c
Revision: 2.21
Committed: Fri Aug 28 10:03:46 1998 UTC (25 years, 8 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 2.20: +12 -8 lines
Log Message:
made different gamma defaults for color and greyscale

File Contents

# Content
1 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * Radiance picture to PostScript file translator -- one way!
9 */
10
11 #include <stdio.h>
12 #include <math.h>
13 #include <ctype.h>
14 #ifdef MSDOS
15 #include <fcntl.h>
16 #endif
17 #include "color.h"
18
19 #define UPPER(c) ((c)&~0x20) /* ASCII trick */
20
21 #define CODE6GAM 1.47 /* gamma for 6-bit codes */
22 #define DEFGGAM 1.0 /* greyscale device gamma */
23 #define DEFCGAM 1.8 /* color device gamma */
24
25 #define GRY -1 /* artificial index for grey */
26
27 #define DEFMARG 0.5 /* default margin (inches) */
28 #define DEFWIDTH 8.5 /* default page width */
29 #define DEFHEIGHT 11 /* default page height */
30 #define HMARGIN (hmarg*72) /* horizontal margin */
31 #define VMARGIN (vmarg*72) /* vertical margin */
32 #define PWIDTH (width*72-2*HMARGIN) /* width of device */
33 #define PHEIGHT (height*72-2*VMARGIN) /* height of device */
34
35 #define RUNCHR '*' /* character to start rle */
36 #define MINRUN 4 /* minimum run-length */
37 #define RSTRT '!' /* character for MINRUN */
38 #define MAXRUN (MINRUN+'~'-RSTRT) /* maximum run-length */
39
40 char code[] = /* 6-bit code lookup table */
41 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@+";
42
43 int wrongformat = 0; /* input in wrong format? */
44 double pixaspect = 1.0; /* pixel aspect ratio */
45
46 double devgam = 0.; /* device gamma response */
47 double hmarg = DEFMARG,
48 vmarg = DEFMARG; /* horizontal and vertical margins */
49 double width = DEFWIDTH,
50 height = DEFHEIGHT; /* default paper width and height */
51 double dpi = 0; /* print density (0 if unknown) */
52 int docolor = 1; /* produce color image? */
53 int bradj = 0; /* brightness adjustment */
54 int ncopies = 1; /* number of copies */
55
56 extern int Aputprim(), Bputprim(), Cputprim();
57
58 int (*putprim)() = Aputprim; /* function for writing scanline */
59
60 char *progname;
61
62 int xmax, ymax; /* input image dimensions */
63
64 extern char *malloc();
65 extern double unit2inch();
66
67
68 headline(s) /* check header line */
69 char *s;
70 {
71 char fmt[32];
72
73 if (isformat(s)) {
74 formatval(fmt, s);
75 wrongformat = strcmp(fmt, COLRFMT);
76 } else if (isaspect(s))
77 pixaspect *= aspectval(s);
78 }
79
80
81 main(argc, argv)
82 int argc;
83 char *argv[];
84 {
85 int i;
86 double d;
87
88 progname = argv[0];
89
90 for (i = 1; i < argc; i++)
91 if (argv[i][0] == '-')
92 switch (argv[i][1]) {
93 case 'b': /* produce b&w PostScript */
94 docolor = 0;
95 break;
96 case 'c': /* produce color PostScript */
97 docolor = 1;
98 break;
99 case 'A': /* standard ASCII encoding */
100 putprim = Aputprim;
101 break;
102 case 'B': /* standard binary encoding */
103 putprim = Bputprim;
104 break;
105 case 'C': /* compressed ASCII encoding */
106 putprim = Cputprim;
107 break;
108 case 'd': /* print density */
109 dpi = atof(argv[++i]);
110 break;
111 case 'g': /* device gamma adjustment */
112 devgam = atof(argv[++i]);
113 break;
114 case 'p': /* paper size */
115 parsepaper(argv[++i]);
116 break;
117 case 'm': /* margin */
118 d = atof(argv[i+1]);
119 d *= unit2inch(argv[i+1]);
120 switch (argv[i][2]) {
121 case '\0':
122 hmarg = vmarg = d;
123 break;
124 case 'h':
125 hmarg = d;
126 break;
127 case 'v':
128 vmarg = d;
129 break;
130 default:
131 goto userr;
132 }
133 i++;
134 break;
135 case 'e': /* exposure adjustment */
136 if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
137 goto userr;
138 bradj = atoi(argv[++i]);
139 break;
140 case 'n': /* number of copies */
141 ncopies = atoi(argv[++i]);
142 break;
143 default:
144 goto userr;
145 }
146 else
147 break;
148
149 if (i < argc-2)
150 goto userr;
151 if (i <= argc-1 && freopen(argv[i], "r", stdin) == NULL) {
152 fprintf(stderr, "%s: can't open input \"%s\"\n",
153 progname, argv[i]);
154 exit(1);
155 }
156 if (i == argc-2 && freopen(argv[i+1], "w", stdout) == NULL) {
157 fprintf(stderr, "%s: can't open output \"%s\"\n",
158 progname, argv[i+1]);
159 exit(1);
160 }
161 #ifdef MSDOS
162 setmode(fileno(stdin), O_BINARY);
163 #endif
164 /* get our header */
165 getheader(stdin, headline, NULL);
166 if (wrongformat || fgetresolu(&xmax, &ymax, stdin) < 0)
167 quiterr("bad picture format");
168 /* gamma compression */
169 if (devgam <= 0.05)
170 devgam = docolor ? DEFCGAM : DEFGGAM;
171 if (putprim == Cputprim)
172 setcolrgam(CODE6GAM);
173 else if (devgam != 1.)
174 setcolrgam(devgam);
175 /* write header */
176 PSheader(argc, argv);
177 /* convert file */
178 ra2ps();
179 /* write trailer */
180 PStrailer();
181 exit(0);
182 userr:
183 fprintf(stderr,
184 "Usage: %s [-b|c][-A|B|C][-e +/-stops][-p paper][-m[h|v] margin][-d dpi][-g gamma] [input [output]]\n",
185 progname);
186 exit(1);
187 }
188
189
190 double
191 unit2inch(s) /* determine unit */
192 register char *s;
193 {
194 static struct unit {char n; float f} u[] = {
195 'i', 1.,
196 'm', 1./25.4,
197 'c', 1./2.54,
198 '\0' };
199 register struct unit *up;
200
201 while (*s && !isalpha(*s))
202 s++;
203 for (up = u; up->n; up++)
204 if (up->n == *s)
205 return(up->f);
206 return(1.);
207 }
208
209
210 int
211 matchid(name, id) /* see if name matches id (case insensitive) */
212 char *name;
213 register char *id;
214 {
215 register char *s = name;
216
217 while (*s) {
218 if (isalpha(*s)) {
219 if (!isalpha(*id) || UPPER(*s) != UPPER(*id))
220 return(0);
221 } else if (*s != *id)
222 return(0);
223 s++; id++;
224 }
225 return(!*id || s-name >= 3); /* substrings >= 3 chars OK */
226 }
227
228
229 parsepaper(ps) /* determine paper size from name */
230 char *ps;
231 {
232 static struct psize {char n[12]; float w,h;} p[] = {
233 "envelope", 4.12, 9.5,
234 "executive", 7.25, 10.5,
235 "letter", 8.5, 11.,
236 "lettersmall", 7.68, 10.16,
237 "legal", 8.5, 14.,
238 "monarch", 3.87, 7.5,
239 "statement", 5.5, 8.5,
240 "tabloid", 11., 17.,
241 "A3", 11.69, 16.54,
242 "A4", 8.27, 11.69,
243 "A4small", 7.47, 10.85,
244 "A5", 6.00, 8.27,
245 "A6", 4.13, 6.00,
246 "B4", 10.12, 14.33,
247 "B5", 7.17, 10.12,
248 "C5", 6.38, 9.01,
249 "C6", 4.49, 6.38,
250 "DL", 4.33, 8.66,
251 "hagaki", 3.94, 5.83,
252 "" };
253 register struct psize *pp;
254 register char *s = ps;
255 double d;
256
257 if (isdigit(*s)) { /* check for WWxHH specification */
258 width = atof(s);
259 while (*s && !isalpha(*s))
260 s++;
261 d = unit2inch(s);
262 height = atof(++s);
263 width *= d;
264 height *= d;
265 if (width >= 1. & height >= 1.)
266 return;
267 } else /* check for match to standard size */
268 for (pp = p; pp->n[0]; pp++)
269 if (matchid(s, pp->n)) {
270 width = pp->w;
271 height = pp->h;
272 return;
273 }
274 fprintf(stderr, "%s: unknown paper size \"%s\" -- known sizes:\n",
275 progname, ps);
276 fprintf(stderr, "_Name________Width_Height_(inches)\n");
277 for (pp = p; pp->n[0]; pp++)
278 fprintf(stderr, "%-11s %5.2f %5.2f\n", pp->n, pp->w, pp->h);
279 fprintf(stderr, "Or use WWxHH size specification\n");
280 exit(1);
281 }
282
283
284 quiterr(err) /* print message and exit */
285 char *err;
286 {
287 if (err != NULL) {
288 fprintf(stderr, "%s: %s\n", progname, err);
289 exit(1);
290 }
291 exit(0);
292 }
293
294
295 PSheader(ac, av) /* print PostScript header */
296 int ac;
297 char **av;
298 {
299 char *rstr;
300 int landscape, rotate, n;
301 double pwidth, pheight;
302 double iwidth, iheight;
303 /* EPS comments */
304 puts("%!PS-Adobe-2.0 EPSF-2.0");
305 printf("%%%%Title: "); printargs(ac, av, stdout);
306 printf("%%%%Creator: %s\n", SCCSid);
307 printf("%%%%Pages: %d\n", ncopies);
308 if (landscape = xmax > pixaspect*ymax)
309 puts("%%Orientation: Landscape");
310 else
311 puts("%%Orientation: Portrait");
312 if (rotate = PWIDTH > PHEIGHT ^ landscape) {
313 pwidth = PHEIGHT;
314 pheight = PWIDTH;
315 } else {
316 pwidth = PWIDTH;
317 pheight = PHEIGHT;
318 }
319 if (dpi > 100 && pixaspect >= 0.99 & pixaspect <= 1.01)
320 if (pheight/pwidth > ymax/xmax) {
321 n = pwidth*dpi/xmax; /* floor */
322 iwidth = n > 0 ? (double)(n*xmax)/dpi : pwidth;
323 iheight = iwidth*ymax/xmax;
324 } else {
325 n = pheight*dpi/ymax; /* floor */
326 iheight = n > 0 ? (double)(n*ymax)/dpi : pheight;
327 iwidth = iheight*xmax/ymax;
328 }
329 else
330 if (pheight/pwidth > pixaspect*ymax/xmax) {
331 iwidth = pwidth;
332 iheight = iwidth*pixaspect*ymax/xmax;
333 } else {
334 iheight = pheight;
335 iwidth = iheight*xmax/(pixaspect*ymax);
336 }
337 if (rotate)
338 printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
339 HMARGIN+(pheight-iheight)*.5,
340 VMARGIN+(pwidth-iwidth)*.5,
341 HMARGIN+(pheight-iheight)*.5+iheight,
342 VMARGIN+(pwidth-iwidth)*.5+iwidth);
343 else
344 printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
345 HMARGIN+(pwidth-iwidth)*.5,
346 VMARGIN+(pheight-iheight)*.5,
347 HMARGIN+(pwidth-iwidth)*.5+iwidth,
348 VMARGIN+(pheight-iheight)*.5+iheight);
349 puts("%%EndComments");
350 puts("gsave save");
351 puts("17 dict begin");
352 /* define image reader */
353 if (docolor) {
354 printf("/redline %d string def\n", xmax);
355 printf("/grnline %d string def\n", xmax);
356 printf("/bluline %d string def\n", xmax);
357 } else
358 printf("/gryline %d string def\n", xmax);
359 /* use compressed encoding? */
360 if (putprim == Cputprim)
361 PSprocdef("read6bitRLE");
362 /* set up transformation matrix */
363 printf("%f %f translate\n", HMARGIN, VMARGIN);
364 if (rotate) {
365 printf("%f 0 translate\n", PWIDTH);
366 puts("90 rotate");
367 }
368 printf("%f %f translate\n", (pwidth-iwidth)*.5, (pheight-iheight)*.5);
369 printf("%f %f scale\n", iwidth, iheight);
370 puts("%%EndProlog");
371 /* start image procedure */
372 printf("%d %d 8 [%d 0 0 %d 0 %d]\n", xmax, ymax, xmax, -ymax, ymax);
373 if (putprim == Cputprim) {
374 if (docolor) {
375 puts("{redline read6bitRLE}");
376 puts("{grnline read6bitRLE}");
377 puts("{bluline read6bitRLE}");
378 puts("true 3 colorimage");
379 } else
380 puts("{gryline read6bitRLE} image");
381 } else {
382 rstr = putprim==Aputprim ? "readhexstring" : "readstring";
383 if (docolor) {
384 printf("{currentfile redline %s pop}\n", rstr);
385 printf("{currentfile grnline %s pop}\n", rstr);
386 printf("{currentfile bluline %s pop}\n", rstr);
387 puts("true 3 colorimage");
388 } else
389 printf("{currentfile gryline %s pop} image\n", rstr);
390 }
391 }
392
393
394 PStrailer() /* print PostScript trailer */
395 {
396 puts("%%Trailer");
397 if (ncopies > 1)
398 printf("/#copies %d def\n", ncopies);
399 puts("showpage");
400 puts("end");
401 puts("restore grestore");
402 puts("%%EOF");
403 }
404
405
406 PSprocdef(nam) /* define PS procedure to read image */
407 char *nam;
408 {
409 short itab[128];
410 register int i;
411 /* assign code values */
412 for (i = 0; i < 128; i++) /* clear */
413 itab[i] = -1;
414 for (i = 1; i < 63; i++) /* assign greys */
415 itab[code[i]] = 256.0*pow((i+.5)/64.0, CODE6GAM/devgam);
416 itab[code[0]] = 0; /* black is black */
417 itab[code[63]] = 255; /* and white is white */
418 printf("/codetab [");
419 for (i = 0; i < 128; i++) {
420 if (!(i & 0xf))
421 putchar('\n');
422 printf(" %3d", itab[i]);
423 }
424 printf("\n] def\n");
425 printf("/nrept 0 def\n");
426 printf("/readbyte { currentfile read not {stop} if } bind def\n");
427 printf("/decode { codetab exch get } bind def\n");
428 printf("/%s {\t%% scanbuffer\n", nam);
429 printf("\t/scanline exch def\n");
430 printf("\t{ 0 1 %d { scanline exch\n", xmax-1);
431 printf("\t\tnrept 0 le\n");
432 printf("\t\t\t{ { readbyte dup %d eq\n", RUNCHR);
433 printf("\t\t\t\t\t{ pop /nrept readbyte %d sub def\n", RSTRT-MINRUN+1);
434 printf("\t\t\t\t\t\t/reptv readbyte decode def\n");
435 printf("\t\t\t\t\t\treptv exit }\n");
436 printf("\t\t\t\t\t{ decode dup 0 lt {pop} {exit} ifelse }\n");
437 printf("\t\t\t\tifelse } loop }\n");
438 printf("\t\t\t{ /nrept nrept 1 sub def reptv }\n");
439 printf("\t\tifelse put\n");
440 printf("\t\t} for\n");
441 printf("\t} stopped {pop pop 0 string} {scanline} ifelse\n");
442 printf("} bind def\n");
443 }
444
445
446 ra2ps() /* convert Radiance scanlines to 6-bit */
447 {
448 register COLR *scanin;
449 int y;
450 /* allocate scanline */
451 scanin = (COLR *)malloc(xmax*sizeof(COLR));
452 if (scanin == NULL)
453 quiterr("out of memory in ra2ps");
454 /* convert image */
455 for (y = ymax-1; y >= 0; y--) {
456 if (freadcolrs(scanin, xmax, stdin) < 0)
457 quiterr("error reading Radiance picture");
458 if (putprim == Cputprim || devgam != 1.) {
459 if (bradj) /* adjust exposure */
460 shiftcolrs(scanin, xmax, bradj);
461 colrs_gambs(scanin, xmax); /* gamma compression */
462 } else
463 normcolrs(scanin, xmax, bradj);
464 if (docolor) {
465 (*putprim)(scanin, RED);
466 (*putprim)(scanin, GRN);
467 (*putprim)(scanin, BLU);
468 } else
469 (*putprim)(scanin, GRY);
470 if (ferror(stdout))
471 quiterr("error writing PostScript file");
472 }
473 putchar('\n');
474 /* free scanline */
475 free((char *)scanin);
476 }
477
478
479 int
480 Aputprim(scn, pri) /* put out hex ASCII primary from scanline */
481 COLR *scn;
482 int pri;
483 {
484 static char hexdigit[] = "0123456789ABCDEF";
485 static int col = 0;
486 register int x, c;
487
488 for (x = 0; x < xmax; x++) {
489 if (pri == GRY)
490 c = normbright(scn[x]);
491 else
492 c = scn[x][pri];
493 if (c > 255) c = 255;
494 putchar(hexdigit[c>>4]);
495 putchar(hexdigit[c&0xf]);
496 if ((col += 2) >= 72) {
497 putchar('\n');
498 col = 0;
499 }
500 }
501 }
502
503
504 int
505 Bputprim(scn, pri) /* put out binary primary from scanline */
506 COLR *scn;
507 int pri;
508 {
509 register int x, c;
510
511 for (x = 0; x < xmax; x++) {
512 if (pri == GRY)
513 c = normbright(scn[x]);
514 else
515 c = scn[x][pri];
516 if (c > 255) c = 255;
517 putchar(c);
518 }
519 }
520
521
522 int
523 Cputprim(scn, pri) /* put out compressed primary from scanline */
524 COLR *scn;
525 int pri;
526 {
527 register int c;
528 register int x;
529 int lastc, cnt;
530
531 lastc = -1; cnt = 0;
532 for (x = 0; x < xmax; x++) {
533 if (pri == GRY)
534 c = normbright(scn[x]) + 2;
535 else
536 c = scn[x][pri] + 2;
537 if (c > 255) c = 255;
538 c = code[c>>2];
539 if (c == lastc && cnt < MAXRUN)
540 cnt++;
541 else {
542 putrle(cnt, lastc);
543 lastc = c;
544 cnt = 1;
545 }
546 }
547 putrle(cnt, lastc);
548 }
549
550
551 putrle(cnt, cod) /* put out cnt of cod */
552 register int cnt, cod;
553 {
554 static int col = 0;
555
556 if (cnt >= MINRUN) {
557 col += 3;
558 putchar(RUNCHR);
559 putchar(RSTRT-MINRUN+cnt);
560 putchar(cod);
561 } else {
562 col += cnt;
563 while (cnt-- > 0)
564 putchar(cod);
565 }
566 if (col >= 72) {
567 putchar('\n');
568 col = 0;
569 }
570 }