ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/x11image.c
Revision: 1.2
Committed: Thu Mar 1 18:13:31 1990 UTC (34 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.1: +27 -31 lines
Log Message:
Various bug fixes

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