ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ximage.c
Revision: 1.3
Committed: Tue Apr 11 17:09:13 1989 UTC (35 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.2: +1 -1 lines
Log Message:
clear window before color change

File Contents

# Content
1 /* Copyright (c) 1987 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * ximage.c - driver for X-windows
9 *
10 * 4/30/87
11 * 3/3/88 Added calls to xraster & Paul Heckbert's ciq routines
12 */
13
14 #include "standard.h"
15
16 #include <X/Xlib.h>
17 #include <X/cursors/bcross.cursor>
18 #include <X/cursors/bcross_mask.cursor>
19
20 #include <sys/types.h>
21
22 #include <ctype.h>
23
24 #include "color.h"
25
26 #include "xraster.h"
27
28 #include "view.h"
29
30 #include "pic.h"
31
32 #define controlshift(e) (((XButtonEvent *)(e))->detail & (ShiftMask|ControlMask))
33
34 #define FONTNAME "9x15" /* text font we'll use */
35
36 #define CTRL(c) ('c'-'@')
37
38 #define BORWIDTH 5 /* border width */
39 #define BARHEIGHT 25 /* menu bar size */
40
41 double gamcor = 2.0; /* gamma correction */
42
43 XRASTER *ourras = NULL; /* our stored raster image */
44
45 int dither = 1; /* dither colors? */
46 int fast = 0; /* keep picture in Pixmap? */
47
48 Window wind = 0; /* our output window */
49 Font fontid; /* our font */
50
51 int maxcolors = 0; /* maximum colors */
52 int greyscale = 0; /* in grey */
53
54 int scale = 0; /* scalefactor; power of two */
55
56 int xoff = 0; /* x image offset */
57 int yoff = 0; /* y image offset */
58
59 VIEW ourview = STDVIEW(0); /* image view parameters */
60 int gotview = 0; /* got parameters from file */
61
62 COLR *scanline; /* scan line buffer */
63
64 int xmax, ymax; /* picture resolution */
65 int width, height; /* window size */
66 char *fname = NULL; /* input file name */
67 FILE *fin = stdin; /* input file */
68 long *scanpos = NULL; /* scan line positions in file */
69 int cury = 0; /* current scan location */
70
71 double exposure = 1.0; /* exposure compensation used */
72
73 struct {
74 int xmin, ymin, xsiz, ysiz;
75 } box = {0, 0, 0, 0}; /* current box */
76
77 char *geometry = NULL; /* geometry specification */
78
79 char *progname;
80
81 char errmsg[128];
82
83 extern long ftell();
84
85 extern char *malloc(), *calloc();
86
87 extern double atof(), pow(), log();
88
89
90 main(argc, argv)
91 int argc;
92 char *argv[];
93 {
94 int headline();
95 int i;
96
97 progname = argv[0];
98
99 for (i = 1; i < argc; i++)
100 if (argv[i][0] == '-')
101 switch (argv[i][1]) {
102 case 'c':
103 maxcolors = atoi(argv[++i]);
104 break;
105 case 'b':
106 greyscale = !greyscale;
107 break;
108 case 'm':
109 maxcolors = 2;
110 break;
111 case 'd':
112 dither = !dither;
113 break;
114 case 'f':
115 fast = !fast;
116 break;
117 case 'e':
118 if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
119 goto userr;
120 scale = atoi(argv[++i]);
121 break;
122 case 'g':
123 gamcor = atof(argv[++i]);
124 break;
125 default:
126 goto userr;
127 }
128 else if (argv[i][0] == '=')
129 geometry = argv[i];
130 else
131 break;
132
133 if (argc-i == 1) {
134 fname = argv[i];
135 fin = fopen(fname, "r");
136 if (fin == NULL) {
137 sprintf(errmsg, "can't open file \"%s\"", fname);
138 quiterr(errmsg);
139 }
140 } else
141 goto userr;
142
143 /* get header */
144 getheader(fin, headline);
145 /* get picture dimensions */
146 if (fscanf(fin, "-Y %d +X %d\n", &ymax, &xmax) != 2)
147 quiterr("bad picture size");
148 /* set view parameters */
149 if (gotview) {
150 ourview.hresolu = xmax;
151 ourview.vresolu = ymax;
152 if (setview(&ourview) != NULL)
153 gotview = 0;
154 }
155 if ((scanline = (COLR *)malloc(xmax*sizeof(COLR))) == NULL)
156 quiterr("out of memory");
157
158 init(); /* get file and open window */
159
160 for ( ; ; )
161 getevent(); /* main loop */
162 userr:
163 fprintf(stderr,
164 "Usage: %s [=geometry][-b][-m][-d][-f][-c ncolors][-e +/-stops] file\n",
165 progname);
166 quit(1);
167 }
168
169
170 headline(s) /* get relevant info from header */
171 char *s;
172 {
173 static char *altname[] = {"rview","rpict","VIEW=",NULL};
174 register char **an;
175
176 if (!strncmp(s, "EXPOSURE=", 9))
177 exposure *= atof(s+9);
178 else
179 for (an = altname; *an != NULL; an++)
180 if (!strncmp(*an, s, strlen(*an))) {
181 if (sscanview(&ourview, s+strlen(*an)) == 0)
182 gotview++;
183 return;
184 }
185 }
186
187
188 char *
189 sskip(s) /* skip a word */
190 register char *s;
191 {
192 while (isspace(*s)) s++;
193 while (*s && !isspace(*s)) s++;
194 return(s);
195 }
196
197
198 init() /* get data and open window */
199 {
200 register int i;
201 OpaqueFrame mainframe;
202 char defgeom[32];
203
204 if (fname != NULL) {
205 scanpos = (long *)malloc(ymax*sizeof(long));
206 if (scanpos == NULL)
207 goto memerr;
208 for (i = 0; i < ymax; i++)
209 scanpos[i] = -1;
210 }
211 if (XOpenDisplay(NULL) == NULL)
212 quiterr("can't open display; DISPLAY variable set?");
213 #ifdef notdef
214 if (DisplayWidth() - 2*BORWIDTH < xmax ||
215 DisplayHeight() - 2*BORWIDTH - BARHEIGHT < ymax)
216 quiterr("resolution mismatch");
217 #endif
218 if (maxcolors == 0) { /* get number of available colors */
219 maxcolors = 1<<DisplayPlanes();
220 if (maxcolors > 4) maxcolors -= 2;
221 }
222 /* store image */
223 getras();
224
225 mainframe.bdrwidth = BORWIDTH;
226 mainframe.border = WhitePixmap;
227 mainframe.background = BlackPixmap;
228 sprintf(defgeom, "=%dx%d+0+22", xmax, ymax);
229 wind = XCreate("Radiance Image", progname, geometry, defgeom,
230 &mainframe, 16, 16);
231 if (wind == 0)
232 quiterr("can't create window");
233 width = mainframe.width;
234 height = mainframe.height;
235 fontid = XGetFont(FONTNAME);
236 if (fontid == 0)
237 quiterr("can't get font");
238 XStoreName(wind, fname == NULL ? progname : fname);
239 XDefineCursor(wind, XCreateCursor(bcross_width, bcross_height,
240 bcross_bits, bcross_mask_bits,
241 bcross_x_hot, bcross_y_hot,
242 BlackPixel, WhitePixel, GXcopy));
243 XSelectInput(wind, ButtonPressed|ButtonReleased|UnmapWindow
244 |RightDownMotion|MiddleDownMotion|LeftDownMotion
245 |KeyPressed|ExposeWindow|ExposeRegion);
246 XMapWindow(wind);
247 return;
248 memerr:
249 quiterr("out of memory");
250 }
251
252
253 quiterr(err) /* print message and exit */
254 char *err;
255 {
256 if (err != NULL)
257 fprintf(stderr, "%s: %s\n", progname, err);
258
259 exit(err == NULL ? 0 : 1);
260 }
261
262
263 eputs(s)
264 char *s;
265 {
266 fputs(s, stderr);
267 }
268
269
270 quit(code)
271 int code;
272 {
273 exit(code);
274 }
275
276
277 getras() /* get raster file */
278 {
279 colormap ourmap;
280
281 ourras = (XRASTER *)calloc(1, sizeof(XRASTER));
282 if (ourras == NULL)
283 goto memerr;
284 ourras->width = xmax;
285 ourras->height = ymax;
286 if (maxcolors <= 2) { /* monochrome */
287 ourras->data.m = (unsigned short *)malloc(BitmapSize(xmax,ymax));
288 if (ourras->data.m == NULL)
289 goto memerr;
290 getmono();
291 } else {
292 ourras->data.bz = (unsigned char *)malloc(BZPixmapSize(xmax,ymax));
293 if (ourras->data.bz == NULL)
294 goto memerr;
295 if (greyscale)
296 biq(dither,maxcolors,1,ourmap);
297 else
298 ciq(dither,maxcolors,1,ourmap);
299 if (init_rcolors(ourras, ourmap) == 0)
300 goto memerr;
301 }
302 return;
303 memerr:
304 quit("out of memory");
305 }
306
307
308 getevent() /* process the next event */
309 {
310 WindowInfo info;
311 XEvent e;
312
313 XNextEvent(&e);
314 switch (e.type) {
315 case KeyPressed:
316 docom(&e);
317 break;
318 case ExposeWindow:
319 XQueryWindow(wind, &info); /* in case resized */
320 width = info.width;
321 height = info.height;
322 /* fall through */
323 case ExposeRegion:
324 fixwindow(&e);
325 break;
326 case UnmapWindow:
327 unmap_rcolors(ourras);
328 break;
329 case ButtonPressed:
330 if (controlshift(&e))
331 moveimage(&e);
332 else
333 getbox(&e);
334 break;
335 }
336 }
337
338
339 fixwindow(eexp) /* fix new or stepped-on window */
340 XExposeEvent *eexp;
341 {
342 redraw(eexp->x, eexp->y, eexp->width, eexp->height);
343 }
344
345
346 redraw(x, y, w, h) /* redraw section of window */
347 int x, y;
348 int w, h;
349 {
350 if (map_rcolors(ourras) == NULL) {
351 fprintf(stderr, "%s: cannot allocate colors\n", progname);
352 return(-1);
353 }
354 if (fast)
355 make_rpixmap(ourras);
356 return(patch_raster(wind,x-xoff,y-yoff,x,y,w,h,ourras) ? 0 : -1);
357 }
358
359
360 docom(ekey) /* execute command */
361 XKeyEvent *ekey;
362 {
363 char buf[80];
364 COLOR cval;
365 char *cp;
366 int n;
367 double comp;
368 FVECT rorg, rdir;
369
370 cp = XLookupMapping(ekey, &n);
371 if (n == 0)
372 return(0);
373 switch (*cp) { /* interpret command */
374 case 'q':
375 case CTRL(D): /* quiterr */
376 quit(0);
377 case '\n':
378 case '\r':
379 case 'l':
380 case 'c': /* value */
381 if (avgbox(cval) == -1)
382 return(-1);
383 switch (*cp) {
384 case '\n':
385 case '\r': /* radiance */
386 sprintf(buf, "%-3g", intens(cval)/exposure);
387 break;
388 case 'l': /* luminance */
389 sprintf(buf, "%-3gL", bright(cval)*683.0/exposure);
390 break;
391 case 'c': /* color */
392 comp = pow(2.0, (double)scale);
393 sprintf(buf, "(%.2f,%.2f,%.2f)",
394 colval(cval,RED)*comp,
395 colval(cval,GRN)*comp,
396 colval(cval,BLU)*comp);
397 break;
398 }
399 XText(wind, box.xmin, box.ymin, buf, strlen(buf),
400 fontid, BlackPixel, WhitePixel);
401 return(0);
402 case 'p': /* position */
403 sprintf(buf, "(%d,%d)", ekey->x-xoff, ymax-1-ekey->y+yoff);
404 XText(wind, ekey->x, ekey->y, buf, strlen(buf),
405 fontid, BlackPixel, WhitePixel);
406 return(0);
407 case 't': /* trace */
408 if (!gotview) {
409 XFeep(0);
410 return(-1);
411 }
412 rayview(rorg, rdir, &ourview,
413 ekey->x-xoff + .5, ymax-1-ekey->y+yoff + .5);
414 printf("%e %e %e ", rorg[0], rorg[1], rorg[2]);
415 printf("%e %e %e\n", rdir[0], rdir[1], rdir[2]);
416 fflush(stdout);
417 return(0);
418 case '=': /* adjust exposure */
419 if (avgbox(cval) == -1)
420 return(-1);
421 n = log(.5/bright(cval))/.69315 - scale; /* truncate */
422 if (n == 0) {
423 XFeep(0);
424 return(0);
425 }
426 scale_rcolors(ourras, pow(2.0, (double)n));
427 scale += n;
428 sprintf(buf, "%+d", scale);
429 XText(wind, box.xmin, box.ymin, buf, strlen(buf),
430 fontid, BlackPixel, WhitePixel);
431 XFlush();
432 free_raster(ourras);
433 getras();
434 /* fall through */
435 case CTRL(R): /* redraw */
436 XClear(wind);
437 return(redraw(0, 0, width, height));
438 case ' ': /* clear */
439 return(redraw(box.xmin, box.ymin, box.xsiz, box.ysiz));
440 default:
441 XFeep(0);
442 return(-1);
443 }
444 }
445
446
447 moveimage(ep) /* shift the image */
448 XButtonEvent *ep;
449 {
450 XButtonEvent eb;
451
452 XMaskEvent(ButtonReleased, &eb);
453 xoff += eb.x - ep->x;
454 yoff += eb.y - ep->y;
455 XClear(wind);
456 return(redraw(0, 0, width, height));
457 }
458
459
460 getbox(ebut) /* get new box */
461 XButtonEvent *ebut;
462 {
463 union {
464 XEvent e;
465 XButtonEvent b;
466 XMouseMovedEvent m;
467 } e;
468
469 XMaskEvent(ButtonReleased|MouseMoved, &e.e);
470 while (e.e.type == MouseMoved) {
471 revbox(ebut->x, ebut->y, box.xmin = e.m.x, box.ymin = e.m.y);
472 XMaskEvent(ButtonReleased|MouseMoved, &e.e);
473 revbox(ebut->x, ebut->y, box.xmin, box.ymin);
474 }
475 box.xmin = e.b.x<0 ? 0 : (e.b.x>=width ? width-1 : e.b.x);
476 box.ymin = e.b.y<0 ? 0 : (e.b.y>=height ? height-1 : e.b.y);
477 if (box.xmin > ebut->x) {
478 box.xsiz = box.xmin - ebut->x + 1;
479 box.xmin = ebut->x;
480 } else {
481 box.xsiz = ebut->x - box.xmin + 1;
482 }
483 if (box.ymin > ebut->y) {
484 box.ysiz = box.ymin - ebut->y + 1;
485 box.ymin = ebut->y;
486 } else {
487 box.ysiz = ebut->y - box.ymin + 1;
488 }
489 }
490
491
492 revbox(x0, y0, x1, y1) /* draw box with reversed lines */
493 int x0, y0, x1, y1;
494 {
495 XLine(wind, x0, y0, x1, y0, 1, 1, 0, GXinvert, AllPlanes);
496 XLine(wind, x0, y1, x1, y1, 1, 1, 0, GXinvert, AllPlanes);
497 XLine(wind, x0, y0, x0, y1, 1, 1, 0, GXinvert, AllPlanes);
498 XLine(wind, x1, y0, x1, y1, 1, 1, 0, GXinvert, AllPlanes);
499 }
500
501
502 avgbox(clr) /* average color over current box */
503 COLOR clr;
504 {
505 int left, right, top, bottom;
506 int y;
507 double d;
508 COLOR ctmp;
509 register int x;
510
511 setcolor(clr, 0.0, 0.0, 0.0);
512 left = box.xmin - xoff;
513 right = left + box.xsiz;
514 if (left < 0)
515 left = 0;
516 if (right > xmax)
517 right = xmax;
518 if (left >= right)
519 return(-1);
520 top = box.ymin - yoff;
521 bottom = top + box.ysiz;
522 if (top < 0)
523 top = 0;
524 if (bottom > ymax)
525 bottom = ymax;
526 if (top >= bottom)
527 return(-1);
528 for (y = top; y < bottom; y++) {
529 if (getscan(y) == -1)
530 return(-1);
531 for (x = left; x < right; x++) {
532 colr_color(ctmp, scanline[x]);
533 addcolor(clr, ctmp);
534 }
535 }
536 d = 1.0/((right-left)*(bottom-top));
537 scalecolor(clr, d);
538 return(0);
539 }
540
541
542 getmono() /* get monochrome data */
543 {
544 register unsigned short *dp;
545 register int x, err;
546 int y;
547 rgbpixel *inline;
548 short *cerr;
549
550 if ((inline = (rgbpixel *)malloc(xmax*sizeof(rgbpixel))) == NULL
551 || (cerr = (short *)calloc(xmax,sizeof(short))) == NULL)
552 quit("out of memory in getmono");
553 dp = ourras->data.m - 1;
554 for (y = 0; y < ymax; y++) {
555 picreadline3(y, inline);
556 err = 0;
557 for (x = 0; x < xmax; x++) {
558 if (!(x&0xf))
559 *++dp = 0;
560 err += rgb_bright(&inline[x]) + cerr[x];
561 if (err > 127)
562 err -= 255;
563 else
564 *dp |= 1<<(x&0xf);
565 cerr[x] = err >>= 1;
566 }
567 }
568 free((char *)inline);
569 free((char *)cerr);
570 }
571
572
573 init_rcolors(xr, cmap) /* (re)assign color values */
574 register XRASTER *xr;
575 colormap cmap;
576 {
577 register int i;
578 register unsigned char *p;
579
580 xr->pmap = (int *)malloc(256*sizeof(int));
581 if (xr->pmap == NULL)
582 return(0);
583 xr->cdefs = (Color *)malloc(256*sizeof(Color));
584 if (xr->cdefs == NULL)
585 return(0);
586 for (i = 0; i < 256; i++)
587 xr->pmap[i] = -1;
588 xr->ncolors = 0;
589 for (p = xr->data.bz, i = BZPixmapSize(xr->width,xr->height); i--; p++)
590 if (xr->pmap[*p] == -1) {
591 xr->cdefs[xr->ncolors].red = cmap[0][*p] << 8;
592 xr->cdefs[xr->ncolors].green = cmap[1][*p] << 8;
593 xr->cdefs[xr->ncolors].blue = cmap[2][*p] << 8;
594 xr->cdefs[xr->ncolors].pixel = *p;
595 xr->pmap[*p] = xr->ncolors++;
596 }
597 xr->cdefs = (Color *)realloc((char *)xr->cdefs, xr->ncolors*sizeof(Color));
598 if (xr->cdefs == NULL)
599 return(0);
600 return(1);
601 }
602
603
604 scale_rcolors(xr, sf) /* scale color map */
605 register XRASTER *xr;
606 double sf;
607 {
608 register int i;
609 int maxv;
610
611 sf = pow(sf, 1.0/gamcor);
612 maxv = (1<<16) / sf;
613
614 for (i = xr->ncolors; i--; ) {
615 xr->cdefs[i].red = xr->cdefs[i].red >= maxv ?
616 (1<<16)-1 :
617 xr->cdefs[i].red * sf;
618 xr->cdefs[i].green = xr->cdefs[i].green >= maxv ?
619 (1<<16)-1 :
620 xr->cdefs[i].green * sf;
621 xr->cdefs[i].blue = xr->cdefs[i].blue >= maxv ?
622 (1<<16)-1 :
623 xr->cdefs[i].blue * sf;
624 }
625 if (xr->pixels != NULL)
626 XStoreColors(xr->ncolors, xr->cdefs);
627 }
628
629
630 getscan(y)
631 int y;
632 {
633 if (y != cury) {
634 if (scanpos == NULL || scanpos[y] == -1)
635 return(-1);
636 if (fseek(fin, scanpos[y], 0) == -1)
637 quit("fseek error");
638 cury = y;
639 } else if (scanpos != NULL)
640 scanpos[y] = ftell(fin);
641
642 if (freadcolrs(scanline, xmax, fin) < 0)
643 quiterr("read error");
644
645 cury++;
646 return(0);
647 }
648
649
650 picreadline3(y, l3) /* read in 3-byte scanline */
651 int y;
652 register rgbpixel *l3;
653 {
654 register BYTE *l4;
655 register int shift, c;
656 int i;
657
658 if (getscan(y) < 0)
659 quiterr("cannot seek for picreadline");
660 /* convert scanline */
661 for (l4=scanline[0], i=xmax; i--; l4+=4, l3++) {
662 shift = l4[EXP] - COLXS + scale;
663 if (shift >= 8) {
664 l3->r = l3->g = l3->b = 255;
665 } else if (shift <= -8) {
666 l3->r = l3->g = l3->b = 0;
667 } else if (shift > 0) {
668 c = l4[RED] << shift;
669 l3->r = c > 255 ? 255 : c;
670 c = l4[GRN] << shift;
671 l3->g = c > 255 ? 255 : c;
672 c = l4[BLU] << shift;
673 l3->b = c > 255 ? 255 : c;
674 } else if (shift < 0) {
675 l3->r = l4[RED] >> -shift;
676 l3->g = l4[GRN] >> -shift;
677 l3->b = l4[BLU] >> -shift;
678 } else {
679 l3->r = l4[RED];
680 l3->g = l4[GRN];
681 l3->b = l4[BLU];
682 }
683 }
684 }
685
686
687 picwriteline(y, l) /* add 8-bit scanline to image */
688 int y;
689 pixel *l;
690 {
691 bcopy(l, ourras->data.bz+BZPixmapSize(xmax,y), BZPixmapSize(xmax,1));
692 }
693
694
695 picreadcm(map) /* do gamcor correction */
696 colormap map;
697 {
698 extern double pow();
699 register int i, val;
700
701 for (i = 0; i < 256; i++) {
702 val = pow(i/256.0, 1.0/gamcor) * 256.0;
703 map[0][i] = map[1][i] = map[2][i] = val;
704 }
705 }
706
707
708 picwritecm(map) /* handled elsewhere */
709 colormap map;
710 {
711 #ifdef DEBUG
712 register int i;
713
714 for (i = 0; i < 256; i++)
715 printf("%d %d %d\n", map[0][i],map[1][i],map[2][i]);
716 #endif
717 }