ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/x11image.c
Revision: 2.13
Committed: Mon Oct 12 12:59:22 1992 UTC (31 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.12: +50 -71 lines
Log Message:
converted to color quantization routines in clrtab.c

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