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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Radiance picture to PostScript file translator -- one way!
6 */
7
8 #include <stdio.h>
9 #include <math.h>
10 #include <ctype.h>
11 #ifdef MSDOS
12 #include <fcntl.h>
13 #endif
14 #include "color.h"
15
16 #define UPPER(c) ((c)&~0x20) /* ASCII trick */
17
18 #define CODE6GAM 1.47 /* gamma for 6-bit codes */
19 #define DEFGGAM 1.0 /* greyscale device gamma */
20 #define DEFCGAM 1.8 /* color device gamma */
21
22 #define GRY -1 /* artificial index for grey */
23
24 #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
32 #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 char code[] = /* 6-bit code lookup table */
38 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@+";
39
40 int wrongformat = 0; /* input in wrong format? */
41 double pixaspect = 1.0; /* pixel aspect ratio */
42
43 double devgam = 0.; /* device gamma response */
44 double hmarg = DEFMARG,
45 vmarg = DEFMARG; /* horizontal and vertical margins */
46 double width = DEFWIDTH,
47 height = DEFHEIGHT; /* default paper width and height */
48 double dpi = 0; /* print density (0 if unknown) */
49 int docolor = 1; /* produce color image? */
50 int bradj = 0; /* brightness adjustment */
51 int ncopies = 1; /* number of copies */
52
53 extern int Aputprim(), Bputprim(), Cputprim();
54
55 int (*putprim)() = Aputprim; /* function for writing scanline */
56
57 char *progname;
58
59 int xmax, ymax; /* input image dimensions */
60
61 extern double unit2inch();
62
63
64 int
65 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 return(0);
76 }
77
78
79 main(argc, argv)
80 int argc;
81 char *argv[];
82 {
83 int i;
84 double d;
85
86 progname = argv[0];
87
88 for (i = 1; i < argc; i++)
89 if (argv[i][0] == '-')
90 switch (argv[i][1]) {
91 case 'b': /* produce b&w PostScript */
92 docolor = 0;
93 break;
94 case 'c': /* produce color PostScript */
95 docolor = 1;
96 break;
97 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 case 'd': /* print density */
107 dpi = atof(argv[++i]);
108 break;
109 case 'g': /* device gamma adjustment */
110 devgam = atof(argv[++i]);
111 break;
112 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 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 case 'n': /* number of copies */
139 ncopies = atoi(argv[++i]);
140 break;
141 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 fprintf(stderr, "%s: can't open output \"%s\"\n",
156 progname, argv[i+1]);
157 exit(1);
158 }
159 #ifdef MSDOS
160 setmode(fileno(stdin), O_BINARY);
161 #endif
162 /* get our header */
163 getheader(stdin, headline, NULL);
164 if (wrongformat || fgetresolu(&xmax, &ymax, stdin) < 0)
165 quiterr("bad picture format");
166 /* gamma compression */
167 if (devgam <= 0.05)
168 devgam = docolor ? DEFCGAM : DEFGGAM;
169 if (putprim == Cputprim)
170 setcolrgam(CODE6GAM);
171 else if (devgam != 1.)
172 setcolrgam(devgam);
173 /* write header */
174 PSheader(argc, argv);
175 /* convert file */
176 ra2ps();
177 /* write trailer */
178 PStrailer();
179 exit(0);
180 userr:
181 fprintf(stderr,
182 "Usage: %s [-b|c][-A|B|C][-e +/-stops][-p paper][-m[h|v] margin][-d dpi][-g gamma] [input [output]]\n",
183 progname);
184 exit(1);
185 }
186
187
188 double
189 unit2inch(s) /* determine unit */
190 register char *s;
191 {
192 static struct unit {char n; float f;} u[] = {
193 '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 "envelope", 4.12, 9.5,
232 "executive", 7.25, 10.5,
233 "letter", 8.5, 11.,
234 "lettersmall", 7.68, 10.16,
235 "legal", 8.5, 14.,
236 "monarch", 3.87, 7.5,
237 "statement", 5.5, 8.5,
238 "tabloid", 11., 17.,
239 "A3", 11.69, 16.54,
240 "A4", 8.27, 11.69,
241 "A4small", 7.47, 10.85,
242 "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 "DL", 4.33, 8.66,
249 "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 fprintf(stderr, "Or use WWxHH size specification\n");
278 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 PSheader(ac, av) /* print PostScript header */
294 int ac;
295 char **av;
296 {
297 char *rstr;
298 int landscape, rotate, n;
299 double pwidth, pheight;
300 double iwidth, iheight;
301 /* EPS comments */
302 puts("%!PS-Adobe-2.0 EPSF-2.0");
303 printf("%%%%Title: "); printargs(ac, av, stdout);
304 printf("%%%%Creator: %s\n", progname);
305 printf("%%%%Pages: %d\n", ncopies);
306 if (landscape = xmax > pixaspect*ymax)
307 puts("%%Orientation: Landscape");
308 else
309 puts("%%Orientation: Portrait");
310 if (rotate = PWIDTH > PHEIGHT ^ landscape) {
311 pwidth = PHEIGHT;
312 pheight = PWIDTH;
313 } else {
314 pwidth = PWIDTH;
315 pheight = PHEIGHT;
316 }
317 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 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 puts("gsave save");
349 puts("17 dict begin");
350 /* define image reader */
351 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 } else
356 printf("/gryline %d string def\n", xmax);
357 /* use compressed encoding? */
358 if (putprim == Cputprim)
359 PSprocdef("read6bitRLE");
360 /* set up transformation matrix */
361 printf("%f %f translate\n", HMARGIN, VMARGIN);
362 if (rotate) {
363 printf("%f 0 translate\n", PWIDTH);
364 puts("90 rotate");
365 }
366 printf("%f %f translate\n", (pwidth-iwidth)*.5, (pheight-iheight)*.5);
367 printf("%f %f scale\n", iwidth, iheight);
368 puts("%%EndProlog");
369 /* start image procedure */
370 printf("%d %d 8 [%d 0 0 %d 0 %d]\n", xmax, ymax, xmax, -ymax, ymax);
371 if (putprim == Cputprim) {
372 if (docolor) {
373 puts("{redline read6bitRLE}");
374 puts("{grnline read6bitRLE}");
375 puts("{bluline read6bitRLE}");
376 puts("true 3 colorimage");
377 } 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 }
390
391
392 PStrailer() /* print PostScript trailer */
393 {
394 puts("%%Trailer");
395 if (ncopies > 1)
396 printf("/#copies %d def\n", ncopies);
397 puts("showpage");
398 puts("end");
399 puts("restore grestore");
400 puts("%%EOF");
401 }
402
403
404 PSprocdef(nam) /* define PS procedure to read image */
405 char *nam;
406 {
407 short itab[128];
408 register int i;
409 /* assign code values */
410 for (i = 0; i < 128; i++) /* clear */
411 itab[i] = -1;
412 for (i = 1; i < 63; i++) /* assign greys */
413 itab[code[i]] = 256.0*pow((i+.5)/64.0, CODE6GAM/devgam);
414 itab[code[0]] = 0; /* black is black */
415 itab[code[63]] = 255; /* and white is white */
416 printf("/codetab [");
417 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 printf("/nrept 0 def\n");
424 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 printf("\t{ 0 1 %d { scanline exch\n", xmax-1);
429 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 printf("} bind def\n");
441 }
442
443
444 ra2ps() /* convert Radiance scanlines to 6-bit */
445 {
446 register COLR *scanin;
447 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 if (putprim == Cputprim || devgam != 1.) {
457 if (bradj) /* adjust exposure */
458 shiftcolrs(scanin, xmax, bradj);
459 colrs_gambs(scanin, xmax); /* gamma compression */
460 } else
461 normcolrs(scanin, xmax, bradj);
462 if (docolor) {
463 (*putprim)(scanin, RED);
464 (*putprim)(scanin, GRN);
465 (*putprim)(scanin, BLU);
466 } else
467 (*putprim)(scanin, GRY);
468 if (ferror(stdout))
469 quiterr("error writing PostScript file");
470 }
471 putchar('\n');
472 /* free scanline */
473 free((void *)scanin);
474 }
475
476
477 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 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 }
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 }