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

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