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

# User Rev Content
1 greg 1.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     }