ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/x11image.c
Revision: 1.12
Committed: Fri Dec 21 17:20:11 1990 UTC (33 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.11: +2 -1 lines
Log Message:
minor compiler complaints

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