ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/aedimage.c
Revision: 2.6
Committed: Fri Jan 2 12:47:01 2004 UTC (20 years, 3 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6P1, rad3R6
Changes since 2.5: +10 -9 lines
Log Message:
Fixed typing/prototype of getheader() and its callback.

File Contents

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