ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ximage.c
Revision: 1.13
Committed: Mon Oct 23 09:10:22 1989 UTC (34 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.12: +4 -2 lines
Log Message:
undid change at 1.10 which introduced bug

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