ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ximage.c
Revision: 1.2
Committed: Fri Apr 7 16:36:10 1989 UTC (35 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.1: +109 -34 lines
Log Message:
Added adjust exposure option and command

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 greg 1.2 double gamcor = 2.0; /* gamma correction */
42 greg 1.1
43 greg 1.2 XRASTER *ourras = NULL; /* our stored raster image */
44 greg 1.1
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 greg 1.2 int scale = 0; /* scalefactor; power of two */
55    
56 greg 1.1 int xoff = 0; /* x image offset */
57     int yoff = 0; /* y image offset */
58    
59     VIEW ourview = STDVIEW(0); /* image view parameters */
60     int gotview = 0; /* got parameters from file */
61    
62     COLR *scanline; /* scan line buffer */
63    
64     int xmax, ymax; /* picture resolution */
65     int width, height; /* window size */
66     char *fname = NULL; /* input file name */
67     FILE *fin = stdin; /* input file */
68     long *scanpos = NULL; /* scan line positions in file */
69     int cury = 0; /* current scan location */
70    
71     double exposure = 1.0; /* exposure compensation used */
72    
73     struct {
74     int xmin, ymin, xsiz, ysiz;
75     } box = {0, 0, 0, 0}; /* current box */
76    
77     char *geometry = NULL; /* geometry specification */
78    
79     char *progname;
80    
81     char errmsg[128];
82    
83     extern long ftell();
84    
85     extern char *malloc(), *calloc();
86    
87 greg 1.2 extern double atof(), pow(), log();
88 greg 1.1
89    
90     main(argc, argv)
91     int argc;
92     char *argv[];
93     {
94     int headline();
95     int i;
96    
97     progname = argv[0];
98    
99     for (i = 1; i < argc; i++)
100     if (argv[i][0] == '-')
101     switch (argv[i][1]) {
102     case 'c':
103     maxcolors = atoi(argv[++i]);
104     break;
105     case 'b':
106     greyscale = !greyscale;
107     break;
108     case 'm':
109     maxcolors = 2;
110     break;
111     case 'd':
112     dither = !dither;
113     break;
114     case 'f':
115     fast = !fast;
116     break;
117 greg 1.2 case 'e':
118     if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
119     goto userr;
120     scale = atoi(argv[++i]);
121     break;
122 greg 1.1 case 'g':
123     gamcor = atof(argv[++i]);
124     break;
125     default:
126     goto userr;
127     }
128     else if (argv[i][0] == '=')
129     geometry = argv[i];
130     else
131     break;
132    
133     if (argc-i == 1) {
134     fname = argv[i];
135     fin = fopen(fname, "r");
136     if (fin == NULL) {
137     sprintf(errmsg, "can't open file \"%s\"", fname);
138     quiterr(errmsg);
139     }
140     } else
141     goto userr;
142    
143     /* get header */
144     getheader(fin, headline);
145     /* get picture dimensions */
146     if (fscanf(fin, "-Y %d +X %d\n", &ymax, &xmax) != 2)
147     quiterr("bad picture size");
148     /* set view parameters */
149     if (gotview) {
150     ourview.hresolu = xmax;
151     ourview.vresolu = ymax;
152     if (setview(&ourview) != NULL)
153     gotview = 0;
154     }
155     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     static char *altname[] = {"rview","rpict","VIEW=",NULL};
174     register char **an;
175    
176     if (!strncmp(s, "EXPOSURE=", 9))
177     exposure *= atof(s+9);
178     else
179     for (an = altname; *an != NULL; an++)
180     if (!strncmp(*an, s, strlen(*an))) {
181     if (sscanview(&ourview, s+strlen(*an)) == 0)
182     gotview++;
183     return;
184     }
185     }
186    
187    
188     char *
189     sskip(s) /* skip a word */
190     register char *s;
191     {
192     while (isspace(*s)) s++;
193     while (*s && !isspace(*s)) s++;
194     return(s);
195     }
196    
197    
198     init() /* get data and open window */
199     {
200     register int i;
201     OpaqueFrame mainframe;
202     char defgeom[32];
203    
204     if (fname != NULL) {
205     scanpos = (long *)malloc(ymax*sizeof(long));
206     if (scanpos == NULL)
207     goto memerr;
208     for (i = 0; i < ymax; i++)
209     scanpos[i] = -1;
210     }
211     if (XOpenDisplay(NULL) == NULL)
212     quiterr("can't open display; DISPLAY variable set?");
213     #ifdef notdef
214     if (DisplayWidth() - 2*BORWIDTH < xmax ||
215     DisplayHeight() - 2*BORWIDTH - BARHEIGHT < ymax)
216     quiterr("resolution mismatch");
217     #endif
218     if (maxcolors == 0) { /* get number of available colors */
219     maxcolors = 1<<DisplayPlanes();
220     if (maxcolors > 4) maxcolors -= 2;
221     }
222     /* store image */
223 greg 1.2 getras();
224    
225 greg 1.1 mainframe.bdrwidth = BORWIDTH;
226     mainframe.border = WhitePixmap;
227     mainframe.background = BlackPixmap;
228     sprintf(defgeom, "=%dx%d+0+22", xmax, ymax);
229     wind = XCreate("Radiance Image", progname, geometry, defgeom,
230     &mainframe, 16, 16);
231     if (wind == 0)
232     quiterr("can't create window");
233     width = mainframe.width;
234     height = mainframe.height;
235     fontid = XGetFont(FONTNAME);
236     if (fontid == 0)
237     quiterr("can't get font");
238     XStoreName(wind, fname == NULL ? progname : fname);
239     XDefineCursor(wind, XCreateCursor(bcross_width, bcross_height,
240     bcross_bits, bcross_mask_bits,
241     bcross_x_hot, bcross_y_hot,
242     BlackPixel, WhitePixel, GXcopy));
243     XSelectInput(wind, ButtonPressed|ButtonReleased|UnmapWindow
244     |RightDownMotion|MiddleDownMotion|LeftDownMotion
245     |KeyPressed|ExposeWindow|ExposeRegion);
246     XMapWindow(wind);
247     return;
248     memerr:
249     quiterr("out of memory");
250     }
251    
252    
253     quiterr(err) /* print message and exit */
254     char *err;
255     {
256     if (err != NULL)
257     fprintf(stderr, "%s: %s\n", progname, err);
258    
259     exit(err == NULL ? 0 : 1);
260     }
261    
262    
263     eputs(s)
264     char *s;
265     {
266     fputs(s, stderr);
267     }
268    
269    
270     quit(code)
271     int code;
272     {
273     exit(code);
274     }
275    
276    
277 greg 1.2 getras() /* get raster file */
278     {
279     colormap ourmap;
280    
281     ourras = (XRASTER *)calloc(1, sizeof(XRASTER));
282     if (ourras == NULL)
283     goto memerr;
284     ourras->width = xmax;
285     ourras->height = ymax;
286     if (maxcolors <= 2) { /* monochrome */
287     ourras->data.m = (unsigned short *)malloc(BitmapSize(xmax,ymax));
288     if (ourras->data.m == NULL)
289     goto memerr;
290     getmono();
291     } else {
292     ourras->data.bz = (unsigned char *)malloc(BZPixmapSize(xmax,ymax));
293     if (ourras->data.bz == NULL)
294     goto memerr;
295     if (greyscale)
296     biq(dither,maxcolors,1,ourmap);
297     else
298     ciq(dither,maxcolors,1,ourmap);
299     if (init_rcolors(ourras, ourmap) == 0)
300     goto memerr;
301     }
302     return;
303     memerr:
304     quit("out of memory");
305     }
306    
307    
308 greg 1.1 getevent() /* process the next event */
309     {
310     WindowInfo info;
311     XEvent e;
312    
313     XNextEvent(&e);
314     switch (e.type) {
315     case KeyPressed:
316     docom(&e);
317     break;
318     case ExposeWindow:
319     XQueryWindow(wind, &info); /* in case resized */
320     width = info.width;
321     height = info.height;
322     /* fall through */
323     case ExposeRegion:
324     fixwindow(&e);
325     break;
326     case UnmapWindow:
327 greg 1.2 unmap_rcolors(ourras);
328 greg 1.1 break;
329     case ButtonPressed:
330     if (controlshift(&e))
331     moveimage(&e);
332     else
333     getbox(&e);
334     break;
335     }
336     }
337    
338    
339     fixwindow(eexp) /* fix new or stepped-on window */
340     XExposeEvent *eexp;
341     {
342     redraw(eexp->x, eexp->y, eexp->width, eexp->height);
343     }
344    
345    
346     redraw(x, y, w, h) /* redraw section of window */
347     int x, y;
348     int w, h;
349     {
350 greg 1.2 if (map_rcolors(ourras) == NULL) {
351     fprintf(stderr, "%s: cannot allocate colors\n", progname);
352     return(-1);
353     }
354 greg 1.1 if (fast)
355 greg 1.2 make_rpixmap(ourras);
356     return(patch_raster(wind,x-xoff,y-yoff,x,y,w,h,ourras) ? 0 : -1);
357 greg 1.1 }
358    
359    
360     docom(ekey) /* execute command */
361     XKeyEvent *ekey;
362     {
363     char buf[80];
364     COLOR cval;
365     char *cp;
366     int n;
367 greg 1.2 double comp;
368 greg 1.1 FVECT rorg, rdir;
369    
370     cp = XLookupMapping(ekey, &n);
371     if (n == 0)
372     return(0);
373     switch (*cp) { /* interpret command */
374     case 'q':
375     case CTRL(D): /* quiterr */
376     quit(0);
377     case '\n':
378     case '\r':
379     case 'l':
380     case 'c': /* value */
381     if (avgbox(cval) == -1)
382     return(-1);
383     switch (*cp) {
384     case '\n':
385     case '\r': /* radiance */
386     sprintf(buf, "%-3g", intens(cval)/exposure);
387     break;
388     case 'l': /* luminance */
389     sprintf(buf, "%-3gL", bright(cval)*683.0/exposure);
390     break;
391     case 'c': /* color */
392 greg 1.2 comp = pow(2.0, (double)scale);
393 greg 1.1 sprintf(buf, "(%.2f,%.2f,%.2f)",
394 greg 1.2 colval(cval,RED)*comp,
395     colval(cval,GRN)*comp,
396     colval(cval,BLU)*comp);
397 greg 1.1 break;
398     }
399     XText(wind, box.xmin, box.ymin, buf, strlen(buf),
400     fontid, BlackPixel, WhitePixel);
401     return(0);
402     case 'p': /* position */
403     sprintf(buf, "(%d,%d)", ekey->x-xoff, ymax-1-ekey->y+yoff);
404     XText(wind, ekey->x, ekey->y, buf, strlen(buf),
405     fontid, BlackPixel, WhitePixel);
406     return(0);
407     case 't': /* trace */
408     if (!gotview) {
409     XFeep(0);
410     return(-1);
411     }
412     rayview(rorg, rdir, &ourview,
413     ekey->x-xoff + .5, ymax-1-ekey->y+yoff + .5);
414     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     if (n == 0) {
423     XFeep(0);
424     return(0);
425     }
426     scale_rcolors(ourras, pow(2.0, (double)n));
427     scale += n;
428     sprintf(buf, "%+d", scale);
429     XText(wind, box.xmin, box.ymin, buf, strlen(buf),
430     fontid, BlackPixel, WhitePixel);
431     XFlush();
432     free_raster(ourras);
433     getras();
434     return(redraw(0, 0, width, height));
435 greg 1.1 case CTRL(R): /* redraw */
436     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     int y;
547     rgbpixel *inline;
548     short *cerr;
549    
550     if ((inline = (rgbpixel *)malloc(xmax*sizeof(rgbpixel))) == NULL
551     || (cerr = (short *)calloc(xmax,sizeof(short))) == NULL)
552     quit("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     picreadline3(y, inline);
556     err = 0;
557     for (x = 0; x < xmax; x++) {
558     if (!(x&0xf))
559     *++dp = 0;
560     err += rgb_bright(&inline[x]) + cerr[x];
561     if (err > 127)
562     err -= 255;
563     else
564     *dp |= 1<<(x&0xf);
565     cerr[x] = err >>= 1;
566     }
567     }
568     free((char *)inline);
569     free((char *)cerr);
570     }
571    
572    
573 greg 1.2 init_rcolors(xr, cmap) /* (re)assign color values */
574 greg 1.1 register XRASTER *xr;
575     colormap cmap;
576     {
577     register int i;
578     register unsigned char *p;
579    
580     xr->pmap = (int *)malloc(256*sizeof(int));
581     if (xr->pmap == NULL)
582     return(0);
583     xr->cdefs = (Color *)malloc(256*sizeof(Color));
584     if (xr->cdefs == NULL)
585     return(0);
586     for (i = 0; i < 256; i++)
587     xr->pmap[i] = -1;
588     xr->ncolors = 0;
589     for (p = xr->data.bz, i = BZPixmapSize(xr->width,xr->height); i--; p++)
590     if (xr->pmap[*p] == -1) {
591     xr->cdefs[xr->ncolors].red = cmap[0][*p] << 8;
592     xr->cdefs[xr->ncolors].green = cmap[1][*p] << 8;
593     xr->cdefs[xr->ncolors].blue = cmap[2][*p] << 8;
594     xr->cdefs[xr->ncolors].pixel = *p;
595     xr->pmap[*p] = xr->ncolors++;
596     }
597     xr->cdefs = (Color *)realloc((char *)xr->cdefs, xr->ncolors*sizeof(Color));
598     if (xr->cdefs == NULL)
599     return(0);
600     return(1);
601     }
602    
603    
604 greg 1.2 scale_rcolors(xr, sf) /* scale color map */
605     register XRASTER *xr;
606     double sf;
607     {
608     register int i;
609     int maxv;
610    
611     sf = pow(sf, 1.0/gamcor);
612     maxv = (1<<16) / sf;
613    
614     for (i = xr->ncolors; i--; ) {
615     xr->cdefs[i].red = xr->cdefs[i].red >= maxv ?
616     (1<<16)-1 :
617     xr->cdefs[i].red * sf;
618     xr->cdefs[i].green = xr->cdefs[i].green >= maxv ?
619     (1<<16)-1 :
620     xr->cdefs[i].green * sf;
621     xr->cdefs[i].blue = xr->cdefs[i].blue >= maxv ?
622     (1<<16)-1 :
623     xr->cdefs[i].blue * sf;
624     }
625     if (xr->pixels != NULL)
626     XStoreColors(xr->ncolors, xr->cdefs);
627     }
628    
629    
630 greg 1.1 getscan(y)
631     int y;
632     {
633     if (y != cury) {
634     if (scanpos == NULL || scanpos[y] == -1)
635     return(-1);
636     if (fseek(fin, scanpos[y], 0) == -1)
637     quit("fseek error");
638     cury = y;
639     } else if (scanpos != NULL)
640     scanpos[y] = ftell(fin);
641    
642     if (freadcolrs(scanline, xmax, fin) < 0)
643     quiterr("read error");
644    
645     cury++;
646     return(0);
647     }
648    
649    
650     picreadline3(y, l3) /* read in 3-byte scanline */
651     int y;
652     register rgbpixel *l3;
653     {
654     register BYTE *l4;
655     register int shift, c;
656     int i;
657    
658     if (getscan(y) < 0)
659     quiterr("cannot seek for picreadline");
660     /* convert scanline */
661     for (l4=scanline[0], i=xmax; i--; l4+=4, l3++) {
662 greg 1.2 shift = l4[EXP] - COLXS + scale;
663 greg 1.1 if (shift >= 8) {
664     l3->r = l3->g = l3->b = 255;
665     } else if (shift <= -8) {
666     l3->r = l3->g = l3->b = 0;
667     } else if (shift > 0) {
668     c = l4[RED] << shift;
669     l3->r = c > 255 ? 255 : c;
670     c = l4[GRN] << shift;
671     l3->g = c > 255 ? 255 : c;
672     c = l4[BLU] << shift;
673     l3->b = c > 255 ? 255 : c;
674     } else if (shift < 0) {
675     l3->r = l4[RED] >> -shift;
676     l3->g = l4[GRN] >> -shift;
677     l3->b = l4[BLU] >> -shift;
678     } else {
679     l3->r = l4[RED];
680     l3->g = l4[GRN];
681     l3->b = l4[BLU];
682     }
683     }
684     }
685    
686    
687     picwriteline(y, l) /* add 8-bit scanline to image */
688     int y;
689     pixel *l;
690     {
691 greg 1.2 bcopy(l, ourras->data.bz+BZPixmapSize(xmax,y), BZPixmapSize(xmax,1));
692 greg 1.1 }
693    
694    
695     picreadcm(map) /* do gamcor correction */
696     colormap map;
697     {
698     extern double pow();
699     register int i, val;
700    
701     for (i = 0; i < 256; i++) {
702     val = pow(i/256.0, 1.0/gamcor) * 256.0;
703     map[0][i] = map[1][i] = map[2][i] = val;
704     }
705     }
706    
707    
708     picwritecm(map) /* handled elsewhere */
709     colormap map;
710     {
711 greg 1.2 #ifdef DEBUG
712     register int i;
713    
714     for (i = 0; i < 256; i++)
715     printf("%d %d %d\n", map[0][i],map[1][i],map[2][i]);
716     #endif
717 greg 1.1 }