ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ximage.c
Revision: 1.1
Committed: Thu Feb 2 10:49:43 1989 UTC (35 years, 3 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) 1987 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * ximage.c - driver for X-windows
9     *
10     * 4/30/87
11     * 3/3/88 Added calls to xraster & Paul Heckbert's ciq routines
12     */
13    
14     #include "standard.h"
15    
16     #include <X/Xlib.h>
17     #include <X/cursors/bcross.cursor>
18     #include <X/cursors/bcross_mask.cursor>
19    
20     #include <sys/types.h>
21    
22     #include <ctype.h>
23    
24     #include "color.h"
25    
26     #include "xraster.h"
27    
28     #include "view.h"
29    
30     #include "pic.h"
31    
32     #define controlshift(e) (((XButtonEvent *)(e))->detail & (ShiftMask|ControlMask))
33    
34     #define FONTNAME "9x15" /* text font we'll use */
35    
36     #define CTRL(c) ('c'-'@')
37    
38     #define BORWIDTH 5 /* border width */
39     #define BARHEIGHT 25 /* menu bar size */
40    
41     double gamcor = 2.0; /* gamcor correction */
42    
43     XRASTER ourras; /* our stored raster image */
44    
45     int dither = 1; /* dither colors? */
46     int fast = 0; /* keep picture in Pixmap? */
47    
48     Window wind = 0; /* our output window */
49     Font fontid; /* our font */
50    
51     int maxcolors = 0; /* maximum colors */
52     int greyscale = 0; /* in grey */
53    
54     int xoff = 0; /* x image offset */
55     int yoff = 0; /* y image offset */
56    
57     VIEW ourview = STDVIEW(0); /* image view parameters */
58     int gotview = 0; /* got parameters from file */
59    
60     COLR *scanline; /* scan line buffer */
61    
62     int xmax, ymax; /* picture resolution */
63     int width, height; /* window size */
64     char *fname = NULL; /* input file name */
65     FILE *fin = stdin; /* input file */
66     long *scanpos = NULL; /* scan line positions in file */
67     int cury = 0; /* current scan location */
68    
69     double exposure = 1.0; /* exposure compensation used */
70    
71     struct {
72     int xmin, ymin, xsiz, ysiz;
73     } box = {0, 0, 0, 0}; /* current box */
74    
75     char *geometry = NULL; /* geometry specification */
76    
77     char *progname;
78    
79     char errmsg[128];
80    
81     extern long ftell();
82    
83     extern char *malloc(), *calloc();
84    
85     extern double atof();
86    
87    
88     main(argc, argv)
89     int argc;
90     char *argv[];
91     {
92     int headline();
93     int i;
94    
95     progname = argv[0];
96    
97     for (i = 1; i < argc; i++)
98     if (argv[i][0] == '-')
99     switch (argv[i][1]) {
100     case 'c':
101     maxcolors = atoi(argv[++i]);
102     break;
103     case 'b':
104     greyscale = !greyscale;
105     break;
106     case 'm':
107     maxcolors = 2;
108     break;
109     case 'd':
110     dither = !dither;
111     break;
112     case 'f':
113     fast = !fast;
114     break;
115     case 'g':
116     gamcor = atof(argv[++i]);
117     break;
118     default:
119     goto userr;
120     }
121     else if (argv[i][0] == '=')
122     geometry = argv[i];
123     else
124     break;
125    
126     if (argc-i == 1) {
127     fname = argv[i];
128     fin = fopen(fname, "r");
129     if (fin == NULL) {
130     sprintf(errmsg, "can't open file \"%s\"", fname);
131     quiterr(errmsg);
132     }
133     } else
134     goto userr;
135    
136     /* get header */
137     getheader(fin, headline);
138     /* get picture dimensions */
139     if (fscanf(fin, "-Y %d +X %d\n", &ymax, &xmax) != 2)
140     quiterr("bad picture size");
141     /* set view parameters */
142     if (gotview) {
143     ourview.hresolu = xmax;
144     ourview.vresolu = ymax;
145     if (setview(&ourview) != NULL)
146     gotview = 0;
147     }
148     if ((scanline = (COLR *)malloc(xmax*sizeof(COLR))) == NULL)
149     quiterr("out of memory");
150    
151     init(); /* get file and open window */
152    
153     for ( ; ; )
154     getevent(); /* main loop */
155     userr:
156     fprintf(stderr,
157     "Usage: %s [=geometry][-b][-m][-d][-f][-c ncolors] file\n",
158     progname);
159     quit(1);
160     }
161    
162    
163     headline(s) /* get relevant info from header */
164     char *s;
165     {
166     static char *altname[] = {"rview","rpict","VIEW=",NULL};
167     register char **an;
168    
169     if (!strncmp(s, "EXPOSURE=", 9))
170     exposure *= atof(s+9);
171     else
172     for (an = altname; *an != NULL; an++)
173     if (!strncmp(*an, s, strlen(*an))) {
174     if (sscanview(&ourview, s+strlen(*an)) == 0)
175     gotview++;
176     return;
177     }
178     }
179    
180    
181     char *
182     sskip(s) /* skip a word */
183     register char *s;
184     {
185     while (isspace(*s)) s++;
186     while (*s && !isspace(*s)) s++;
187     return(s);
188     }
189    
190    
191     init() /* get data and open window */
192     {
193     register int i;
194     colormap ourmap;
195     OpaqueFrame mainframe;
196     char defgeom[32];
197    
198     if (fname != NULL) {
199     scanpos = (long *)malloc(ymax*sizeof(long));
200     if (scanpos == NULL)
201     goto memerr;
202     for (i = 0; i < ymax; i++)
203     scanpos[i] = -1;
204     }
205     if (XOpenDisplay(NULL) == NULL)
206     quiterr("can't open display; DISPLAY variable set?");
207     #ifdef notdef
208     if (DisplayWidth() - 2*BORWIDTH < xmax ||
209     DisplayHeight() - 2*BORWIDTH - BARHEIGHT < ymax)
210     quiterr("resolution mismatch");
211     #endif
212     if (maxcolors == 0) { /* get number of available colors */
213     maxcolors = 1<<DisplayPlanes();
214     if (maxcolors > 4) maxcolors -= 2;
215     }
216     ourras.width = xmax;
217     ourras.height = ymax;
218     /* store image */
219     if (maxcolors <= 2) { /* monochrome */
220     ourras.data.m = (unsigned short *)malloc(BitmapSize(xmax,ymax));
221     if (ourras.data.m == NULL)
222     goto memerr;
223     getmono();
224     } else {
225     ourras.data.bz = (unsigned char *)malloc(BZPixmapSize(xmax,ymax));
226     if (ourras.data.bz == NULL)
227     goto memerr;
228     if (greyscale)
229     biq(dither,maxcolors,1,ourmap);
230     else
231     ciq(dither,maxcolors,1,ourmap);
232     if (init_rcolors(&ourras, ourmap) == 0)
233     goto memerr;
234     }
235     mainframe.bdrwidth = BORWIDTH;
236     mainframe.border = WhitePixmap;
237     mainframe.background = BlackPixmap;
238     sprintf(defgeom, "=%dx%d+0+22", xmax, ymax);
239     wind = XCreate("Radiance Image", progname, geometry, defgeom,
240     &mainframe, 16, 16);
241     if (wind == 0)
242     quiterr("can't create window");
243     width = mainframe.width;
244     height = mainframe.height;
245     fontid = XGetFont(FONTNAME);
246     if (fontid == 0)
247     quiterr("can't get font");
248     XStoreName(wind, fname == NULL ? progname : fname);
249     XDefineCursor(wind, XCreateCursor(bcross_width, bcross_height,
250     bcross_bits, bcross_mask_bits,
251     bcross_x_hot, bcross_y_hot,
252     BlackPixel, WhitePixel, GXcopy));
253     XSelectInput(wind, ButtonPressed|ButtonReleased|UnmapWindow
254     |RightDownMotion|MiddleDownMotion|LeftDownMotion
255     |KeyPressed|ExposeWindow|ExposeRegion);
256     XMapWindow(wind);
257     return;
258     memerr:
259     quiterr("out of memory");
260     }
261    
262    
263     quiterr(err) /* print message and exit */
264     char *err;
265     {
266     if (err != NULL)
267     fprintf(stderr, "%s: %s\n", progname, err);
268    
269     exit(err == NULL ? 0 : 1);
270     }
271    
272    
273     eputs(s)
274     char *s;
275     {
276     fputs(s, stderr);
277     }
278    
279    
280     quit(code)
281     int code;
282     {
283     exit(code);
284     }
285    
286    
287     getevent() /* process the next event */
288     {
289     WindowInfo info;
290     XEvent e;
291    
292     XNextEvent(&e);
293     switch (e.type) {
294     case KeyPressed:
295     docom(&e);
296     break;
297     case ExposeWindow:
298     XQueryWindow(wind, &info); /* in case resized */
299     width = info.width;
300     height = info.height;
301     /* fall through */
302     case ExposeRegion:
303     fixwindow(&e);
304     break;
305     case UnmapWindow:
306     unmap_rcolors(&ourras);
307     break;
308     case ButtonPressed:
309     if (controlshift(&e))
310     moveimage(&e);
311     else
312     getbox(&e);
313     break;
314     }
315     }
316    
317    
318     fixwindow(eexp) /* fix new or stepped-on window */
319     XExposeEvent *eexp;
320     {
321     redraw(eexp->x, eexp->y, eexp->width, eexp->height);
322     }
323    
324    
325     redraw(x, y, w, h) /* redraw section of window */
326     int x, y;
327     int w, h;
328     {
329     map_rcolors(&ourras);
330     if (fast)
331     make_rpixmap(&ourras);
332     return(patch_raster(wind,x-xoff,y-yoff,x,y,w,h,&ourras) ? 0 : -1);
333     }
334    
335    
336     docom(ekey) /* execute command */
337     XKeyEvent *ekey;
338     {
339     char buf[80];
340     COLOR cval;
341     char *cp;
342     int n;
343     FVECT rorg, rdir;
344    
345     cp = XLookupMapping(ekey, &n);
346     if (n == 0)
347     return(0);
348     switch (*cp) { /* interpret command */
349     case 'q':
350     case CTRL(D): /* quiterr */
351     quit(0);
352     case '\n':
353     case '\r':
354     case 'l':
355     case 'c': /* value */
356     if (avgbox(cval) == -1)
357     return(-1);
358     switch (*cp) {
359     case '\n':
360     case '\r': /* radiance */
361     sprintf(buf, "%-3g", intens(cval)/exposure);
362     break;
363     case 'l': /* luminance */
364     sprintf(buf, "%-3gL", bright(cval)*683.0/exposure);
365     break;
366     case 'c': /* color */
367     sprintf(buf, "(%.2f,%.2f,%.2f)",
368     colval(cval,RED),
369     colval(cval,GRN),
370     colval(cval,BLU));
371     break;
372     }
373     XText(wind, box.xmin, box.ymin, buf, strlen(buf),
374     fontid, BlackPixel, WhitePixel);
375     return(0);
376     case 'p': /* position */
377     sprintf(buf, "(%d,%d)", ekey->x-xoff, ymax-1-ekey->y+yoff);
378     XText(wind, ekey->x, ekey->y, buf, strlen(buf),
379     fontid, BlackPixel, WhitePixel);
380     return(0);
381     case 't': /* trace */
382     if (!gotview) {
383     XFeep(0);
384     return(-1);
385     }
386     rayview(rorg, rdir, &ourview,
387     ekey->x-xoff + .5, ymax-1-ekey->y+yoff + .5);
388     printf("%e %e %e ", rorg[0], rorg[1], rorg[2]);
389     printf("%e %e %e\n", rdir[0], rdir[1], rdir[2]);
390     fflush(stdout);
391     return(0);
392     case CTRL(R): /* redraw */
393     XClear(wind);
394     return(redraw(0, 0, width, height));
395     case ' ': /* clear */
396     return(redraw(box.xmin, box.ymin, box.xsiz, box.ysiz));
397     default:
398     XFeep(0);
399     return(-1);
400     }
401     }
402    
403    
404     moveimage(ep) /* shift the image */
405     XButtonEvent *ep;
406     {
407     XButtonEvent eb;
408    
409     XMaskEvent(ButtonReleased, &eb);
410     xoff += eb.x - ep->x;
411     yoff += eb.y - ep->y;
412     XClear(wind);
413     return(redraw(0, 0, width, height));
414     }
415    
416    
417     getbox(ebut) /* get new box */
418     XButtonEvent *ebut;
419     {
420     union {
421     XEvent e;
422     XButtonEvent b;
423     XMouseMovedEvent m;
424     } e;
425    
426     XMaskEvent(ButtonReleased|MouseMoved, &e.e);
427     while (e.e.type == MouseMoved) {
428     revbox(ebut->x, ebut->y, box.xmin = e.m.x, box.ymin = e.m.y);
429     XMaskEvent(ButtonReleased|MouseMoved, &e.e);
430     revbox(ebut->x, ebut->y, box.xmin, box.ymin);
431     }
432     box.xmin = e.b.x<0 ? 0 : (e.b.x>=width ? width-1 : e.b.x);
433     box.ymin = e.b.y<0 ? 0 : (e.b.y>=height ? height-1 : e.b.y);
434     if (box.xmin > ebut->x) {
435     box.xsiz = box.xmin - ebut->x + 1;
436     box.xmin = ebut->x;
437     } else {
438     box.xsiz = ebut->x - box.xmin + 1;
439     }
440     if (box.ymin > ebut->y) {
441     box.ysiz = box.ymin - ebut->y + 1;
442     box.ymin = ebut->y;
443     } else {
444     box.ysiz = ebut->y - box.ymin + 1;
445     }
446     }
447    
448    
449     revbox(x0, y0, x1, y1) /* draw box with reversed lines */
450     int x0, y0, x1, y1;
451     {
452     XLine(wind, x0, y0, x1, y0, 1, 1, 0, GXinvert, AllPlanes);
453     XLine(wind, x0, y1, x1, y1, 1, 1, 0, GXinvert, AllPlanes);
454     XLine(wind, x0, y0, x0, y1, 1, 1, 0, GXinvert, AllPlanes);
455     XLine(wind, x1, y0, x1, y1, 1, 1, 0, GXinvert, AllPlanes);
456     }
457    
458    
459     avgbox(clr) /* average color over current box */
460     COLOR clr;
461     {
462     int left, right, top, bottom;
463     int y;
464     double d;
465     COLOR ctmp;
466     register int x;
467    
468     setcolor(clr, 0.0, 0.0, 0.0);
469     left = box.xmin - xoff;
470     right = left + box.xsiz;
471     if (left < 0)
472     left = 0;
473     if (right > xmax)
474     right = xmax;
475     if (left >= right)
476     return(-1);
477     top = box.ymin - yoff;
478     bottom = top + box.ysiz;
479     if (top < 0)
480     top = 0;
481     if (bottom > ymax)
482     bottom = ymax;
483     if (top >= bottom)
484     return(-1);
485     for (y = top; y < bottom; y++) {
486     if (getscan(y) == -1)
487     return(-1);
488     for (x = left; x < right; x++) {
489     colr_color(ctmp, scanline[x]);
490     addcolor(clr, ctmp);
491     }
492     }
493     d = 1.0/((right-left)*(bottom-top));
494     scalecolor(clr, d);
495     return(0);
496     }
497    
498    
499     getmono() /* get monochrome data */
500     {
501     register unsigned short *dp;
502     register int x, err;
503     int y;
504     rgbpixel *inline;
505     short *cerr;
506    
507     if ((inline = (rgbpixel *)malloc(xmax*sizeof(rgbpixel))) == NULL
508     || (cerr = (short *)calloc(xmax,sizeof(short))) == NULL)
509     quit("out of memory in getmono");
510     dp = ourras.data.m - 1;
511     for (y = 0; y < ymax; y++) {
512     picreadline3(y, inline);
513     err = 0;
514     for (x = 0; x < xmax; x++) {
515     if (!(x&0xf))
516     *++dp = 0;
517     err += rgb_bright(&inline[x]) + cerr[x];
518     if (err > 127)
519     err -= 255;
520     else
521     *dp |= 1<<(x&0xf);
522     cerr[x] = err >>= 1;
523     }
524     }
525     free((char *)inline);
526     free((char *)cerr);
527     }
528    
529    
530     init_rcolors(xr, cmap) /* assign color values */
531     register XRASTER *xr;
532     colormap cmap;
533     {
534     register int i;
535     register unsigned char *p;
536    
537     xr->pmap = (int *)malloc(256*sizeof(int));
538     if (xr->pmap == NULL)
539     return(0);
540     xr->cdefs = (Color *)malloc(256*sizeof(Color));
541     if (xr->cdefs == NULL)
542     return(0);
543     for (i = 0; i < 256; i++)
544     xr->pmap[i] = -1;
545     xr->ncolors = 0;
546     for (p = xr->data.bz, i = BZPixmapSize(xr->width,xr->height); i--; p++)
547     if (xr->pmap[*p] == -1) {
548     xr->cdefs[xr->ncolors].red = cmap[0][*p] << 8;
549     xr->cdefs[xr->ncolors].green = cmap[1][*p] << 8;
550     xr->cdefs[xr->ncolors].blue = cmap[2][*p] << 8;
551     xr->cdefs[xr->ncolors].pixel = *p;
552     xr->pmap[*p] = xr->ncolors++;
553     }
554     xr->cdefs = (Color *)realloc((char *)xr->cdefs, xr->ncolors*sizeof(Color));
555     if (xr->cdefs == NULL)
556     return(0);
557     return(1);
558     }
559    
560    
561     getscan(y)
562     int y;
563     {
564     if (y != cury) {
565     if (scanpos == NULL || scanpos[y] == -1)
566     return(-1);
567     if (fseek(fin, scanpos[y], 0) == -1)
568     quit("fseek error");
569     cury = y;
570     } else if (scanpos != NULL)
571     scanpos[y] = ftell(fin);
572    
573     if (freadcolrs(scanline, xmax, fin) < 0)
574     quiterr("read error");
575    
576     cury++;
577     return(0);
578     }
579    
580    
581     picreadline3(y, l3) /* read in 3-byte scanline */
582     int y;
583     register rgbpixel *l3;
584     {
585     register BYTE *l4;
586     register int shift, c;
587     int i;
588    
589     if (getscan(y) < 0)
590     quiterr("cannot seek for picreadline");
591     /* convert scanline */
592     for (l4=scanline[0], i=xmax; i--; l4+=4, l3++) {
593     shift = l4[EXP] - COLXS;
594     if (shift >= 8) {
595     l3->r = l3->g = l3->b = 255;
596     } else if (shift <= -8) {
597     l3->r = l3->g = l3->b = 0;
598     } else if (shift > 0) {
599     c = l4[RED] << shift;
600     l3->r = c > 255 ? 255 : c;
601     c = l4[GRN] << shift;
602     l3->g = c > 255 ? 255 : c;
603     c = l4[BLU] << shift;
604     l3->b = c > 255 ? 255 : c;
605     } else if (shift < 0) {
606     l3->r = l4[RED] >> -shift;
607     l3->g = l4[GRN] >> -shift;
608     l3->b = l4[BLU] >> -shift;
609     } else {
610     l3->r = l4[RED];
611     l3->g = l4[GRN];
612     l3->b = l4[BLU];
613     }
614     }
615     }
616    
617    
618     picwriteline(y, l) /* add 8-bit scanline to image */
619     int y;
620     pixel *l;
621     {
622     bcopy(l, ourras.data.bz+BZPixmapSize(xmax,y), BZPixmapSize(xmax,1));
623     }
624    
625    
626     picreadcm(map) /* do gamcor correction */
627     colormap map;
628     {
629     extern double pow();
630     register int i, val;
631    
632     for (i = 0; i < 256; i++) {
633     val = pow(i/256.0, 1.0/gamcor) * 256.0;
634     map[0][i] = map[1][i] = map[2][i] = val;
635     }
636     }
637    
638    
639     picwritecm(map) /* handled elsewhere */
640     colormap map;
641     {
642     }