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

# User Rev Content
1 gregl 2.17 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2 greg 2.1
3     #ifndef lint
4 gregl 2.17 static char SCCSid[] = "$SunId$ SGI";
5 greg 2.1 #endif
6    
7     /*
8     * Radiance picture to PostScript file translator -- one way!
9     */
10    
11     #include <stdio.h>
12 greg 2.13 #include <math.h>
13 gregl 2.18 #include <ctype.h>
14 greg 2.6 #ifdef MSDOS
15     #include <fcntl.h>
16     #endif
17 greg 2.1 #include "color.h"
18    
19 gregl 2.18 #define UPPER(c) ((c)&~0x20) /* ASCII trick */
20    
21 gregl 2.17 #define CODE6GAM 1.47 /* gamma for 6-bit codes */
22     #define DEFDGAM 1.0 /* default device gamma */
23 greg 2.13
24 greg 2.11 #define GRY -1 /* artificial index for grey */
25    
26 gregl 2.18 #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 greg 2.1
34 greg 2.9 #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 greg 2.1 char code[] = /* 6-bit code lookup table */
40     "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@+";
41    
42     int wrongformat = 0; /* input in wrong format? */
43 greg 2.6 double pixaspect = 1.0; /* pixel aspect ratio */
44 greg 2.1
45 gregl 2.17 double devgam = DEFDGAM; /* device gamma response */
46 gregl 2.18 double hmarg = DEFMARG,
47     vmarg = DEFMARG; /* horizontal and vertical margins */
48     double width = DEFWIDTH,
49     height = DEFHEIGHT; /* default paper width and height */
50 greg 2.11 int docolor = 0; /* produce color image? */
51 greg 2.1 int bradj = 0; /* brightness adjustment */
52 greg 2.4 int ncopies = 1; /* number of copies */
53 greg 2.1
54 greg 2.15 extern int Aputprim(), Bputprim(), Cputprim();
55    
56     int (*putprim)() = Aputprim; /* function for writing scanline */
57    
58 greg 2.1 char *progname;
59    
60     int xmax, ymax;
61    
62 greg 2.6 extern char *malloc();
63 gregl 2.18 extern double unit2inch();
64 greg 2.1
65 greg 2.6
66 greg 2.1 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 gregl 2.18 double d;
85 greg 2.1
86     progname = argv[0];
87    
88     for (i = 1; i < argc; i++)
89     if (argv[i][0] == '-')
90     switch (argv[i][1]) {
91 greg 2.15 case 'b': /* produce b&w PostScript */
92     docolor = 0;
93     break;
94 greg 2.11 case 'c': /* produce color PostScript */
95 greg 2.15 docolor = 1;
96 greg 2.11 break;
97 greg 2.15 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 gregl 2.18 case 'g': /* device gamma adjustment */
107 gregl 2.17 devgam = atof(argv[++i]);
108     break;
109 gregl 2.18 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 greg 2.1 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 greg 2.4 case 'n': /* number of copies */
136     ncopies = atoi(argv[++i]);
137     break;
138 greg 2.1 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 greg 2.7 fprintf(stderr, "%s: can't open output \"%s\"\n",
153 greg 2.1 progname, argv[i+1]);
154     exit(1);
155     }
156 greg 2.6 #ifdef MSDOS
157     setmode(fileno(stdin), O_BINARY);
158     #endif
159 greg 2.1 /* get our header */
160     getheader(stdin, headline, NULL);
161     if (wrongformat || fgetresolu(&xmax, &ymax, stdin) < 0)
162     quiterr("bad picture format");
163 greg 2.13 /* gamma compression */
164 greg 2.15 if (putprim == Cputprim)
165 gregl 2.17 setcolrgam(CODE6GAM/devgam);
166     else if (devgam != 1.)
167     setcolrgam(1./devgam);
168 greg 2.1 /* 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 gregl 2.18 fprintf(stderr,
177     "Usage: %s [-b|c][-A|B|C][-e +/-stops][-p paper][-m[h|v] margin][-g gamma] [input [output]]\n",
178 greg 2.11 progname);
179 gregl 2.18 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 greg 2.1 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 greg 2.15 char *rstr;
288 greg 2.1 int landscape = 0;
289 greg 2.6 double pwidth, pheight;
290     double iwidth, iheight;
291 greg 2.10 /* EPS comments */
292 greg 2.11 puts("%!PS-Adobe-2.0 EPSF-2.0");
293 greg 2.1 printf("%%%%Title: %s\n", name);
294 greg 2.10 printf("%%%%Creator: %s = %s\n", progname, SCCSid);
295 greg 2.4 printf("%%%%Pages: %d\n", ncopies);
296 greg 2.1 if (landscape = xmax > pixaspect*ymax)
297 greg 2.10 puts("%%Orientation: Landscape");
298 greg 2.1 else
299 greg 2.10 puts("%%Orientation: Portrait");
300 greg 2.1 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 greg 2.2 iwidth = pwidth;
309     iheight = pwidth*pixaspect*ymax/xmax;
310 greg 2.1 } else {
311 greg 2.2 iheight = pheight;
312     iwidth = pheight*xmax/(pixaspect*ymax);
313 greg 2.1 }
314 greg 2.10 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 greg 2.13 puts("gsave save");
328 greg 2.15 puts("17 dict begin");
329 greg 2.10 /* define image reader */
330 greg 2.11 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 greg 2.15 } else
335     printf("/gryline %d string def\n", xmax);
336     /* use compressed encoding? */
337     if (putprim == Cputprim)
338     PSprocdef("read6bitRLE");
339 greg 2.10 /* set up transformation matrix */
340     printf("%f %f translate\n", HMARGIN, VMARGIN);
341     if (pwidth == PHEIGHT) {
342 greg 2.14 printf("%f 0 translate\n", PWIDTH);
343     puts("90 rotate");
344 greg 2.10 }
345 greg 2.2 printf("%f %f translate\n", (pwidth-iwidth)*.5, (pheight-iheight)*.5);
346     printf("%f %f scale\n", iwidth, iheight);
347 greg 2.12 puts("%%EndProlog");
348 greg 2.3 /* start image procedure */
349 greg 2.15 printf("%d %d 8 [%d 0 0 %d 0 %d]\n", xmax, ymax, xmax, -ymax, ymax);
350     if (putprim == Cputprim) {
351     if (docolor) {
352 greg 2.16 puts("{redline read6bitRLE}");
353     puts("{grnline read6bitRLE}");
354     puts("{bluline read6bitRLE}");
355     puts("true 3 colorimage");
356 greg 2.15 } 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 greg 2.1 }
369    
370    
371     PStrailer() /* print PostScript trailer */
372     {
373     puts("%%Trailer");
374 greg 2.4 if (ncopies > 1)
375     printf("/#copies %d def\n", ncopies);
376     puts("showpage");
377 greg 2.1 puts("end");
378 greg 2.13 puts("restore grestore");
379 greg 2.1 puts("%%EOF");
380     }
381    
382    
383 greg 2.15 PSprocdef(nam) /* define PS procedure to read image */
384     char *nam;
385 greg 2.1 {
386     short itab[128];
387     register int i;
388 greg 2.5 /* assign code values */
389     for (i = 0; i < 128; i++) /* clear */
390 greg 2.1 itab[i] = -1;
391 greg 2.5 for (i = 1; i < 63; i++) /* assign greys */
392 gregl 2.17 itab[code[i]] = 256.0*pow((i+.5)/64.0, CODE6GAM);
393 greg 2.5 itab[code[0]] = 0; /* black is black */
394     itab[code[63]] = 255; /* and white is white */
395 greg 2.9 printf("/codetab [");
396 greg 2.1 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 greg 2.9 printf("/nrept 0 def\n");
403 greg 2.11 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 greg 2.1 printf("\t{ 0 1 %d { scanline exch\n", xmax-1);
408 greg 2.9 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 greg 2.8 printf("} bind def\n");
420 greg 2.1 }
421    
422    
423     ra2ps() /* convert Radiance scanlines to 6-bit */
424     {
425 greg 2.9 register COLR *scanin;
426 greg 2.1 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 gregl 2.17 if (putprim == Cputprim || devgam != 1.) {
436 greg 2.15 if (bradj) /* adjust exposure */
437     shiftcolrs(scanin, xmax, bradj);
438     colrs_gambs(scanin, xmax); /* gamma compression */
439     } else
440     normcolrs(scanin, xmax, bradj);
441 greg 2.11 if (docolor) {
442 greg 2.15 (*putprim)(scanin, RED);
443     (*putprim)(scanin, GRN);
444     (*putprim)(scanin, BLU);
445 greg 2.11 } else
446 greg 2.15 (*putprim)(scanin, GRY);
447 greg 2.1 if (ferror(stdout))
448     quiterr("error writing PostScript file");
449     }
450     putchar('\n');
451     /* free scanline */
452     free((char *)scanin);
453 greg 2.11 }
454    
455    
456 greg 2.15 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 greg 2.11 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 greg 2.9 }
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 greg 2.1 }