ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ps.c
Revision: 2.20
Committed: Fri Sep 26 14:20:38 1997 UTC (26 years, 7 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 2.19: +28 -13 lines
Log Message:
added -d option to match printer density to pixels

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