ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/ximage.c
Revision: 1.1
Committed: Thu Feb 2 10:49:43 1989 UTC (35 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

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