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

# 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 greg 1.2 #define redraw(x,y,w,h) patch_raster(wind,(x)-xoff,(y)-yoff,x,y,w,h,ourras)
47    
48 greg 1.1 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 greg 1.2 int maxcolors = 0; /* maximum colors */
57 greg 1.1 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 greg 1.2 if (isexpos(s))
181     exposure *= exposval(s);
182 greg 1.1 else
183     for (an = altname; *an != NULL; an++)
184     if (!strncmp(*an, s, strlen(*an))) {
185 greg 1.2 if (sscanview(&ourview, s+strlen(*an)) > 0)
186 greg 1.1 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 greg 1.2 i = DisplayPlanes(thedisplay,ourscreen);
212     maxcolors = i > 8 ? 256 : 1<<i;
213 greg 1.1 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 greg 1.2 XSelectInput(thedisplay, wind, ButtonPressMask|ButtonReleaseMask
240     |ButtonMotionMask|StructureNotifyMask
241     |KeyPressMask|ExposureMask);
242 greg 1.1 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 greg 1.2 cvx.flags = DoRed|DoGreen|DoBlue;
418     XStoreColor(thedisplay, ourras->cmap, &cvx);
419 greg 1.1 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 greg 1.2 XBell(thedisplay, 0);
467 greg 1.1 return(-1);
468     }
469     }
470    
471    
472 greg 1.2 moveimage(ebut) /* shift the image */
473     XButtonPressedEvent *ebut;
474 greg 1.1 {
475 greg 1.2 union {
476     XEvent u;
477     XButtonReleasedEvent b;
478     } e;
479 greg 1.1
480 greg 1.2 XMaskEvent(thedisplay, ButtonReleaseMask, &e.u);
481     xoff += e.b.x - ebut->x;
482     yoff += e.b.y - ebut->y;
483 greg 1.1 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 greg 1.2 XEvent u;
493 greg 1.1 XButtonReleasedEvent b;
494     XPointerMovedEvent m;
495     } e;
496    
497 greg 1.2 XMaskEvent(thedisplay, ButtonReleaseMask|ButtonMotionMask, &e.u);
498     while (e.u.type == MotionNotify) {
499 greg 1.1 revbox(ebut->x, ebut->y, box.xmin = e.m.x, box.ymin = e.m.y);
500 greg 1.2 XMaskEvent(thedisplay,ButtonReleaseMask|ButtonMotionMask,&e.u);
501 greg 1.1 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     }