ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ximage.c
Revision: 1.30
Committed: Wed May 1 12:40:03 1991 UTC (33 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.29: +1 -1 lines
Log Message:
changed 'n' to 'L' in luminance display

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