ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ps.c
Revision: 2.19
Committed: Tue Sep 23 16:52:23 1997 UTC (26 years, 7 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 2.18: +10 -6 lines
Log Message:
fixed gamma correction and added new pages sizes

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.19 setcolrgam(CODE6GAM);
166 gregl 2.17 else if (devgam != 1.)
167 gregl 2.19 setcolrgam(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 gregl 2.19 "envelope", 4.12, 9.5,
227     "executive", 7.25, 10.5,
228 gregl 2.18 "letter", 8.5, 11.,
229 gregl 2.19 "lettersmall", 7.68, 10.16,
230 gregl 2.18 "legal", 8.5, 14.,
231     "monarch", 3.87, 7.5,
232 gregl 2.19 "statement", 5.5, 8.5,
233 gregl 2.18 "tabloid", 11., 17.,
234     "A3", 11.69, 16.54,
235     "A4", 8.27, 11.69,
236 gregl 2.19 "A4small", 7.47, 10.85,
237 gregl 2.18 "A5", 6.00, 8.27,
238     "A6", 4.13, 6.00,
239     "B4", 10.12, 14.33,
240     "B5", 7.17, 10.12,
241     "C5", 6.38, 9.01,
242     "C6", 4.49, 6.38,
243 gregl 2.19 "DL", 4.33, 8.66,
244 gregl 2.18 "hagaki", 3.94, 5.83,
245     "" };
246     register struct psize *pp;
247     register char *s = ps;
248     double d;
249    
250     if (isdigit(*s)) { /* check for WWxHH specification */
251     width = atof(s);
252     while (*s && !isalpha(*s))
253     s++;
254     d = unit2inch(s);
255     height = atof(++s);
256     width *= d;
257     height *= d;
258     if (width >= 1. & height >= 1.)
259     return;
260     } else /* check for match to standard size */
261     for (pp = p; pp->n[0]; pp++)
262     if (matchid(s, pp->n)) {
263     width = pp->w;
264     height = pp->h;
265     return;
266     }
267     fprintf(stderr, "%s: unknown paper size \"%s\" -- known sizes:\n",
268     progname, ps);
269     fprintf(stderr, "_Name________Width_Height_(inches)\n");
270     for (pp = p; pp->n[0]; pp++)
271     fprintf(stderr, "%-11s %5.2f %5.2f\n", pp->n, pp->w, pp->h);
272 gregl 2.19 fprintf(stderr, "Or use WWxHH size specification\n");
273 greg 2.1 exit(1);
274     }
275    
276    
277     quiterr(err) /* print message and exit */
278     char *err;
279     {
280     if (err != NULL) {
281     fprintf(stderr, "%s: %s\n", progname, err);
282     exit(1);
283     }
284     exit(0);
285     }
286    
287    
288     PSheader(name) /* print PostScript header */
289     char *name;
290     {
291 greg 2.15 char *rstr;
292 greg 2.1 int landscape = 0;
293 greg 2.6 double pwidth, pheight;
294     double iwidth, iheight;
295 greg 2.10 /* EPS comments */
296 greg 2.11 puts("%!PS-Adobe-2.0 EPSF-2.0");
297 greg 2.1 printf("%%%%Title: %s\n", name);
298 greg 2.10 printf("%%%%Creator: %s = %s\n", progname, SCCSid);
299 greg 2.4 printf("%%%%Pages: %d\n", ncopies);
300 greg 2.1 if (landscape = xmax > pixaspect*ymax)
301 greg 2.10 puts("%%Orientation: Landscape");
302 greg 2.1 else
303 greg 2.10 puts("%%Orientation: Portrait");
304 greg 2.1 if (PWIDTH > PHEIGHT ^ landscape) {
305     pwidth = PHEIGHT;
306     pheight = PWIDTH;
307     } else {
308     pwidth = PWIDTH;
309     pheight = PHEIGHT;
310     }
311     if (pheight/pwidth > pixaspect*ymax/xmax) {
312 greg 2.2 iwidth = pwidth;
313     iheight = pwidth*pixaspect*ymax/xmax;
314 greg 2.1 } else {
315 greg 2.2 iheight = pheight;
316     iwidth = pheight*xmax/(pixaspect*ymax);
317 greg 2.1 }
318 greg 2.10 if (pwidth == PHEIGHT)
319     printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
320     HMARGIN+(pheight-iheight)*.5,
321     VMARGIN+(pwidth-iwidth)*.5,
322     HMARGIN+(pheight-iheight)*.5+iheight,
323     VMARGIN+(pwidth-iwidth)*.5+iwidth);
324     else
325     printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
326     HMARGIN+(pwidth-iwidth)*.5,
327     VMARGIN+(pheight-iheight)*.5,
328     HMARGIN+(pwidth-iwidth)*.5+iwidth,
329     VMARGIN+(pheight-iheight)*.5+iheight);
330     puts("%%EndComments");
331 greg 2.13 puts("gsave save");
332 greg 2.15 puts("17 dict begin");
333 greg 2.10 /* define image reader */
334 greg 2.11 if (docolor) {
335     printf("/redline %d string def\n", xmax);
336     printf("/grnline %d string def\n", xmax);
337     printf("/bluline %d string def\n", xmax);
338 greg 2.15 } else
339     printf("/gryline %d string def\n", xmax);
340     /* use compressed encoding? */
341     if (putprim == Cputprim)
342     PSprocdef("read6bitRLE");
343 greg 2.10 /* set up transformation matrix */
344     printf("%f %f translate\n", HMARGIN, VMARGIN);
345     if (pwidth == PHEIGHT) {
346 greg 2.14 printf("%f 0 translate\n", PWIDTH);
347     puts("90 rotate");
348 greg 2.10 }
349 greg 2.2 printf("%f %f translate\n", (pwidth-iwidth)*.5, (pheight-iheight)*.5);
350     printf("%f %f scale\n", iwidth, iheight);
351 greg 2.12 puts("%%EndProlog");
352 greg 2.3 /* start image procedure */
353 greg 2.15 printf("%d %d 8 [%d 0 0 %d 0 %d]\n", xmax, ymax, xmax, -ymax, ymax);
354     if (putprim == Cputprim) {
355     if (docolor) {
356 greg 2.16 puts("{redline read6bitRLE}");
357     puts("{grnline read6bitRLE}");
358     puts("{bluline read6bitRLE}");
359     puts("true 3 colorimage");
360 greg 2.15 } else
361     puts("{gryline read6bitRLE} image");
362     } else {
363     rstr = putprim==Aputprim ? "readhexstring" : "readstring";
364     if (docolor) {
365     printf("{currentfile redline %s pop}\n", rstr);
366     printf("{currentfile grnline %s pop}\n", rstr);
367     printf("{currentfile bluline %s pop}\n", rstr);
368     puts("true 3 colorimage");
369     } else
370     printf("{currentfile gryline %s pop} image\n", rstr);
371     }
372 greg 2.1 }
373    
374    
375     PStrailer() /* print PostScript trailer */
376     {
377     puts("%%Trailer");
378 greg 2.4 if (ncopies > 1)
379     printf("/#copies %d def\n", ncopies);
380     puts("showpage");
381 greg 2.1 puts("end");
382 greg 2.13 puts("restore grestore");
383 greg 2.1 puts("%%EOF");
384     }
385    
386    
387 greg 2.15 PSprocdef(nam) /* define PS procedure to read image */
388     char *nam;
389 greg 2.1 {
390     short itab[128];
391     register int i;
392 greg 2.5 /* assign code values */
393     for (i = 0; i < 128; i++) /* clear */
394 greg 2.1 itab[i] = -1;
395 greg 2.5 for (i = 1; i < 63; i++) /* assign greys */
396 gregl 2.19 itab[code[i]] = 256.0*pow((i+.5)/64.0, CODE6GAM/devgam);
397 greg 2.5 itab[code[0]] = 0; /* black is black */
398     itab[code[63]] = 255; /* and white is white */
399 greg 2.9 printf("/codetab [");
400 greg 2.1 for (i = 0; i < 128; i++) {
401     if (!(i & 0xf))
402     putchar('\n');
403     printf(" %3d", itab[i]);
404     }
405     printf("\n] def\n");
406 greg 2.9 printf("/nrept 0 def\n");
407 greg 2.11 printf("/readbyte { currentfile read not {stop} if } bind def\n");
408     printf("/decode { codetab exch get } bind def\n");
409     printf("/%s {\t%% scanbuffer\n", nam);
410     printf("\t/scanline exch def\n");
411 greg 2.1 printf("\t{ 0 1 %d { scanline exch\n", xmax-1);
412 greg 2.9 printf("\t\tnrept 0 le\n");
413     printf("\t\t\t{ { readbyte dup %d eq\n", RUNCHR);
414     printf("\t\t\t\t\t{ pop /nrept readbyte %d sub def\n", RSTRT-MINRUN+1);
415     printf("\t\t\t\t\t\t/reptv readbyte decode def\n");
416     printf("\t\t\t\t\t\treptv exit }\n");
417     printf("\t\t\t\t\t{ decode dup 0 lt {pop} {exit} ifelse }\n");
418     printf("\t\t\t\tifelse } loop }\n");
419     printf("\t\t\t{ /nrept nrept 1 sub def reptv }\n");
420     printf("\t\tifelse put\n");
421     printf("\t\t} for\n");
422     printf("\t} stopped {pop pop 0 string} {scanline} ifelse\n");
423 greg 2.8 printf("} bind def\n");
424 greg 2.1 }
425    
426    
427     ra2ps() /* convert Radiance scanlines to 6-bit */
428     {
429 greg 2.9 register COLR *scanin;
430 greg 2.1 int y;
431     /* allocate scanline */
432     scanin = (COLR *)malloc(xmax*sizeof(COLR));
433     if (scanin == NULL)
434     quiterr("out of memory in ra2ps");
435     /* convert image */
436     for (y = ymax-1; y >= 0; y--) {
437     if (freadcolrs(scanin, xmax, stdin) < 0)
438     quiterr("error reading Radiance picture");
439 gregl 2.17 if (putprim == Cputprim || devgam != 1.) {
440 greg 2.15 if (bradj) /* adjust exposure */
441     shiftcolrs(scanin, xmax, bradj);
442     colrs_gambs(scanin, xmax); /* gamma compression */
443     } else
444     normcolrs(scanin, xmax, bradj);
445 greg 2.11 if (docolor) {
446 greg 2.15 (*putprim)(scanin, RED);
447     (*putprim)(scanin, GRN);
448     (*putprim)(scanin, BLU);
449 greg 2.11 } else
450 greg 2.15 (*putprim)(scanin, GRY);
451 greg 2.1 if (ferror(stdout))
452     quiterr("error writing PostScript file");
453     }
454     putchar('\n');
455     /* free scanline */
456     free((char *)scanin);
457 greg 2.11 }
458    
459    
460 greg 2.15 int
461     Aputprim(scn, pri) /* put out hex ASCII primary from scanline */
462     COLR *scn;
463     int pri;
464     {
465     static char hexdigit[] = "0123456789ABCDEF";
466     static int col = 0;
467     register int x, c;
468    
469     for (x = 0; x < xmax; x++) {
470     if (pri == GRY)
471     c = normbright(scn[x]);
472     else
473     c = scn[x][pri];
474     if (c > 255) c = 255;
475     putchar(hexdigit[c>>4]);
476     putchar(hexdigit[c&0xf]);
477     if ((col += 2) >= 72) {
478     putchar('\n');
479     col = 0;
480     }
481     }
482     }
483    
484    
485     int
486     Bputprim(scn, pri) /* put out binary primary from scanline */
487     COLR *scn;
488     int pri;
489     {
490     register int x, c;
491    
492     for (x = 0; x < xmax; x++) {
493     if (pri == GRY)
494     c = normbright(scn[x]);
495     else
496     c = scn[x][pri];
497     if (c > 255) c = 255;
498     putchar(c);
499     }
500     }
501    
502    
503     int
504     Cputprim(scn, pri) /* put out compressed primary from scanline */
505 greg 2.11 COLR *scn;
506     int pri;
507     {
508     register int c;
509     register int x;
510     int lastc, cnt;
511    
512     lastc = -1; cnt = 0;
513     for (x = 0; x < xmax; x++) {
514     if (pri == GRY)
515     c = normbright(scn[x]) + 2;
516     else
517     c = scn[x][pri] + 2;
518     if (c > 255) c = 255;
519     c = code[c>>2];
520     if (c == lastc && cnt < MAXRUN)
521     cnt++;
522     else {
523     putrle(cnt, lastc);
524     lastc = c;
525     cnt = 1;
526     }
527     }
528     putrle(cnt, lastc);
529 greg 2.9 }
530    
531    
532     putrle(cnt, cod) /* put out cnt of cod */
533     register int cnt, cod;
534     {
535     static int col = 0;
536    
537     if (cnt >= MINRUN) {
538     col += 3;
539     putchar(RUNCHR);
540     putchar(RSTRT-MINRUN+cnt);
541     putchar(cod);
542     } else {
543     col += cnt;
544     while (cnt-- > 0)
545     putchar(cod);
546     }
547     if (col >= 72) {
548     putchar('\n');
549     col = 0;
550     }
551 greg 2.1 }