ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/aedimage.c
Revision: 2.5
Committed: Sat Feb 22 02:07:27 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.4: +3 -4 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 * aedimage.c - RADIANCE driver for AED 512 terminal.
6 *
7 * 3/20/86
8 * 3/3/88 Added calls to Paul Heckbert's ciq routines
9 */
10
11 #include <stdio.h>
12
13 #include <math.h>
14
15 #include <signal.h>
16
17 #include <sys/ioctl.h>
18
19 #include "pic.h"
20
21 #include "color.h"
22
23
24 /* AED command characters */
25
26 #define AEDFMT "1888N" /* Format string to send to AED */
27 #define CSTAT 0100 /* Console status: lower case */
28 #define SCS 96 /* Set Console Status */
29 #define SCT 75 /* Set color lookup table */
30 #define SEC 67 /* Set color for vector drawing */
31 #define MOV 81 /* Set CAP (current access pointer) to x, y */
32 #define MVR 105 /* Set CAP relative */
33 #define DVA 65 /* Draw vector to new CAP x, y */
34 #define DVR 108 /* Draw vector relative */
35 #define WHS 88 /* Write horizontal scan */
36 #define WHR 92 /* Write horizontal runs */
37 #define OPT 40 /* Miscellaneous terminal control */
38 #define SEN 71 /* Set encoding types */
39 #define RST 48 /* Reset terminal */
40 #define FFD 12 /* Clear screen */
41 #define SCS 96 /* Set status */
42 #define DAI 114 /* Define area of interest */
43 #define EJC 85 /* Enable Joystick cursor positioning */
44 #define DJC 100 /* Disable Joystick cursor positioning */
45 #define SCC 99 /* Set Cursor Colors */
46 #define SCP 93 /* Set Cursor Parameters */
47 #define RCP 106 /* Read Cursor Position */
48 #define MAXRLEN 255 /* Maximum runlength for a span */
49 #define NUL 0 /* Null terminates run sequences */
50 #define ESC 27 /* Escape starts a command sequence */
51 #define END 1 /* Ctrl-A used to terminate command mode */
52
53 #define BLK 0 /* color table entry for black */
54 #define WHT 7 /* color table entry for white */
55
56 #define command(c) (putc(ESC, stdout), putc(c, stdout))
57 #define byte(b) putc(b, stdout)
58 #define flush() fflush(stdout)
59
60 #define GAMMA 2.5 /* gamma value used in correction */
61
62 #define MINCOLOR 8 /* start of device color table */
63
64 #define NCOLORS 248 /* available color table size */
65
66 #define NROWS 512 /* maximum # rows for output */
67 #define NCOLS 512 /* maximum # columns for output */
68
69 int dither = 0; /* dither colors? */
70
71 int greyscale = 0; /* grey only? */
72
73 int initialized = 0;
74 struct sgttyb oldflags;
75 int oldlmode;
76
77 int intrcnt = 0; /* interrupt well */
78
79 #define disintr() (intrcnt--) /* disable interrupts */
80 #define enaintr() onintr() /* enable interrupts */
81
82 char *progname;
83
84 char errmsg[128];
85
86 COLR scanline[NCOLS];
87
88 colormap colrtbl;
89
90 int cury;
91
92 int xmax, ymax;
93
94 FILE *fin;
95
96 extern long ftell();
97 long scanpos[NROWS];
98
99 double exposure = 1.0;
100 int wrong_fmt = 0;
101
102
103 main(argc, argv)
104 int argc;
105 char *argv[];
106 {
107 int onintr(), checkhead();
108 char sbuf[256];
109 register int i;
110
111 progname = argv[0];
112
113 #ifdef SIGTSTP
114 signal(SIGTSTP, SIG_IGN);
115 #endif
116 if (signal(SIGINT, onintr) == SIG_IGN)
117 signal(SIGINT, SIG_IGN);
118
119 for (i = 1; i < argc; i++)
120 if (argv[i][0] == '-')
121 switch (argv[i][1]) {
122 case 'd':
123 dither = !dither;
124 break;
125 case 'b':
126 greyscale = !greyscale;
127 break;
128 default:
129 goto userr;
130 }
131 else
132 break;
133
134 if (i+1 != argc)
135 goto userr;
136
137 if ((fin = fopen(argv[i], "r")) == NULL) {
138 sprintf(errmsg, "can't open file \"%s\"", argv[i]);
139 quitmsg(errmsg);
140 }
141 /* get header */
142 getheader(fin, checkhead, NULL);
143 if (wrong_fmt)
144 quitmsg("input must be a Radiance picture");
145 /* get picture dimensions */
146 if (fgetresolu(&xmax, &ymax, fin) < 0)
147 quitmsg("bad picture size");
148 if (xmax > NCOLS || ymax > NROWS)
149 quitmsg("resolution mismatch");
150
151 init(); /* initialize terminal for output */
152
153 for (i = 0; i < NROWS; i++)
154 scanpos[i] = -1;
155
156 if (greyscale) /* map colors and display */
157 biq(dither,NCOLORS,1,colrtbl);
158 else
159 ciq(dither,NCOLORS,1,colrtbl);
160
161 loopcom();
162
163 quitmsg(NULL);
164 userr:
165 fprintf(stderr, "Usage: %s [-d][-b] input\n", progname);
166 quit(1);
167 }
168
169
170 int
171 checkhead(line) /* deal with line from header */
172 char *line;
173 {
174 char fmt[32];
175
176 if (isexpos(line))
177 exposure *= exposval(line);
178 else if (isformat(line)) {
179 formatval(fmt, line);
180 wrong_fmt = strcmp(fmt, COLRFMT);
181 }
182 return(0);
183 }
184
185
186 init() /* initialize terminal */
187 {
188 struct sgttyb flags;
189 int lmode;
190
191 if (isatty(1)) {
192 /* Set literal mode so AED gets bit 8 */
193 ioctl(1, TIOCLGET, &oldlmode);
194 lmode = oldlmode | LLITOUT | LNOFLSH;
195 ioctl(1, TIOCLSET, &lmode);
196 ioctl(1, TIOCLGET, &lmode); /* 4.2 bug */
197 /* Turn terminal echoing off */
198 ioctl(1, TIOCGETP, &oldflags);
199 ioctl(1, TIOCGETP, &flags);
200 flags.sg_flags &= ~ECHO;
201 ioctl(1, TIOCSETP, &flags);
202 initialized = 1;
203 } else
204 quitmsg("output must be to a terminal");
205
206 /* Reset AED and tell it the data format */
207 command(RST);
208 longwait(2);
209 command(OPT);
210 byte(6); byte(1); /* AED command set */
211 command(SEN); fputs(AEDFMT, stdout);
212 command(SCS); byte(CSTAT); /* console status */
213 command(FFD); /* clear screen */
214 flush();
215 }
216
217
218 onintr() /* die gracefully */
219 {
220 if (++intrcnt > 0)
221 quitmsg("interrupt");
222 }
223
224
225 quitmsg(err) /* uninitialize terminal and exit */
226 char *err;
227 {
228 if (initialized) { /* close AED */
229 command(DJC); /* disable cursor */
230 command(SEC);
231 byte(WHT); /* Set color to white */
232 aedsetcap(0, 0); /* Put cursor in a good place */
233 byte(END);
234 flush();
235 ioctl(1, TIOCSETP, &oldflags);
236 ioctl(1, TIOCLSET, &oldlmode);
237 putchar('\n');
238 }
239 if (err != NULL) {
240 fprintf(stderr, "%s: %s\n", progname, err);
241 exit(1);
242 }
243 exit(0);
244 }
245
246
247 void
248 eputs(s)
249 char *s;
250 {
251 fputs(s, stderr);
252 }
253
254
255 void
256 quit(status)
257 int status;
258 {
259 quitmsg(status ? "aborted" : NULL);
260 }
261
262
263 loopcom() /* print pixel values interactively */
264 {
265 int coffset[3]; /* color table offset */
266 struct sgttyb flags;
267 COLOR cval, ctmp;
268 int rept, x, y, j;
269 register int com, i;
270 /* Set raw mode on input */
271 ioctl(0, TIOCGETP, &flags);
272 flags.sg_flags |= RAW;
273 flags.sg_flags &= ~ECHO;
274 ioctl(0, TIOCSETP, &flags);
275
276 coffset[0] = coffset[1] = coffset[2] = 0;
277 /* set cursor type */
278 command(SCC);
279 byte(BLK); byte(WHT); byte(15);
280 command(SCP);
281 byte('+'); byte(0); byte(1);
282 /* loop on command */
283 for ( ; ; ) {
284 command(EJC); /* enable cursor */
285 flush();
286 rept = 0; /* get command */
287 while ((com = getc(stdin)) >= '0' && com <= '9')
288 rept = rept*10 + com - '0';
289 if (rept == 0) rept = 1;
290 command(DJC); /* disable cursor */
291 switch (com) {
292 case '\r':
293 case '\n':
294 case 'l':
295 case 'L':
296 case 'c':
297 case 'C':
298 case 'p':
299 case 'P':
300 case '=':
301 aedgetcap(&x, &y); /* get cursor position */
302 y = ymax-1-y;
303 if (y < 0 || scanpos[y] == -1) /* off picture? */
304 break;
305 /* get value */
306 setcolor(cval, 0.0, 0.0, 0.0);
307 for (j = rept-1; j >= 0; j--) {
308 if (y+j >= NROWS || scanpos[y+j] == -1)
309 continue;
310 getscan(y+j);
311 for (i = 0; i < rept; i++)
312 if (x+i < xmax) {
313 colr_color(ctmp, scanline[x+i]);
314 addcolor(cval, ctmp);
315 }
316 }
317 scalecolor(cval, 1.0/(rept*rept));
318 /* print value */
319 command(SEC);
320 byte(scanline[(x+20)%xmax][EXP] >= COLXS ? BLK : WHT);
321 byte(END);
322 switch (com) {
323 case '\r':
324 case '\n':
325 printf("%-3g", intens(cval)/exposure);
326 break;
327 case 'l':
328 case 'L':
329 printf("%-3gL", luminance(cval)/exposure);
330 break;
331 case 'c':
332 case 'C':
333 printf("(%.2f,%.2f,%.2f)",
334 colval(cval,RED),
335 colval(cval,GRN),
336 colval(cval,BLU));
337 break;
338 case 'p':
339 case 'P':
340 printf("(%d,%d)", x, y);
341 break;
342 case '=':
343 printf("(%d,%d,%d)", coffset[0],
344 coffset[1], coffset[2]);
345 break;
346 }
347 break;
348 case 'w':
349 rept = -rept;
350 case 'W':
351 coffset[0] += rept;
352 coffset[1] += rept;
353 coffset[2] += rept;
354 movecolor(coffset);
355 break;
356 case 'r':
357 rept = -rept;
358 case 'R':
359 coffset[0] += rept;
360 movecolor(coffset);
361 break;
362 case 'g':
363 rept = -rept;
364 case 'G':
365 coffset[1] += rept;
366 movecolor(coffset);
367 break;
368 case 'b':
369 rept = -rept;
370 case 'B':
371 coffset[2] += rept;
372 movecolor(coffset);
373 break;
374 case '!':
375 coffset[0] = coffset[1] = coffset[2] = 0;
376 movecolor(coffset);
377 break;
378 case 'C'-'@':
379 case 'q':
380 case 'Q':
381 return;
382 }
383 }
384 }
385
386
387 getscan(y)
388 int y;
389 {
390 if (y != cury) {
391 if (scanpos[y] == -1)
392 quitmsg("cannot seek in getscan");
393 if (fseek(fin, scanpos[y], 0) == -1)
394 quitmsg("fseek error");
395 cury = y;
396 } else
397 scanpos[y] = ftell(fin);
398
399 if (freadcolrs(scanline, xmax, fin) < 0)
400 quitmsg("read error");
401
402 cury++;
403 }
404
405
406 picreadline3(y, l3) /* read in 3-byte scanline */
407 int y;
408 register rgbpixel *l3;
409 {
410 register int i;
411 /* read scanline */
412 getscan(y);
413 /* convert scanline */
414 normcolrs(scanline, xmax, 0);
415 for (i = 0; i < xmax; i++) {
416 l3[i].r = scanline[i][RED];
417 l3[i].g = scanline[i][GRN];
418 l3[i].b = scanline[i][BLU];
419 }
420 }
421
422
423 picwriteline(y, l) /* output scan line of pixel values */
424 int y;
425 register pixel *l;
426 {
427 int curpix;
428 register int n, ncols;
429
430 disintr(); /* disable interrupts */
431 aedsetcap(0, ymax-1-y);
432 command(DAI);
433 aedcoord(xmax-1, ymax-1-y);
434 ncols = xmax;
435 if (dither) { /* pixel run lengths short */
436 command(WHS);
437 while (ncols-- > 0)
438 byte(MINCOLOR + *l++);
439 } else { /* pixel run lengths long */
440 command(WHR);
441 while (ncols-- > 0) {
442 curpix = *l++;
443 for (n = 1; n < MAXRLEN; n++) {
444 if (ncols <= 0 || *l != curpix)
445 break;
446 l++; ncols--;
447 }
448 byte(n);
449 byte(MINCOLOR + curpix);
450 }
451 byte(NUL);
452 }
453 flush();
454 enaintr(); /* enable interrupts */
455 }
456
457
458 /*
459 * aedsetcap - sets AED's current access pointer to (x, y). Used
460 * before writing a span to put it in the right place.
461 */
462
463 aedsetcap(x, y)
464 register int x, y;
465 {
466 command(MOV);
467 aedcoord(x, y);
468 }
469
470 /*
471 * aedcoord - puts out an (x, y) coordinate in AED 8 bit format.
472 */
473
474 aedcoord(x, y)
475 register int x, y;
476 {
477 putc(((x >> 4) & 0x30) | ((y >> 8) & 0x3), stdout);
478 putc(x & 0xff, stdout);
479 putc(y & 0xff, stdout);
480 }
481
482
483 aedgetcap(xp, yp) /* get cursor postion */
484 int *xp, *yp;
485 {
486 register int c;
487 /* get cursor postition */
488 command(RCP);
489 flush();
490 c = getc(stdin);
491 *xp = (c & 0x30) << 4;
492 *yp = (c & 0x3) << 8;
493 *xp |= getc(stdin);
494 *yp |= getc(stdin);
495 }
496
497
498 movecolor(offset) /* move our color table up or down */
499 int offset[3];
500 {
501 register int i, j, c;
502
503 disintr();
504 command(SCT);
505 byte(MINCOLOR);
506 byte(NCOLORS);
507 for (i = 0; i < NCOLORS; i++)
508 for (j = 0; j < 3; j++) {
509 c = colrtbl[j][i] + offset[j];
510 if (c < 0)
511 byte(0);
512 else if (c > 255)
513 byte(255);
514 else
515 byte(c);
516 }
517 shortwait(20);
518 enaintr();
519 }
520
521
522 picreadcm(map) /* do gamma correction */
523 colormap map;
524 {
525 register int i, val;
526
527 for (i = 0; i < 256; i++) {
528 val = pow((i+0.5)/256.0, 1.0/GAMMA) * 256.0;
529 map[0][i] = map[1][i] = map[2][i] = val;
530 }
531 }
532
533
534 picwritecm(map) /* write out color map */
535 colormap map;
536 {
537 register int i, j;
538
539 disintr();
540 command(SCT);
541 byte(MINCOLOR);
542 byte(NCOLORS);
543 for (i = 0; i < NCOLORS; i++)
544 for (j = 0; j < 3; j++)
545 byte(map[j][i]);
546 shortwait(20);
547 enaintr();
548 }
549
550
551 longwait(t) /* longer wait */
552 int t;
553 {
554 flush();
555 sleep(t);
556 }
557
558
559 shortwait(t) /* shorter wait */
560 int t;
561 {
562 register long l = t*1000;
563
564 flush();
565 while (l--)
566 ;
567 }