ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ps.c
Revision: 2.18
Committed: Thu Sep 18 18:01:24 1997 UTC (26 years, 7 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 2.17: +130 -6 lines
Log Message:
added -m and -p options to specify paper size and margins

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