ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/x11image.c
Revision: 2.11
Committed: Fri Aug 21 13:49:30 1992 UTC (31 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.10: +1 -1 lines
Log Message:
made getscan() slightly more efficient

File Contents

# Content
1 /* Copyright (c) 1992 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * x11image.c - driver for X-windows
9 *
10 * 3/1/90
11 */
12
13 /*
14 * Modified for X11
15 *
16 * January 1990
17 *
18 * Anat Grynberg and Greg Ward
19 */
20
21
22 #include "standard.h"
23
24 #include <X11/Xlib.h>
25 #include <X11/cursorfont.h>
26 #include <X11/Xutil.h>
27
28 #include "color.h"
29 #include "view.h"
30 #include "pic.h"
31 #include "x11raster.h"
32 #include "random.h"
33 #include "resolu.h"
34
35 #define FONTNAME "8x13" /* text font we'll use */
36
37 #define CTRL(c) ((c)-'@')
38
39 #define BORWIDTH 5 /* border width */
40
41 #define ICONSIZ (8*10) /* maximum icon dimension (even 8) */
42
43 #define ourscreen DefaultScreen(thedisplay)
44 #define ourroot RootWindow(thedisplay,ourscreen)
45
46 #define revline(x0,y0,x1,y1) XDrawLine(thedisplay,wind,revgc,x0,y0,x1,y1)
47
48 #define redraw(x,y,w,h) patch_raster(wind,(x)-xoff,(y)-yoff,x,y,w,h,ourras)
49
50 double gamcor = 2.2; /* gamma correction */
51
52 int dither = 1; /* dither colors? */
53 int fast = 0; /* keep picture in Pixmap? */
54
55 char *dispname = NULL; /* our display name */
56
57 Window wind = 0; /* our output window */
58 unsigned long ourblack=0, ourwhite=1; /* black and white for this visual */
59 Font fontid; /* our font */
60
61 int maxcolors = 0; /* maximum colors */
62 int greyscale = 0; /* in grey */
63
64 int scale = 0; /* scalefactor; power of two */
65
66 int xoff = 0; /* x image offset */
67 int yoff = 0; /* y image offset */
68
69 VIEW ourview = STDVIEW; /* image view parameters */
70 int gotview = 0; /* got parameters from file */
71
72 COLR *scanline; /* scan line buffer */
73
74 RESOLU inpres; /* input resolution and ordering */
75 int xmax, ymax; /* picture dimensions */
76 int width, height; /* window size */
77 char *fname = NULL; /* input file name */
78 FILE *fin = stdin; /* input file */
79 long *scanpos = NULL; /* scan line positions in file */
80 int cury = 0; /* current scan location */
81
82 double exposure = 1.0; /* exposure compensation used */
83
84 int wrongformat = 0; /* input in another format? */
85
86 GC ourgc; /* standard graphics context */
87 GC revgc; /* graphics context with GXinvert */
88
89 int *ourrank; /* our visual class ranking */
90 XVisualInfo ourvis; /* our visual */
91 XRASTER *ourras; /* our stored image */
92 unsigned char *ourdata; /* our image data */
93
94 struct {
95 int xmin, ymin, xsiz, ysiz;
96 } box = {0, 0, 0, 0}; /* current box */
97
98 char *geometry = NULL; /* geometry specification */
99
100 char icondata[ICONSIZ*ICONSIZ/8]; /* icon bitmap data */
101 int iconwidth = 0, iconheight = 0;
102
103 char *progname;
104
105 char errmsg[128];
106
107 extern long ftell();
108
109 extern char *malloc(), *calloc();
110
111 extern double pow(), log();
112
113 Display *thedisplay;
114
115 main(argc, argv)
116 int argc;
117 char *argv[];
118 {
119 extern char *getenv();
120 char *gv;
121 int headline();
122 int i;
123
124 progname = argv[0];
125 if ((gv = getenv("GAMMA")) != NULL)
126 gamcor = atof(gv);
127
128 for (i = 1; i < argc; i++)
129 if (argv[i][0] == '-')
130 switch (argv[i][1]) {
131 case 'c':
132 maxcolors = atoi(argv[++i]);
133 break;
134 case 'b':
135 greyscale = !greyscale;
136 break;
137 case 'm':
138 maxcolors = 2;
139 break;
140 case 'd':
141 if (argv[i][2] == 'i')
142 dispname = argv[++i];
143 else
144 dither = !dither;
145 break;
146 case 'f':
147 fast = !fast;
148 break;
149 case 'e':
150 if (argv[i+1][0] != '+' && argv[i+1][0] != '-')
151 goto userr;
152 scale = atoi(argv[++i]);
153 break;
154 case 'g':
155 if (argv[i][2] == 'e')
156 geometry = argv[++i];
157 else
158 gamcor = atof(argv[++i]);
159 break;
160 default:
161 goto userr;
162 }
163 else if (argv[i][0] == '=')
164 geometry = argv[i];
165 else
166 break;
167
168 if (i == argc-1) {
169 fname = argv[i];
170 fin = fopen(fname, "r");
171 if (fin == NULL) {
172 sprintf(errmsg, "cannot open file \"%s\"", fname);
173 quiterr(errmsg);
174 }
175 } else if (i != argc)
176 goto userr;
177 /* get header */
178 getheader(fin, headline, NULL);
179 /* get picture dimensions */
180 if (wrongformat || !fgetsresolu(&inpres, fin))
181 quiterr("bad picture format");
182 xmax = scanlen(&inpres);
183 ymax = numscans(&inpres);
184 /* set view parameters */
185 if (gotview && setview(&ourview) != NULL)
186 gotview = 0;
187 if ((scanline = (COLR *)malloc(xmax*sizeof(COLR))) == NULL)
188 quiterr("out of memory");
189
190 init(); /* get file and open window */
191
192 for ( ; ; )
193 getevent(); /* main loop */
194 userr:
195 fprintf(stderr,
196 "Usage: %s [-display disp][-geometry spec][-b][-m][-d][-f][-c ncolors][-e +/-stops] file\n",
197 progname);
198 quit(1);
199 }
200
201
202 headline(s) /* get relevant info from header */
203 char *s;
204 {
205 char fmt[32];
206
207 if (isexpos(s))
208 exposure *= exposval(s);
209 else if (isformat(s)) {
210 formatval(fmt, s);
211 wrongformat = strcmp(fmt, COLRFMT);
212 } else if (isview(s) && sscanview(&ourview, s) > 0)
213 gotview++;
214 }
215
216
217 init() /* get data and open window */
218 {
219 XWMHints ourxwmhints;
220 XSetWindowAttributes ourwinattr;
221 XSizeHints oursizhints;
222 register int i;
223
224 if (fname != NULL) {
225 scanpos = (long *)malloc(ymax*sizeof(long));
226 if (scanpos == NULL)
227 goto memerr;
228 for (i = 0; i < ymax; i++)
229 scanpos[i] = -1;
230 }
231 if ((thedisplay = XOpenDisplay(dispname)) == NULL)
232 quiterr("cannot open display");
233 /* get best visual for default screen */
234 getbestvis();
235 /* store image */
236 getras();
237 /* open window */
238 ourwinattr.border_pixel = ourblack;
239 ourwinattr.background_pixel = ourwhite;
240 ourwinattr.colormap = XCreateColormap(thedisplay, ourroot,
241 ourvis.visual, AllocNone);
242 wind = XCreateWindow(thedisplay, ourroot, 0, 0, xmax, ymax, BORWIDTH,
243 ourvis.depth, InputOutput, ourvis.visual,
244 CWBackPixel|CWBorderPixel|CWColormap, &ourwinattr);
245 if (wind == 0)
246 quiterr("cannot create window");
247 XFreeColormap(thedisplay, ourwinattr.colormap);
248 width = xmax;
249 height = ymax;
250 ourgc = XCreateGC(thedisplay, wind, 0, 0);
251 XSetState(thedisplay, ourgc, ourblack, ourwhite, GXcopy, AllPlanes);
252 revgc = XCreateGC(thedisplay, wind, 0, 0);
253 XSetFunction(thedisplay, revgc, GXinvert);
254 fontid = XLoadFont(thedisplay, FONTNAME);
255 if (fontid == 0)
256 quiterr("cannot get font");
257 XSetFont(thedisplay, ourgc, fontid);
258 XDefineCursor(thedisplay, wind, XCreateFontCursor(thedisplay,
259 XC_diamond_cross));
260 XStoreName(thedisplay, wind, fname == NULL ? progname : fname);
261 if (geometry != NULL) {
262 bzero((char *)&oursizhints, sizeof(oursizhints));
263 i = XParseGeometry(geometry, &oursizhints.x, &oursizhints.y,
264 (unsigned *)&oursizhints.width,
265 (unsigned *)&oursizhints.height);
266 if ((i&(WidthValue|HeightValue)) == (WidthValue|HeightValue))
267 oursizhints.flags |= USSize;
268 else {
269 oursizhints.width = xmax;
270 oursizhints.height = ymax;
271 oursizhints.flags |= PSize;
272 }
273 if ((i&(XValue|YValue)) == (XValue|YValue)) {
274 oursizhints.flags |= USPosition;
275 if (i & XNegative)
276 oursizhints.x += DisplayWidth(thedisplay,
277 ourscreen)-1-oursizhints.width-2*BORWIDTH;
278 if (i & YNegative)
279 oursizhints.y += DisplayHeight(thedisplay,
280 ourscreen)-1-oursizhints.height-2*BORWIDTH;
281 }
282 XSetNormalHints(thedisplay, wind, &oursizhints);
283 }
284 ourxwmhints.flags = InputHint|IconPixmapHint;
285 ourxwmhints.input = True;
286 ourxwmhints.icon_pixmap = XCreateBitmapFromData(thedisplay,
287 wind, icondata, iconwidth, iconheight);
288 XSetWMHints(thedisplay, wind, &ourxwmhints);
289 XSelectInput(thedisplay, wind, ButtonPressMask|ButtonReleaseMask
290 |ButtonMotionMask|StructureNotifyMask
291 |KeyPressMask|ExposureMask);
292 XMapWindow(thedisplay, wind);
293 return;
294 memerr:
295 quiterr("out of memory");
296 } /* end of init */
297
298
299 quiterr(err) /* print message and exit */
300 char *err;
301 {
302 if (err != NULL) {
303 fprintf(stderr, "%s: %s\n", progname, err);
304 exit(1);
305 }
306 exit(0);
307 }
308
309
310 eputs(s)
311 char *s;
312 {
313 fputs(s, stderr);
314 }
315
316
317 quit(code)
318 int code;
319 {
320 exit(code);
321 }
322
323
324 static int
325 viscmp(v1,v2) /* compare visual to see which is better, descending */
326 register XVisualInfo *v1, *v2;
327 {
328 int bad1 = 0, bad2 = 0;
329 register int *rp;
330
331 if (v1->class == v2->class) {
332 if (v1->class == TrueColor || v1->class == DirectColor) {
333 /* prefer 24-bit to 32-bit */
334 if (v1->depth == 24 && v2->depth == 32)
335 return(-1);
336 if (v1->depth == 32 && v2->depth == 24)
337 return(1);
338 return(0);
339 }
340 /* don't be too greedy */
341 if (maxcolors <= 1<<v1->depth && maxcolors <= 1<<v2->depth)
342 return(v1->depth - v2->depth);
343 return(v2->depth - v1->depth);
344 }
345 /* prefer Pseudo when < 24-bit */
346 if ((v1->class == TrueColor || v1->class == DirectColor) &&
347 v1->depth < 24)
348 bad1 = 1;
349 if ((v2->class == TrueColor || v2->class == DirectColor) &&
350 v2->depth < 24)
351 bad2 = -1;
352 if (bad1 | bad2)
353 return(bad1+bad2);
354 /* otherwise, use class ranking */
355 for (rp = ourrank; *rp != -1; rp++) {
356 if (v1->class == *rp)
357 return(-1);
358 if (v2->class == *rp)
359 return(1);
360 }
361 return(0);
362 }
363
364
365 getbestvis() /* get the best visual for this screen */
366 {
367 #ifdef DEBUG
368 static char vistype[][12] = {
369 "StaticGray",
370 "GrayScale",
371 "StaticColor",
372 "PseudoColor",
373 "TrueColor",
374 "DirectColor"
375 };
376 #endif
377 static int rankings[3][6] = {
378 {TrueColor,DirectColor,PseudoColor,GrayScale,StaticGray,-1},
379 {PseudoColor,GrayScale,StaticGray,-1},
380 {PseudoColor,GrayScale,StaticGray,-1}
381 };
382 XVisualInfo *xvi;
383 int vismatched;
384 register int i, j;
385
386 if (greyscale) {
387 ourrank = rankings[2];
388 if (maxcolors < 2) maxcolors = 256;
389 } else if (maxcolors >= 2 && maxcolors <= 256)
390 ourrank = rankings[1];
391 else {
392 ourrank = rankings[0];
393 maxcolors = 256;
394 }
395 /* find best visual */
396 ourvis.screen = ourscreen;
397 xvi = XGetVisualInfo(thedisplay,VisualScreenMask,&ourvis,&vismatched);
398 if (xvi == NULL)
399 quiterr("no visuals for this screen!");
400 #ifdef DEBUG
401 fprintf(stderr, "Supported visuals:\n");
402 for (i = 0; i < vismatched; i++)
403 fprintf(stderr, "\ttype %s, depth %d\n",
404 vistype[xvi[i].class], xvi[i].depth);
405 #endif
406 for (i = 0, j = 1; j < vismatched; j++)
407 if (viscmp(&xvi[i],&xvi[j]) > 0)
408 i = j;
409 /* compare to least acceptable */
410 for (j = 0; ourrank[j++] != -1; )
411 ;
412 ourvis.class = ourrank[--j];
413 ourvis.depth = 1;
414 if (viscmp(&xvi[i],&ourvis) > 0)
415 quiterr("inadequate visuals on this screen");
416 /* OK, we'll use it */
417 copystruct(&ourvis, &xvi[i]);
418 #ifdef DEBUG
419 fprintf(stderr, "Selected visual type %s, depth %d\n",
420 vistype[ourvis.class], ourvis.depth);
421 #endif
422 /* make appropriate adjustments */
423 if (ourvis.class == GrayScale || ourvis.class == StaticGray)
424 greyscale = 1;
425 if (ourvis.depth <= 8 && ourvis.colormap_size < maxcolors)
426 maxcolors = ourvis.colormap_size;
427 if (maxcolors > 4)
428 maxcolors -= 2;
429 if (ourvis.class == StaticGray) {
430 ourblack = 0;
431 ourwhite = 255;
432 } else if (ourvis.class == PseudoColor) {
433 ourblack = BlackPixel(thedisplay,ourscreen);
434 ourwhite = WhitePixel(thedisplay,ourscreen);
435 if ((ourblack|ourwhite) & ~255L) {
436 ourblack = 0;
437 ourwhite = 1;
438 }
439 } else {
440 ourblack = 0;
441 ourwhite = ourvis.red_mask|ourvis.green_mask|ourvis.blue_mask;
442 }
443 XFree((char *)xvi);
444 }
445
446
447 getras() /* get raster file */
448 {
449 colormap ourmap;
450 XVisualInfo vinfo;
451
452 if (maxcolors <= 2) { /* monochrome */
453 ourdata = (unsigned char *)malloc(ymax*((xmax+7)/8));
454 if (ourdata == NULL)
455 goto fail;
456 ourras = make_raster(thedisplay, &ourvis, 1, ourdata,
457 xmax, ymax, 8);
458 if (ourras == NULL)
459 goto fail;
460 getmono();
461 } else if (ourvis.class == TrueColor || ourvis.class == DirectColor) {
462 ourdata = (unsigned char *)malloc(4*xmax*ymax);
463 if (ourdata == NULL)
464 goto fail;
465 ourras = make_raster(thedisplay, &ourvis, 32,
466 ourdata, xmax, ymax, 32);
467 if (ourras == NULL)
468 goto fail;
469 getfull();
470 } else {
471 ourdata = (unsigned char *)malloc(xmax*ymax);
472 if (ourdata == NULL)
473 goto fail;
474 ourras = make_raster(thedisplay, &ourvis, 8, ourdata,
475 xmax, ymax, 8);
476 if (ourras == NULL)
477 goto fail;
478 if (ourvis.class == StaticGray)
479 getgrey();
480 else {
481 if (greyscale)
482 biq(dither,maxcolors,1,ourmap);
483 else
484 ciq(dither,maxcolors,1,ourmap);
485 if (init_rcolors(ourras, ourmap[0],
486 ourmap[1], ourmap[2]) == 0)
487 goto fail;
488 }
489 }
490 return;
491 fail:
492 quiterr("could not create raster image");
493 }
494
495
496 getevent() /* process the next event */
497 {
498 union {
499 XEvent u;
500 XConfigureEvent c;
501 XExposeEvent e;
502 XButtonPressedEvent b;
503 XKeyPressedEvent k;
504 } e;
505
506 XNextEvent(thedisplay, &e.u);
507 switch (e.u.type) {
508 case KeyPress:
509 docom(&e.k);
510 break;
511 case ConfigureNotify:
512 width = e.c.width;
513 height = e.c.height;
514 break;
515 case MapNotify:
516 map_rcolors(ourras, wind);
517 if (fast)
518 make_rpixmap(ourras, wind);
519 break;
520 case UnmapNotify:
521 if (!fast)
522 unmap_rcolors(ourras);
523 break;
524 case Expose:
525 redraw(e.e.x, e.e.y, e.e.width, e.e.height);
526 break;
527 case ButtonPress:
528 if (e.b.state & (ShiftMask|ControlMask))
529 moveimage(&e.b);
530 else
531 getbox(&e.b);
532 break;
533 }
534 }
535
536
537 docom(ekey) /* execute command */
538 XKeyPressedEvent *ekey;
539 {
540 char buf[80];
541 COLOR cval;
542 XColor cvx;
543 int com, n;
544 double comp;
545 FLOAT hv[2];
546 FVECT rorg, rdir;
547
548 n = XLookupString(ekey, buf, sizeof(buf), NULL, NULL);
549 if (n == 0)
550 return(0);
551 com = buf[0];
552 switch (com) { /* interpret command */
553 case 'q':
554 case CTRL('D'): /* quit */
555 quit(0);
556 case '\n':
557 case '\r':
558 case 'l':
559 case 'c': /* value */
560 if (avgbox(cval) == -1)
561 return(-1);
562 switch (com) {
563 case '\n':
564 case '\r': /* radiance */
565 sprintf(buf, "%.3f", intens(cval)/exposure);
566 break;
567 case 'l': /* luminance */
568 sprintf(buf, "%.0fL", luminance(cval)/exposure);
569 break;
570 case 'c': /* color */
571 comp = pow(2.0, (double)scale);
572 sprintf(buf, "(%.2f,%.2f,%.2f)",
573 colval(cval,RED)*comp,
574 colval(cval,GRN)*comp,
575 colval(cval,BLU)*comp);
576 break;
577 }
578 XDrawImageString(thedisplay, wind, ourgc,
579 box.xmin, box.ymin+box.ysiz, buf, strlen(buf));
580 return(0);
581 case 'i': /* identify (contour) */
582 if (ourras->pixels == NULL)
583 return(-1);
584 n = ourdata[ekey->x-xoff+xmax*(ekey->y-yoff)];
585 n = ourras->pmap[n];
586 cvx.pixel = ourras->cdefs[n].pixel;
587 cvx.red = random() & 65535;
588 cvx.green = random() & 65535;
589 cvx.blue = random() & 65535;
590 cvx.flags = DoRed|DoGreen|DoBlue;
591 XStoreColor(thedisplay, ourras->cmap, &cvx);
592 return(0);
593 case 'p': /* position */
594 pix2loc(hv, &inpres, ekey->x-xoff, ekey->y-yoff);
595 sprintf(buf, "(%d,%d)", (int)(hv[0]*inpres.xr),
596 (int)(hv[1]*inpres.yr));
597 XDrawImageString(thedisplay, wind, ourgc, ekey->x, ekey->y,
598 buf, strlen(buf));
599 return(0);
600 case 't': /* trace */
601 if (!gotview) {
602 XBell(thedisplay, 0);
603 return(-1);
604 }
605 pix2loc(hv, &inpres, ekey->x-xoff, ekey->y-yoff);
606 if (viewray(rorg, rdir, &ourview, hv[0], hv[1]) < 0)
607 return(-1);
608 printf("%e %e %e ", rorg[0], rorg[1], rorg[2]);
609 printf("%e %e %e\n", rdir[0], rdir[1], rdir[2]);
610 fflush(stdout);
611 return(0);
612 case '=': /* adjust exposure */
613 if (avgbox(cval) == -1)
614 return(-1);
615 n = log(.5/bright(cval))/.69315 - scale; /* truncate */
616 if (n == 0)
617 return(0);
618 scale_rcolors(ourras, pow(2.0, (double)n));
619 scale += n;
620 sprintf(buf, "%+d", scale);
621 XDrawImageString(thedisplay, wind, ourgc,
622 box.xmin, box.ymin+box.ysiz, buf, strlen(buf));
623 XFlush(thedisplay);
624 free(ourdata);
625 free_raster(ourras);
626 getras();
627 /* fall through */
628 case CTRL('R'): /* redraw */
629 case CTRL('L'):
630 unmap_rcolors(ourras);
631 XClearWindow(thedisplay, wind);
632 map_rcolors(ourras, wind);
633 if (fast)
634 make_rpixmap(ourras);
635 redraw(0, 0, width, height);
636 return(0);
637 case ' ': /* clear */
638 redraw(box.xmin, box.ymin, box.xsiz, box.ysiz);
639 return(0);
640 default:
641 XBell(thedisplay, 0);
642 return(-1);
643 }
644 }
645
646
647 moveimage(ebut) /* shift the image */
648 XButtonPressedEvent *ebut;
649 {
650 union {
651 XEvent u;
652 XButtonReleasedEvent b;
653 XPointerMovedEvent m;
654 } e;
655 int mxo, myo;
656
657 XMaskEvent(thedisplay, ButtonReleaseMask|ButtonMotionMask, &e.u);
658 while (e.u.type == MotionNotify) {
659 mxo = e.m.x;
660 myo = e.m.y;
661 revline(ebut->x, ebut->y, mxo, myo);
662 revbox(xoff+mxo-ebut->x, yoff+myo-ebut->y,
663 xoff+mxo-ebut->x+xmax, yoff+myo-ebut->y+ymax);
664 XMaskEvent(thedisplay,ButtonReleaseMask|ButtonMotionMask,&e.u);
665 revline(ebut->x, ebut->y, mxo, myo);
666 revbox(xoff+mxo-ebut->x, yoff+myo-ebut->y,
667 xoff+mxo-ebut->x+xmax, yoff+myo-ebut->y+ymax);
668 }
669 xoff += e.b.x - ebut->x;
670 yoff += e.b.y - ebut->y;
671 XClearWindow(thedisplay, wind);
672 redraw(0, 0, width, height);
673 }
674
675
676 getbox(ebut) /* get new box */
677 XButtonPressedEvent *ebut;
678 {
679 union {
680 XEvent u;
681 XButtonReleasedEvent b;
682 XPointerMovedEvent m;
683 } e;
684
685 XMaskEvent(thedisplay, ButtonReleaseMask|ButtonMotionMask, &e.u);
686 while (e.u.type == MotionNotify) {
687 revbox(ebut->x, ebut->y, box.xmin = e.m.x, box.ymin = e.m.y);
688 XMaskEvent(thedisplay,ButtonReleaseMask|ButtonMotionMask,&e.u);
689 revbox(ebut->x, ebut->y, box.xmin, box.ymin);
690 }
691 box.xmin = e.b.x<0 ? 0 : (e.b.x>=width ? width-1 : e.b.x);
692 box.ymin = e.b.y<0 ? 0 : (e.b.y>=height ? height-1 : e.b.y);
693 if (box.xmin > ebut->x) {
694 box.xsiz = box.xmin - ebut->x + 1;
695 box.xmin = ebut->x;
696 } else {
697 box.xsiz = ebut->x - box.xmin + 1;
698 }
699 if (box.ymin > ebut->y) {
700 box.ysiz = box.ymin - ebut->y + 1;
701 box.ymin = ebut->y;
702 } else {
703 box.ysiz = ebut->y - box.ymin + 1;
704 }
705 }
706
707
708 revbox(x0, y0, x1, y1) /* draw box with reversed lines */
709 int x0, y0, x1, y1;
710 {
711 revline(x0, y0, x1, y0);
712 revline(x0, y1, x1, y1);
713 revline(x0, y0, x0, y1);
714 revline(x1, y0, x1, y1);
715 }
716
717
718 avgbox(clr) /* average color over current box */
719 COLOR clr;
720 {
721 static COLOR lc;
722 static int ll, lr, lt, lb;
723 int left, right, top, bottom;
724 int y;
725 double d;
726 COLOR ctmp;
727 register int x;
728
729 setcolor(clr, 0.0, 0.0, 0.0);
730 left = box.xmin - xoff;
731 right = left + box.xsiz;
732 if (left < 0)
733 left = 0;
734 if (right > xmax)
735 right = xmax;
736 if (left >= right)
737 return(-1);
738 top = box.ymin - yoff;
739 bottom = top + box.ysiz;
740 if (top < 0)
741 top = 0;
742 if (bottom > ymax)
743 bottom = ymax;
744 if (top >= bottom)
745 return(-1);
746 if (left == ll && right == lr && top == lt && bottom == lb) {
747 copycolor(clr, lc);
748 return;
749 }
750 for (y = top; y < bottom; y++) {
751 if (getscan(y) == -1)
752 return(-1);
753 for (x = left; x < right; x++) {
754 colr_color(ctmp, scanline[x]);
755 addcolor(clr, ctmp);
756 }
757 }
758 d = 1.0/((right-left)*(bottom-top));
759 scalecolor(clr, d);
760 ll = left; lr = right; lt = top; lb = bottom;
761 copycolor(lc, clr);
762 return(0);
763 }
764
765
766 getmono() /* get monochrome data */
767 {
768 register unsigned char *dp;
769 register int x, err;
770 int y, errp;
771 short *cerr;
772
773 if ((cerr = (short *)calloc(xmax,sizeof(short))) == NULL)
774 quiterr("out of memory in getmono");
775 dp = ourdata - 1;
776 for (y = 0; y < ymax; y++) {
777 if (getscan(y) < 0)
778 quiterr("seek error in getmono");
779 normcolrs(scanline, xmax, scale);
780 add2icon(y, scanline);
781 err = 0;
782 for (x = 0; x < xmax; x++) {
783 if (!(x&7))
784 *++dp = 0;
785 errp = err;
786 err += normbright(scanline[x]) + cerr[x];
787 if (err > 127)
788 err -= 255;
789 else
790 *dp |= 1<<(7-(x&07));
791 err /= 3;
792 cerr[x] = err + errp;
793 }
794 }
795 free((char *)cerr);
796 }
797
798
799 add2icon(y, scan) /* add a scanline to our icon data */
800 int y;
801 COLR *scan;
802 {
803 static short cerr[ICONSIZ];
804 static int ynext;
805 static char *dp;
806 register int err;
807 register int x, ti;
808 int errp;
809
810 if (iconheight == 0) { /* initialize */
811 if (xmax <= ICONSIZ && ymax <= ICONSIZ) {
812 iconwidth = xmax;
813 iconheight = ymax;
814 } else if (xmax > ymax) {
815 iconwidth = ICONSIZ;
816 iconheight = ICONSIZ*ymax/xmax;
817 if (iconheight < 1)
818 iconheight = 1;
819 } else {
820 iconwidth = ICONSIZ*xmax/ymax;
821 if (iconwidth < 1)
822 iconwidth = 1;
823 iconheight = ICONSIZ;
824 }
825 ynext = 0;
826 dp = icondata - 1;
827 }
828 if (y < ynext*ymax/iconheight) /* skip this one */
829 return;
830 err = 0;
831 for (x = 0; x < iconwidth; x++) {
832 if (!(x&7))
833 *++dp = 0;
834 errp = err;
835 ti = x*xmax/iconwidth;
836 err += normbright(scan[ti]) + cerr[x];
837 if (err > 127)
838 err -= 255;
839 else
840 *dp |= 1<<(x&07);
841 err /= 3;
842 cerr[x] = err + errp;
843 }
844 ynext++;
845 }
846
847
848 getfull() /* get full (24-bit) data */
849 {
850 int y;
851 register unsigned long *dp;
852 register int x;
853 /* set gamma correction */
854 setcolrgam(gamcor);
855 /* read and convert file */
856 dp = (unsigned long *)ourdata;
857 for (y = 0; y < ymax; y++) {
858 if (getscan(y) < 0)
859 quiterr("seek error in getfull");
860 if (scale)
861 shiftcolrs(scanline, xmax, scale);
862 colrs_gambs(scanline, xmax);
863 add2icon(y, scanline);
864 if (ourras->image->blue_mask & 1)
865 for (x = 0; x < xmax; x++)
866 *dp++ = scanline[x][RED] << 16 |
867 scanline[x][GRN] << 8 |
868 scanline[x][BLU] ;
869 else
870 for (x = 0; x < xmax; x++)
871 *dp++ = scanline[x][RED] |
872 scanline[x][GRN] << 8 |
873 scanline[x][BLU] << 16 ;
874 }
875 }
876
877
878 getgrey() /* get greyscale data */
879 {
880 int y;
881 register unsigned char *dp;
882 register int x;
883 /* set gamma correction */
884 setcolrgam(gamcor);
885 /* read and convert file */
886 dp = ourdata;
887 for (y = 0; y < ymax; y++) {
888 if (getscan(y) < 0)
889 quiterr("seek error in getfull");
890 if (scale)
891 shiftcolrs(scanline, xmax, scale);
892 colrs_gambs(scanline, xmax);
893 add2icon(y, scanline);
894 if (ourvis.colormap_size < 256)
895 for (x = 0; x < xmax; x++)
896 *dp++ = ((long)normbright(scanline[x]) *
897 ourvis.colormap_size + 128) >> 8;
898 else
899 for (x = 0; x < xmax; x++)
900 *dp++ = normbright(scanline[x]);
901 }
902 }
903
904
905 scale_rcolors(xr, sf) /* scale color map */
906 register XRASTER *xr;
907 double sf;
908 {
909 register int i;
910 long maxv;
911
912 if (xr->pixels == NULL)
913 return;
914
915 sf = pow(sf, 1.0/gamcor);
916 maxv = 65535/sf;
917
918 for (i = xr->ncolors; i--; ) {
919 xr->cdefs[i].red = xr->cdefs[i].red > maxv ?
920 65535 :
921 xr->cdefs[i].red * sf;
922 xr->cdefs[i].green = xr->cdefs[i].green > maxv ?
923 65535 :
924 xr->cdefs[i].green * sf;
925 xr->cdefs[i].blue = xr->cdefs[i].blue > maxv ?
926 65535 :
927 xr->cdefs[i].blue * sf;
928 }
929 XStoreColors(thedisplay, xr->cmap, xr->cdefs, xr->ncolors);
930 }
931
932
933 getscan(y)
934 int y;
935 {
936 if (y != cury) {
937 if (scanpos == NULL || scanpos[y] == -1)
938 return(-1);
939 if (fseek(fin, scanpos[y], 0) == -1)
940 quiterr("fseek error");
941 cury = y;
942 } else if (scanpos != NULL && scanpos[y] == -1)
943 scanpos[y] = ftell(fin);
944
945 if (freadcolrs(scanline, xmax, fin) < 0)
946 quiterr("read error");
947
948 cury++;
949 return(0);
950 }
951
952
953 picreadline3(y, l3) /* read in 3-byte scanline */
954 int y;
955 register rgbpixel *l3;
956 {
957 register int i;
958 /* read scanline */
959 if (getscan(y) < 0)
960 quiterr("cannot seek for picreadline");
961 /* convert scanline */
962 normcolrs(scanline, xmax, scale);
963 add2icon(y, scanline);
964 for (i = 0; i < xmax; i++) {
965 l3[i].r = scanline[i][RED];
966 l3[i].g = scanline[i][GRN];
967 l3[i].b = scanline[i][BLU];
968 }
969 }
970
971
972 picwriteline(y, l) /* add 8-bit scanline to image */
973 int y;
974 pixel *l;
975 {
976 bcopy((char *)l, (char *)ourdata+y*xmax, xmax);
977 }
978
979
980 picreadcm(map) /* do gamma correction */
981 colormap map;
982 {
983 extern double pow();
984 register int i, val;
985
986 for (i = 0; i < 256; i++) {
987 val = pow((i+0.5)/256.0, 1.0/gamcor) * 256.0;
988 map[0][i] = map[1][i] = map[2][i] = val;
989 }
990 }
991
992
993 picwritecm(map) /* handled elsewhere */
994 colormap map;
995 {
996 #if 0
997 register int i;
998
999 for (i = 0; i < 256; i++)
1000 printf("%d %d %d\n", map[0][i],map[1][i],map[2][i]);
1001 #endif
1002 }