ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/x11image.c
Revision: 1.4
Committed: Fri Mar 2 14:58:57 1990 UTC (34 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.3: +11 -6 lines
Log Message:
changed order of call to XCreateWindow to support different visuals

File Contents

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