ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ximage.c
Revision: 1.11
Committed: Tue Oct 3 09:11:43 1989 UTC (34 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.10: +1 -1 lines
Log Message:
increased default gamma correction

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.11 double gamcor = 2.2; /* 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 greg 1.6 }
141 greg 1.1 /* get header */
142     getheader(fin, headline);
143     /* get picture dimensions */
144 greg 1.9 if (fgetresolu(&xmax, &ymax, fin) != (YMAJOR|YDECR))
145 greg 1.1 quiterr("bad picture size");
146     /* set view parameters */
147 greg 1.10 if (gotview)
148 greg 1.1 if (setview(&ourview) != NULL)
149     gotview = 0;
150 greg 1.10
151 greg 1.1 if ((scanline = (COLR *)malloc(xmax*sizeof(COLR))) == NULL)
152     quiterr("out of memory");
153    
154     init(); /* get file and open window */
155    
156     for ( ; ; )
157     getevent(); /* main loop */
158     userr:
159     fprintf(stderr,
160 greg 1.2 "Usage: %s [=geometry][-b][-m][-d][-f][-c ncolors][-e +/-stops] file\n",
161 greg 1.1 progname);
162     quit(1);
163     }
164    
165    
166     headline(s) /* get relevant info from header */
167     char *s;
168     {
169 greg 1.4 static char *altname[] = {"rview","rpict",VIEWSTR,NULL};
170 greg 1.1 register char **an;
171    
172     if (!strncmp(s, "EXPOSURE=", 9))
173     exposure *= atof(s+9);
174     else
175     for (an = altname; *an != NULL; an++)
176     if (!strncmp(*an, s, strlen(*an))) {
177     if (sscanview(&ourview, s+strlen(*an)) == 0)
178     gotview++;
179     return;
180     }
181     }
182    
183    
184     char *
185     sskip(s) /* skip a word */
186     register char *s;
187     {
188     while (isspace(*s)) s++;
189     while (*s && !isspace(*s)) s++;
190     return(s);
191     }
192    
193    
194     init() /* get data and open window */
195     {
196     register int i;
197     OpaqueFrame mainframe;
198     char defgeom[32];
199    
200     if (fname != NULL) {
201     scanpos = (long *)malloc(ymax*sizeof(long));
202     if (scanpos == NULL)
203     goto memerr;
204     for (i = 0; i < ymax; i++)
205     scanpos[i] = -1;
206     }
207     if (XOpenDisplay(NULL) == NULL)
208     quiterr("can't open display; DISPLAY variable set?");
209     #ifdef notdef
210     if (DisplayWidth() - 2*BORWIDTH < xmax ||
211     DisplayHeight() - 2*BORWIDTH - BARHEIGHT < ymax)
212     quiterr("resolution mismatch");
213     #endif
214     if (maxcolors == 0) { /* get number of available colors */
215     maxcolors = 1<<DisplayPlanes();
216     if (maxcolors > 4) maxcolors -= 2;
217     }
218     /* store image */
219 greg 1.2 getras();
220    
221 greg 1.1 mainframe.bdrwidth = BORWIDTH;
222     mainframe.border = WhitePixmap;
223     mainframe.background = BlackPixmap;
224     sprintf(defgeom, "=%dx%d+0+22", xmax, ymax);
225     wind = XCreate("Radiance Image", progname, geometry, defgeom,
226     &mainframe, 16, 16);
227     if (wind == 0)
228     quiterr("can't create window");
229     width = mainframe.width;
230     height = mainframe.height;
231     fontid = XGetFont(FONTNAME);
232     if (fontid == 0)
233     quiterr("can't get font");
234     XStoreName(wind, fname == NULL ? progname : fname);
235     XDefineCursor(wind, XCreateCursor(bcross_width, bcross_height,
236     bcross_bits, bcross_mask_bits,
237     bcross_x_hot, bcross_y_hot,
238     BlackPixel, WhitePixel, GXcopy));
239     XSelectInput(wind, ButtonPressed|ButtonReleased|UnmapWindow
240     |RightDownMotion|MiddleDownMotion|LeftDownMotion
241     |KeyPressed|ExposeWindow|ExposeRegion);
242     XMapWindow(wind);
243     return;
244     memerr:
245     quiterr("out of memory");
246     }
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    
255     exit(err == NULL ? 0 : 1);
256     }
257    
258    
259     eputs(s)
260     char *s;
261     {
262     fputs(s, stderr);
263     }
264    
265    
266     quit(code)
267     int code;
268     {
269     exit(code);
270     }
271    
272    
273 greg 1.2 getras() /* get raster file */
274     {
275     colormap ourmap;
276    
277     ourras = (XRASTER *)calloc(1, sizeof(XRASTER));
278     if (ourras == NULL)
279     goto memerr;
280     ourras->width = xmax;
281     ourras->height = ymax;
282     if (maxcolors <= 2) { /* monochrome */
283     ourras->data.m = (unsigned short *)malloc(BitmapSize(xmax,ymax));
284     if (ourras->data.m == NULL)
285     goto memerr;
286     getmono();
287     } else {
288     ourras->data.bz = (unsigned char *)malloc(BZPixmapSize(xmax,ymax));
289     if (ourras->data.bz == NULL)
290     goto memerr;
291     if (greyscale)
292     biq(dither,maxcolors,1,ourmap);
293     else
294     ciq(dither,maxcolors,1,ourmap);
295     if (init_rcolors(ourras, ourmap) == 0)
296     goto memerr;
297     }
298     return;
299     memerr:
300     quit("out of memory");
301     }
302    
303    
304 greg 1.1 getevent() /* process the next event */
305     {
306     WindowInfo info;
307     XEvent e;
308    
309     XNextEvent(&e);
310     switch (e.type) {
311     case KeyPressed:
312     docom(&e);
313     break;
314     case ExposeWindow:
315     XQueryWindow(wind, &info); /* in case resized */
316     width = info.width;
317     height = info.height;
318     /* fall through */
319     case ExposeRegion:
320     fixwindow(&e);
321     break;
322     case UnmapWindow:
323 greg 1.2 unmap_rcolors(ourras);
324 greg 1.1 break;
325     case ButtonPressed:
326     if (controlshift(&e))
327     moveimage(&e);
328     else
329     getbox(&e);
330     break;
331     }
332     }
333    
334    
335     fixwindow(eexp) /* fix new or stepped-on window */
336     XExposeEvent *eexp;
337     {
338     redraw(eexp->x, eexp->y, eexp->width, eexp->height);
339     }
340    
341    
342     redraw(x, y, w, h) /* redraw section of window */
343     int x, y;
344     int w, h;
345     {
346 greg 1.7 if (ourras->ncolors && map_rcolors(ourras) == NULL) {
347 greg 1.2 fprintf(stderr, "%s: cannot allocate colors\n", progname);
348     return(-1);
349     }
350 greg 1.1 if (fast)
351 greg 1.2 make_rpixmap(ourras);
352     return(patch_raster(wind,x-xoff,y-yoff,x,y,w,h,ourras) ? 0 : -1);
353 greg 1.1 }
354    
355    
356     docom(ekey) /* execute command */
357     XKeyEvent *ekey;
358     {
359     char buf[80];
360     COLOR cval;
361     char *cp;
362     int n;
363 greg 1.2 double comp;
364 greg 1.1 FVECT rorg, rdir;
365    
366     cp = XLookupMapping(ekey, &n);
367     if (n == 0)
368     return(0);
369     switch (*cp) { /* interpret command */
370     case 'q':
371     case CTRL(D): /* quiterr */
372     quit(0);
373     case '\n':
374     case '\r':
375     case 'l':
376     case 'c': /* value */
377     if (avgbox(cval) == -1)
378     return(-1);
379     switch (*cp) {
380     case '\n':
381     case '\r': /* radiance */
382     sprintf(buf, "%-3g", intens(cval)/exposure);
383     break;
384     case 'l': /* luminance */
385     sprintf(buf, "%-3gL", bright(cval)*683.0/exposure);
386     break;
387     case 'c': /* color */
388 greg 1.2 comp = pow(2.0, (double)scale);
389 greg 1.1 sprintf(buf, "(%.2f,%.2f,%.2f)",
390 greg 1.2 colval(cval,RED)*comp,
391     colval(cval,GRN)*comp,
392     colval(cval,BLU)*comp);
393 greg 1.1 break;
394     }
395     XText(wind, box.xmin, box.ymin, buf, strlen(buf),
396     fontid, BlackPixel, WhitePixel);
397     return(0);
398     case 'p': /* position */
399     sprintf(buf, "(%d,%d)", ekey->x-xoff, ymax-1-ekey->y+yoff);
400     XText(wind, ekey->x, ekey->y, buf, strlen(buf),
401     fontid, BlackPixel, WhitePixel);
402     return(0);
403     case 't': /* trace */
404     if (!gotview) {
405     XFeep(0);
406     return(-1);
407     }
408     rayview(rorg, rdir, &ourview,
409     ekey->x-xoff + .5, ymax-1-ekey->y+yoff + .5);
410     printf("%e %e %e ", rorg[0], rorg[1], rorg[2]);
411     printf("%e %e %e\n", rdir[0], rdir[1], rdir[2]);
412     fflush(stdout);
413     return(0);
414 greg 1.2 case '=': /* adjust exposure */
415     if (avgbox(cval) == -1)
416     return(-1);
417     n = log(.5/bright(cval))/.69315 - scale; /* truncate */
418 greg 1.5 if (n == 0)
419 greg 1.2 return(0);
420     scale_rcolors(ourras, pow(2.0, (double)n));
421     scale += n;
422     sprintf(buf, "%+d", scale);
423     XText(wind, box.xmin, box.ymin, buf, strlen(buf),
424     fontid, BlackPixel, WhitePixel);
425     XFlush();
426     free_raster(ourras);
427     getras();
428 greg 1.3 /* fall through */
429 greg 1.1 case CTRL(R): /* redraw */
430 greg 1.6 case CTRL(L):
431 greg 1.1 XClear(wind);
432     return(redraw(0, 0, width, height));
433     case ' ': /* clear */
434     return(redraw(box.xmin, box.ymin, box.xsiz, box.ysiz));
435     default:
436     XFeep(0);
437     return(-1);
438     }
439     }
440    
441    
442     moveimage(ep) /* shift the image */
443     XButtonEvent *ep;
444     {
445     XButtonEvent eb;
446    
447     XMaskEvent(ButtonReleased, &eb);
448     xoff += eb.x - ep->x;
449     yoff += eb.y - ep->y;
450     XClear(wind);
451     return(redraw(0, 0, width, height));
452     }
453    
454    
455     getbox(ebut) /* get new box */
456     XButtonEvent *ebut;
457     {
458     union {
459     XEvent e;
460     XButtonEvent b;
461     XMouseMovedEvent m;
462     } e;
463    
464     XMaskEvent(ButtonReleased|MouseMoved, &e.e);
465     while (e.e.type == MouseMoved) {
466     revbox(ebut->x, ebut->y, box.xmin = e.m.x, box.ymin = e.m.y);
467     XMaskEvent(ButtonReleased|MouseMoved, &e.e);
468     revbox(ebut->x, ebut->y, box.xmin, box.ymin);
469     }
470     box.xmin = e.b.x<0 ? 0 : (e.b.x>=width ? width-1 : e.b.x);
471     box.ymin = e.b.y<0 ? 0 : (e.b.y>=height ? height-1 : e.b.y);
472     if (box.xmin > ebut->x) {
473     box.xsiz = box.xmin - ebut->x + 1;
474     box.xmin = ebut->x;
475     } else {
476     box.xsiz = ebut->x - box.xmin + 1;
477     }
478     if (box.ymin > ebut->y) {
479     box.ysiz = box.ymin - ebut->y + 1;
480     box.ymin = ebut->y;
481     } else {
482     box.ysiz = ebut->y - box.ymin + 1;
483     }
484     }
485    
486    
487     revbox(x0, y0, x1, y1) /* draw box with reversed lines */
488     int x0, y0, x1, y1;
489     {
490     XLine(wind, x0, y0, x1, y0, 1, 1, 0, GXinvert, AllPlanes);
491     XLine(wind, x0, y1, x1, y1, 1, 1, 0, GXinvert, AllPlanes);
492     XLine(wind, x0, y0, x0, y1, 1, 1, 0, GXinvert, AllPlanes);
493     XLine(wind, x1, y0, x1, y1, 1, 1, 0, GXinvert, AllPlanes);
494     }
495    
496    
497     avgbox(clr) /* average color over current box */
498     COLOR clr;
499     {
500     int left, right, top, bottom;
501     int y;
502     double d;
503     COLOR ctmp;
504     register int x;
505    
506     setcolor(clr, 0.0, 0.0, 0.0);
507     left = box.xmin - xoff;
508     right = left + box.xsiz;
509     if (left < 0)
510     left = 0;
511     if (right > xmax)
512     right = xmax;
513     if (left >= right)
514     return(-1);
515     top = box.ymin - yoff;
516     bottom = top + box.ysiz;
517     if (top < 0)
518     top = 0;
519     if (bottom > ymax)
520     bottom = ymax;
521     if (top >= bottom)
522     return(-1);
523     for (y = top; y < bottom; y++) {
524     if (getscan(y) == -1)
525     return(-1);
526     for (x = left; x < right; x++) {
527     colr_color(ctmp, scanline[x]);
528     addcolor(clr, ctmp);
529     }
530     }
531     d = 1.0/((right-left)*(bottom-top));
532     scalecolor(clr, d);
533     return(0);
534     }
535    
536    
537     getmono() /* get monochrome data */
538     {
539     register unsigned short *dp;
540     register int x, err;
541     int y;
542     rgbpixel *inline;
543     short *cerr;
544    
545     if ((inline = (rgbpixel *)malloc(xmax*sizeof(rgbpixel))) == NULL
546     || (cerr = (short *)calloc(xmax,sizeof(short))) == NULL)
547     quit("out of memory in getmono");
548 greg 1.2 dp = ourras->data.m - 1;
549 greg 1.1 for (y = 0; y < ymax; y++) {
550     picreadline3(y, inline);
551     err = 0;
552     for (x = 0; x < xmax; x++) {
553     if (!(x&0xf))
554     *++dp = 0;
555     err += rgb_bright(&inline[x]) + cerr[x];
556     if (err > 127)
557     err -= 255;
558     else
559     *dp |= 1<<(x&0xf);
560     cerr[x] = err >>= 1;
561     }
562     }
563     free((char *)inline);
564     free((char *)cerr);
565     }
566    
567    
568 greg 1.2 init_rcolors(xr, cmap) /* (re)assign color values */
569 greg 1.1 register XRASTER *xr;
570     colormap cmap;
571     {
572     register int i;
573     register unsigned char *p;
574    
575     xr->pmap = (int *)malloc(256*sizeof(int));
576     if (xr->pmap == NULL)
577     return(0);
578     xr->cdefs = (Color *)malloc(256*sizeof(Color));
579     if (xr->cdefs == NULL)
580     return(0);
581     for (i = 0; i < 256; i++)
582     xr->pmap[i] = -1;
583     xr->ncolors = 0;
584     for (p = xr->data.bz, i = BZPixmapSize(xr->width,xr->height); i--; p++)
585     if (xr->pmap[*p] == -1) {
586     xr->cdefs[xr->ncolors].red = cmap[0][*p] << 8;
587     xr->cdefs[xr->ncolors].green = cmap[1][*p] << 8;
588     xr->cdefs[xr->ncolors].blue = cmap[2][*p] << 8;
589     xr->cdefs[xr->ncolors].pixel = *p;
590     xr->pmap[*p] = xr->ncolors++;
591     }
592     xr->cdefs = (Color *)realloc((char *)xr->cdefs, xr->ncolors*sizeof(Color));
593     if (xr->cdefs == NULL)
594     return(0);
595     return(1);
596     }
597    
598    
599 greg 1.2 scale_rcolors(xr, sf) /* scale color map */
600     register XRASTER *xr;
601     double sf;
602     {
603     register int i;
604     int maxv;
605    
606     sf = pow(sf, 1.0/gamcor);
607     maxv = (1<<16) / sf;
608    
609     for (i = xr->ncolors; i--; ) {
610     xr->cdefs[i].red = xr->cdefs[i].red >= maxv ?
611     (1<<16)-1 :
612     xr->cdefs[i].red * sf;
613     xr->cdefs[i].green = xr->cdefs[i].green >= maxv ?
614     (1<<16)-1 :
615     xr->cdefs[i].green * sf;
616     xr->cdefs[i].blue = xr->cdefs[i].blue >= maxv ?
617     (1<<16)-1 :
618     xr->cdefs[i].blue * sf;
619     }
620     if (xr->pixels != NULL)
621     XStoreColors(xr->ncolors, xr->cdefs);
622     }
623    
624    
625 greg 1.1 getscan(y)
626     int y;
627     {
628     if (y != cury) {
629     if (scanpos == NULL || scanpos[y] == -1)
630     return(-1);
631     if (fseek(fin, scanpos[y], 0) == -1)
632     quit("fseek error");
633     cury = y;
634     } else if (scanpos != NULL)
635     scanpos[y] = ftell(fin);
636    
637     if (freadcolrs(scanline, xmax, fin) < 0)
638     quiterr("read error");
639    
640     cury++;
641     return(0);
642     }
643    
644    
645     picreadline3(y, l3) /* read in 3-byte scanline */
646     int y;
647     register rgbpixel *l3;
648     {
649     register BYTE *l4;
650     register int shift, c;
651     int i;
652    
653     if (getscan(y) < 0)
654     quiterr("cannot seek for picreadline");
655     /* convert scanline */
656     for (l4=scanline[0], i=xmax; i--; l4+=4, l3++) {
657 greg 1.2 shift = l4[EXP] - COLXS + scale;
658 greg 1.1 if (shift >= 8) {
659     l3->r = l3->g = l3->b = 255;
660     } else if (shift <= -8) {
661     l3->r = l3->g = l3->b = 0;
662     } else if (shift > 0) {
663     c = l4[RED] << shift;
664     l3->r = c > 255 ? 255 : c;
665     c = l4[GRN] << shift;
666     l3->g = c > 255 ? 255 : c;
667     c = l4[BLU] << shift;
668     l3->b = c > 255 ? 255 : c;
669     } else if (shift < 0) {
670     l3->r = l4[RED] >> -shift;
671     l3->g = l4[GRN] >> -shift;
672     l3->b = l4[BLU] >> -shift;
673     } else {
674     l3->r = l4[RED];
675     l3->g = l4[GRN];
676     l3->b = l4[BLU];
677     }
678     }
679     }
680    
681    
682     picwriteline(y, l) /* add 8-bit scanline to image */
683     int y;
684     pixel *l;
685     {
686 greg 1.2 bcopy(l, ourras->data.bz+BZPixmapSize(xmax,y), BZPixmapSize(xmax,1));
687 greg 1.1 }
688    
689    
690 greg 1.8 picreadcm(map) /* do gamma correction */
691 greg 1.1 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 greg 1.2 #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 greg 1.1 }