ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/x11image.c
Revision: 1.1
Committed: Thu Mar 1 13:18:22 1990 UTC (34 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

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