ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ximage.c
Revision: 2.4
Committed: Tue Apr 28 09:40:36 1992 UTC (32 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.3: +2 -9 lines
Log Message:
changed calls to get view parameters from files

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