ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ps.c
Revision: 2.24
Committed: Sat Feb 22 02:07:28 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.23: +3 -7 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

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