ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/x11image.c
Revision: 2.8
Committed: Fri May 29 14:21:12 1992 UTC (31 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.7: +13 -4 lines
Log Message:
fixed text color on 24-bit displays

File Contents

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