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

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