ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ps.c
Revision: 2.23
Committed: Mon Jul 19 09:53:06 1999 UTC (24 years, 9 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 2.22: +1 -1 lines
Log Message:
added missing semicolon to union declaration

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