ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ps.c
Revision: 2.25
Committed: Thu Jun 5 19:29:34 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.24: +4 -7 lines
Log Message:
Macros for setting binary file mode. Replacing MSDOS by _WIN32.

File Contents

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