ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ps.c
Revision: 2.21
Committed: Fri Aug 28 10:03:46 1998 UTC (25 years, 8 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 2.20: +12 -8 lines
Log Message:
made different gamma defaults for color and greyscale

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