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

# Content
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 #include "random.h"
33
34 #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 double gamcor = 2.2; /* gamma correction */
44
45 XRASTER *ourras = NULL; /* our stored raster image */
46
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 int scale = 0; /* scalefactor; power of two */
57
58 int xoff = 0; /* x image offset */
59 int yoff = 0; /* y image offset */
60
61 VIEW ourview = STDVIEW; /* image view parameters */
62 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 int wrongformat = 0; /* input in another format */
76
77 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 extern double atof(), pow(), log();
92
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 case 'e':
122 if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
123 goto userr;
124 scale = atoi(argv[++i]);
125 break;
126 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 }
145 /* get header */
146 getheader(fin, headline, NULL);
147 /* get picture dimensions */
148 if (wrongformat || fgetresolu(&xmax, &ymax, fin) != (YMAJOR|YDECR))
149 quiterr("bad picture size");
150 /* set view parameters */
151 if (gotview && setview(&ourview) != NULL)
152 gotview = 0;
153 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 "Usage: %s [=geometry][-b][-m][-d][-f][-c ncolors][-e +/-stops] file\n",
163 progname);
164 quit(1);
165 }
166
167
168 headline(s) /* get relevant info from header */
169 char *s;
170 {
171 static char *altname[] = {"rview","rpict",VIEWSTR,NULL};
172 register char **an;
173 char fmt[32];
174
175 if (isexpos(s))
176 exposure *= exposval(s);
177 else if (isformat(s)) {
178 formatval(fmt, s);
179 wrongformat = strcmp(fmt, COLRFMT);
180 } else
181 for (an = altname; *an != NULL; an++)
182 if (!strncmp(*an, s, strlen(*an))) {
183 if (sscanview(&ourview, s+strlen(*an)) > 0)
184 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 getras();
216
217 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 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 quiterr("out of memory");
297 }
298
299
300 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 unmap_rcolors(ourras);
320 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 if (ourras->ncolors && map_rcolors(ourras) == NULL) {
343 fprintf(stderr, "%s: cannot allocate colors\n", progname);
344 return(-1);
345 }
346 if (fast)
347 make_rpixmap(ourras);
348 return(patch_raster(wind,x-xoff,y-yoff,x,y,w,h,ourras) ? 0 : -1);
349 }
350
351
352 docom(ekey) /* execute command */
353 XKeyEvent *ekey;
354 {
355 char buf[80];
356 COLOR cval;
357 Color cvx;
358 char *cp;
359 int n;
360 double comp;
361 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 case CTRL(D): /* quit */
369 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 sprintf(buf, "%.3f", intens(cval)/exposure);
380 break;
381 case 'l': /* luminance */
382 sprintf(buf, "%.0fL", luminance(cval)/exposure);
383 break;
384 case 'c': /* color */
385 comp = pow(2.0, (double)scale);
386 sprintf(buf, "(%.2f,%.2f,%.2f)",
387 colval(cval,RED)*comp,
388 colval(cval,GRN)*comp,
389 colval(cval,BLU)*comp);
390 break;
391 }
392 XText(wind, box.xmin, box.ymin, buf, strlen(buf),
393 fontid, BlackPixel, WhitePixel);
394 return(0);
395 case 'i': /* identify (contour) */
396 if (ourras->pixels == NULL)
397 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 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 if (viewray(rorg, rdir, &ourview, (ekey->x-xoff+.5)/xmax,
417 (ymax-1-ekey->y+yoff+.5)/ymax) < 0)
418 return(-1);
419 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 case '=': /* adjust exposure */
424 if (avgbox(cval) == -1)
425 return(-1);
426 n = log(.5/bright(cval))/.69315 - scale; /* truncate */
427 if (n == 0)
428 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 /* fall through */
438 case CTRL(R): /* redraw */
439 case CTRL(L):
440 unmap_rcolors(ourras);
441 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 rgbpixel *inl;
553 short *cerr;
554
555 if ((inl = (rgbpixel *)malloc(xmax*sizeof(rgbpixel))) == NULL
556 || (cerr = (short *)calloc(xmax,sizeof(short))) == NULL)
557 quiterr("out of memory in getmono");
558 dp = ourras->data.m - 1;
559 for (y = 0; y < ymax; y++) {
560 picreadline3(y, inl);
561 err = 0;
562 for (x = 0; x < xmax; x++) {
563 if (!(x&0xf))
564 *++dp = 0;
565 err += rgb_bright(&inl[x]) + cerr[x];
566 if (err > 127)
567 err -= 255;
568 else
569 *dp |= 1<<(x&0xf);
570 cerr[x] = err >>= 1;
571 }
572 }
573 free((char *)inl);
574 free((char *)cerr);
575 }
576
577
578 init_rcolors(xr, cmap) /* (re)assign color values */
579 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 scale_rcolors(xr, sf) /* scale color map */
610 register XRASTER *xr;
611 double sf;
612 {
613 register int i;
614 long maxv;
615
616 if (xr->pixels == NULL)
617 return;
618
619 sf = pow(sf, 1.0/gamcor);
620 maxv = 65535/sf;
621
622 for (i = xr->ncolors; i--; ) {
623 xr->cdefs[i].red = xr->cdefs[i].red > maxv ?
624 65535 :
625 xr->cdefs[i].red * sf;
626 xr->cdefs[i].green = xr->cdefs[i].green > maxv ?
627 65535 :
628 xr->cdefs[i].green * sf;
629 xr->cdefs[i].blue = xr->cdefs[i].blue > maxv ?
630 65535 :
631 xr->cdefs[i].blue * sf;
632 }
633 XStoreColors(xr->ncolors, xr->cdefs);
634 }
635
636
637 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 quiterr("fseek error");
645 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 register int i;
662 /* read scanline */
663 if (getscan(y) < 0)
664 quiterr("cannot seek for picreadline");
665 /* convert scanline */
666 normcolrs(scanline, xmax, scale);
667 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 }
672 }
673
674
675 picwriteline(y, l) /* add 8-bit scanline to image */
676 int y;
677 pixel *l;
678 {
679 bcopy((char *)l, (char *)ourras->data.bz+BZPixmapSize(xmax,y), BZPixmapSize(xmax,1));
680 }
681
682
683 picreadcm(map) /* do gamma correction */
684 colormap map;
685 {
686 extern double pow();
687 register int i, val;
688
689 for (i = 0; i < 256; i++) {
690 val = pow((i+0.5)/256.0, 1.0/gamcor) * 256.0;
691 map[0][i] = map[1][i] = map[2][i] = val;
692 }
693 }
694
695
696 picwritecm(map) /* handled elsewhere */
697 colormap map;
698 {
699 #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 }