ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/x11image.c
Revision: 2.9
Committed: Sat May 30 09:33:01 1992 UTC (31 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.8: +8 -3 lines
Log Message:
small improvement in white&black color assignments

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