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

# 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 gwlarson 2.21 #define DEFGGAM 1.0 /* greyscale device gamma */
23     #define DEFCGAM 1.8 /* color device gamma */
24 greg 2.13
25 greg 2.11 #define GRY -1 /* artificial index for grey */
26    
27 gregl 2.18 #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 greg 2.1
35 greg 2.9 #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 greg 2.1 char code[] = /* 6-bit code lookup table */
41     "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@+";
42    
43     int wrongformat = 0; /* input in wrong format? */
44 greg 2.6 double pixaspect = 1.0; /* pixel aspect ratio */
45 greg 2.1
46 gwlarson 2.21 double devgam = 0.; /* device gamma response */
47 gregl 2.18 double hmarg = DEFMARG,
48     vmarg = DEFMARG; /* horizontal and vertical margins */
49     double width = DEFWIDTH,
50     height = DEFHEIGHT; /* default paper width and height */
51 gregl 2.20 double dpi = 0; /* print density (0 if unknown) */
52 gwlarson 2.21 int docolor = 1; /* produce color image? */
53 greg 2.1 int bradj = 0; /* brightness adjustment */
54 greg 2.4 int ncopies = 1; /* number of copies */
55 greg 2.1
56 greg 2.15 extern int Aputprim(), Bputprim(), Cputprim();
57    
58     int (*putprim)() = Aputprim; /* function for writing scanline */
59    
60 greg 2.1 char *progname;
61    
62 gregl 2.20 int xmax, ymax; /* input image dimensions */
63 greg 2.1
64 greg 2.6 extern char *malloc();
65 gregl 2.18 extern double unit2inch();
66 greg 2.1
67 greg 2.6
68 gwlarson 2.22 int
69 greg 2.1 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 gwlarson 2.22 return(0);
80 greg 2.1 }
81    
82    
83     main(argc, argv)
84     int argc;
85     char *argv[];
86     {
87     int i;
88 gregl 2.18 double d;
89 greg 2.1
90     progname = argv[0];
91    
92     for (i = 1; i < argc; i++)
93     if (argv[i][0] == '-')
94     switch (argv[i][1]) {
95 greg 2.15 case 'b': /* produce b&w PostScript */
96     docolor = 0;
97     break;
98 greg 2.11 case 'c': /* produce color PostScript */
99 greg 2.15 docolor = 1;
100 greg 2.11 break;
101 greg 2.15 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 gregl 2.20 case 'd': /* print density */
111     dpi = atof(argv[++i]);
112     break;
113 gregl 2.18 case 'g': /* device gamma adjustment */
114 gregl 2.17 devgam = atof(argv[++i]);
115     break;
116 gregl 2.18 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 greg 2.1 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 greg 2.4 case 'n': /* number of copies */
143     ncopies = atoi(argv[++i]);
144     break;
145 greg 2.1 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 greg 2.7 fprintf(stderr, "%s: can't open output \"%s\"\n",
160 greg 2.1 progname, argv[i+1]);
161     exit(1);
162     }
163 greg 2.6 #ifdef MSDOS
164     setmode(fileno(stdin), O_BINARY);
165     #endif
166 greg 2.1 /* get our header */
167     getheader(stdin, headline, NULL);
168     if (wrongformat || fgetresolu(&xmax, &ymax, stdin) < 0)
169     quiterr("bad picture format");
170 greg 2.13 /* gamma compression */
171 gwlarson 2.21 if (devgam <= 0.05)
172     devgam = docolor ? DEFCGAM : DEFGGAM;
173 greg 2.15 if (putprim == Cputprim)
174 gregl 2.19 setcolrgam(CODE6GAM);
175 gregl 2.17 else if (devgam != 1.)
176 gregl 2.19 setcolrgam(devgam);
177 greg 2.1 /* write header */
178 gwlarson 2.21 PSheader(argc, argv);
179 greg 2.1 /* convert file */
180     ra2ps();
181     /* write trailer */
182     PStrailer();
183     exit(0);
184     userr:
185 gregl 2.18 fprintf(stderr,
186 gregl 2.20 "Usage: %s [-b|c][-A|B|C][-e +/-stops][-p paper][-m[h|v] margin][-d dpi][-g gamma] [input [output]]\n",
187 greg 2.11 progname);
188 gregl 2.18 exit(1);
189     }
190    
191    
192     double
193     unit2inch(s) /* determine unit */
194     register char *s;
195     {
196 gwlarson 2.23 static struct unit {char n; float f;} u[] = {
197 gregl 2.18 '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 gregl 2.19 "envelope", 4.12, 9.5,
236     "executive", 7.25, 10.5,
237 gregl 2.18 "letter", 8.5, 11.,
238 gregl 2.19 "lettersmall", 7.68, 10.16,
239 gregl 2.18 "legal", 8.5, 14.,
240     "monarch", 3.87, 7.5,
241 gregl 2.19 "statement", 5.5, 8.5,
242 gregl 2.18 "tabloid", 11., 17.,
243     "A3", 11.69, 16.54,
244     "A4", 8.27, 11.69,
245 gregl 2.19 "A4small", 7.47, 10.85,
246 gregl 2.18 "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 gregl 2.19 "DL", 4.33, 8.66,
253 gregl 2.18 "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 gregl 2.19 fprintf(stderr, "Or use WWxHH size specification\n");
282 greg 2.1 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 gwlarson 2.21 PSheader(ac, av) /* print PostScript header */
298     int ac;
299     char **av;
300 greg 2.1 {
301 greg 2.15 char *rstr;
302 gregl 2.20 int landscape, rotate, n;
303 greg 2.6 double pwidth, pheight;
304     double iwidth, iheight;
305 greg 2.10 /* EPS comments */
306 greg 2.11 puts("%!PS-Adobe-2.0 EPSF-2.0");
307 gwlarson 2.21 printf("%%%%Title: "); printargs(ac, av, stdout);
308     printf("%%%%Creator: %s\n", SCCSid);
309 greg 2.4 printf("%%%%Pages: %d\n", ncopies);
310 greg 2.1 if (landscape = xmax > pixaspect*ymax)
311 greg 2.10 puts("%%Orientation: Landscape");
312 greg 2.1 else
313 greg 2.10 puts("%%Orientation: Portrait");
314 gregl 2.20 if (rotate = PWIDTH > PHEIGHT ^ landscape) {
315 greg 2.1 pwidth = PHEIGHT;
316     pheight = PWIDTH;
317     } else {
318     pwidth = PWIDTH;
319     pheight = PHEIGHT;
320     }
321 gregl 2.20 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 greg 2.10 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 greg 2.13 puts("gsave save");
353 greg 2.15 puts("17 dict begin");
354 greg 2.10 /* define image reader */
355 greg 2.11 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 greg 2.15 } else
360     printf("/gryline %d string def\n", xmax);
361     /* use compressed encoding? */
362     if (putprim == Cputprim)
363     PSprocdef("read6bitRLE");
364 greg 2.10 /* set up transformation matrix */
365     printf("%f %f translate\n", HMARGIN, VMARGIN);
366 gregl 2.20 if (rotate) {
367 greg 2.14 printf("%f 0 translate\n", PWIDTH);
368     puts("90 rotate");
369 greg 2.10 }
370 greg 2.2 printf("%f %f translate\n", (pwidth-iwidth)*.5, (pheight-iheight)*.5);
371     printf("%f %f scale\n", iwidth, iheight);
372 greg 2.12 puts("%%EndProlog");
373 greg 2.3 /* start image procedure */
374 greg 2.15 printf("%d %d 8 [%d 0 0 %d 0 %d]\n", xmax, ymax, xmax, -ymax, ymax);
375     if (putprim == Cputprim) {
376     if (docolor) {
377 greg 2.16 puts("{redline read6bitRLE}");
378     puts("{grnline read6bitRLE}");
379     puts("{bluline read6bitRLE}");
380     puts("true 3 colorimage");
381 greg 2.15 } 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 greg 2.1 }
394    
395    
396     PStrailer() /* print PostScript trailer */
397     {
398     puts("%%Trailer");
399 greg 2.4 if (ncopies > 1)
400     printf("/#copies %d def\n", ncopies);
401     puts("showpage");
402 greg 2.1 puts("end");
403 greg 2.13 puts("restore grestore");
404 greg 2.1 puts("%%EOF");
405     }
406    
407    
408 greg 2.15 PSprocdef(nam) /* define PS procedure to read image */
409     char *nam;
410 greg 2.1 {
411     short itab[128];
412     register int i;
413 greg 2.5 /* assign code values */
414     for (i = 0; i < 128; i++) /* clear */
415 greg 2.1 itab[i] = -1;
416 greg 2.5 for (i = 1; i < 63; i++) /* assign greys */
417 gregl 2.19 itab[code[i]] = 256.0*pow((i+.5)/64.0, CODE6GAM/devgam);
418 greg 2.5 itab[code[0]] = 0; /* black is black */
419     itab[code[63]] = 255; /* and white is white */
420 greg 2.9 printf("/codetab [");
421 greg 2.1 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 greg 2.9 printf("/nrept 0 def\n");
428 greg 2.11 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 greg 2.1 printf("\t{ 0 1 %d { scanline exch\n", xmax-1);
433 greg 2.9 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 greg 2.8 printf("} bind def\n");
445 greg 2.1 }
446    
447    
448     ra2ps() /* convert Radiance scanlines to 6-bit */
449     {
450 greg 2.9 register COLR *scanin;
451 greg 2.1 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 gregl 2.17 if (putprim == Cputprim || devgam != 1.) {
461 greg 2.15 if (bradj) /* adjust exposure */
462     shiftcolrs(scanin, xmax, bradj);
463     colrs_gambs(scanin, xmax); /* gamma compression */
464     } else
465     normcolrs(scanin, xmax, bradj);
466 greg 2.11 if (docolor) {
467 greg 2.15 (*putprim)(scanin, RED);
468     (*putprim)(scanin, GRN);
469     (*putprim)(scanin, BLU);
470 greg 2.11 } else
471 greg 2.15 (*putprim)(scanin, GRY);
472 greg 2.1 if (ferror(stdout))
473     quiterr("error writing PostScript file");
474     }
475     putchar('\n');
476     /* free scanline */
477     free((char *)scanin);
478 greg 2.11 }
479    
480    
481 greg 2.15 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 greg 2.11 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 greg 2.9 }
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 greg 2.1 }