ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ra_ps.c
Revision: 2.19
Committed: Tue Sep 23 16:52:23 1997 UTC (26 years, 7 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 2.18: +10 -6 lines
Log Message:
fixed gamma correction and added new pages sizes

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