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

# User Rev Content
1 greg 2.9 /* Copyright (c) 1992 Regents of the University of California */
2 greg 1.1
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 greg 1.26 #include "resolu.h"
34 greg 1.1
35     #define FONTNAME "8x13" /* text font we'll use */
36    
37 greg 2.3 #define CTRL(c) ((c)-'@')
38 greg 1.1
39     #define BORWIDTH 5 /* border width */
40    
41 greg 1.18 #define ICONSIZ (8*10) /* maximum icon dimension (even 8) */
42 greg 1.17
43 greg 1.1 #define ourscreen DefaultScreen(thedisplay)
44     #define ourroot RootWindow(thedisplay,ourscreen)
45    
46 greg 1.5 #define revline(x0,y0,x1,y1) XDrawLine(thedisplay,wind,revgc,x0,y0,x1,y1)
47    
48 greg 1.2 #define redraw(x,y,w,h) patch_raster(wind,(x)-xoff,(y)-yoff,x,y,w,h,ourras)
49    
50 greg 1.1 double gamcor = 2.2; /* gamma correction */
51    
52     int dither = 1; /* dither colors? */
53     int fast = 0; /* keep picture in Pixmap? */
54    
55 greg 2.6 char *dispname = NULL; /* our display name */
56    
57 greg 1.1 Window wind = 0; /* our output window */
58 greg 2.9 unsigned long ourblack=0, ourwhite=1; /* black and white for this visual */
59 greg 1.1 Font fontid; /* our font */
60    
61 greg 1.2 int maxcolors = 0; /* maximum colors */
62 greg 1.1 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 greg 1.26 RESOLU inpres; /* input resolution and ordering */
75     int xmax, ymax; /* picture dimensions */
76 greg 1.1 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 greg 1.14 int wrongformat = 0; /* input in another format? */
85    
86 greg 2.6 GC ourgc; /* standard graphics context */
87 greg 1.5 GC revgc; /* graphics context with GXinvert */
88    
89 greg 2.6 int *ourrank; /* our visual class ranking */
90     XVisualInfo ourvis; /* our visual */
91     XRASTER *ourras; /* our stored image */
92 greg 1.1 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 greg 1.18 char icondata[ICONSIZ*ICONSIZ/8]; /* icon bitmap data */
101 greg 1.17 int iconwidth = 0, iconheight = 0;
102    
103 greg 1.1 char *progname;
104    
105     char errmsg[128];
106    
107     extern long ftell();
108    
109     extern char *malloc(), *calloc();
110    
111 greg 2.2 extern double pow(), log();
112 greg 1.1
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 greg 2.7 if (argv[i][2] == 'i')
138 greg 2.6 dispname = argv[++i];
139 greg 2.7 else
140     dither = !dither;
141 greg 1.1 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 greg 2.7 if (argv[i][2] == 'e')
152 greg 1.1 geometry = argv[++i];
153     else
154     gamcor = atof(argv[++i]);
155     break;
156     default:
157     goto userr;
158     }
159 greg 1.3 else if (argv[i][0] == '=')
160     geometry = argv[i];
161 greg 1.1 else
162     break;
163    
164 greg 1.3 if (i == argc-1) {
165 greg 1.1 fname = argv[i];
166     fin = fopen(fname, "r");
167     if (fin == NULL) {
168 greg 2.6 sprintf(errmsg, "cannot open file \"%s\"", fname);
169 greg 1.1 quiterr(errmsg);
170     }
171 greg 1.3 } else if (i != argc)
172     goto userr;
173 greg 1.1 /* get header */
174 greg 1.14 getheader(fin, headline, NULL);
175 greg 1.1 /* get picture dimensions */
176 greg 1.26 if (wrongformat || !fgetsresolu(&inpres, fin))
177 greg 1.14 quiterr("bad picture format");
178 greg 1.26 xmax = scanlen(&inpres);
179     ymax = numscans(&inpres);
180 greg 1.1 /* 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 greg 2.7 "Usage: %s [-display disp][-geometry spec][-b][-m][-d][-f][-c ncolors][-e +/-stops] file\n",
193 greg 1.1 progname);
194     quit(1);
195     }
196    
197    
198     headline(s) /* get relevant info from header */
199     char *s;
200     {
201 greg 1.14 char fmt[32];
202 greg 1.1
203 greg 1.2 if (isexpos(s))
204     exposure *= exposval(s);
205 greg 1.14 else if (isformat(s)) {
206     formatval(fmt, s);
207     wrongformat = strcmp(fmt, COLRFMT);
208 greg 2.4 } else if (isview(s) && sscanview(&ourview, s) > 0)
209     gotview++;
210 greg 1.1 }
211    
212    
213     init() /* get data and open window */
214     {
215 greg 1.15 XWMHints ourxwmhints;
216 greg 1.4 XSetWindowAttributes ourwinattr;
217 greg 2.6 XSizeHints oursizhints;
218     register int i;
219 greg 1.1
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 greg 2.6 if ((thedisplay = XOpenDisplay(dispname)) == NULL)
228     quiterr("cannot open display");
229     /* get best visual for default screen */
230     getbestvis();
231 greg 1.4 /* store image */
232     getras();
233     /* open window */
234     ourwinattr.border_pixel = ourblack;
235     ourwinattr.background_pixel = ourwhite;
236 greg 2.6 ourwinattr.colormap = XCreateColormap(thedisplay, ourroot,
237     ourvis.visual, AllocNone);
238 greg 1.4 wind = XCreateWindow(thedisplay, ourroot, 0, 0, xmax, ymax, BORWIDTH,
239 greg 2.6 ourvis.depth, InputOutput, ourvis.visual,
240     CWBackPixel|CWBorderPixel|CWColormap, &ourwinattr);
241 greg 1.4 if (wind == 0)
242 greg 2.6 quiterr("cannot create window");
243 greg 2.9 XFreeColormap(thedisplay, ourwinattr.colormap);
244 greg 1.5 width = xmax;
245     height = ymax;
246 greg 2.6 ourgc = XCreateGC(thedisplay, wind, 0, 0);
247 greg 2.8 XSetState(thedisplay, ourgc, ourblack, ourwhite, GXcopy, AllPlanes);
248 greg 2.6 revgc = XCreateGC(thedisplay, wind, 0, 0);
249     XSetFunction(thedisplay, revgc, GXinvert);
250 greg 1.1 fontid = XLoadFont(thedisplay, FONTNAME);
251     if (fontid == 0)
252 greg 2.6 quiterr("cannot get font");
253 greg 1.1 XSetFont(thedisplay, ourgc, fontid);
254     XDefineCursor(thedisplay, wind, XCreateFontCursor(thedisplay,
255     XC_diamond_cross));
256 greg 1.22 XStoreName(thedisplay, wind, fname == NULL ? progname : fname);
257 greg 1.1 if (geometry != NULL) {
258     bzero((char *)&oursizhints, sizeof(oursizhints));
259     i = XParseGeometry(geometry, &oursizhints.x, &oursizhints.y,
260 greg 1.12 (unsigned *)&oursizhints.width,
261     (unsigned *)&oursizhints.height);
262 greg 1.3 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 greg 1.1 oursizhints.flags |= USPosition;
271     if (i & XNegative)
272 greg 1.3 oursizhints.x += DisplayWidth(thedisplay,
273     ourscreen)-1-oursizhints.width-2*BORWIDTH;
274 greg 1.1 if (i & YNegative)
275 greg 1.3 oursizhints.y += DisplayHeight(thedisplay,
276     ourscreen)-1-oursizhints.height-2*BORWIDTH;
277 greg 1.1 }
278     XSetNormalHints(thedisplay, wind, &oursizhints);
279     }
280 greg 1.15 ourxwmhints.flags = InputHint|IconPixmapHint;
281     ourxwmhints.input = True;
282     ourxwmhints.icon_pixmap = XCreateBitmapFromData(thedisplay,
283 greg 1.17 wind, icondata, iconwidth, iconheight);
284 greg 1.15 XSetWMHints(thedisplay, wind, &ourxwmhints);
285 greg 1.2 XSelectInput(thedisplay, wind, ButtonPressMask|ButtonReleaseMask
286     |ButtonMotionMask|StructureNotifyMask
287     |KeyPressMask|ExposureMask);
288 greg 1.1 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 greg 2.6 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 greg 2.7 #ifdef DEBUG
364 greg 2.6 static char vistype[][12] = {
365     "StaticGray",
366     "GrayScale",
367     "StaticColor",
368     "PseudoColor",
369     "TrueColor",
370     "DirectColor"
371     };
372 greg 2.7 #endif
373 greg 2.6 static int rankings[3][6] = {
374     {TrueColor,DirectColor,PseudoColor,GrayScale,StaticGray,-1},
375 greg 2.7 {PseudoColor,GrayScale,StaticGray,-1},
376     {PseudoColor,GrayScale,StaticGray,-1}
377 greg 2.6 };
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 greg 2.7 #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 greg 2.6 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 greg 2.7 #ifdef DEBUG
415     fprintf(stderr, "Selected visual type %s, depth %d\n",
416     vistype[ourvis.class], ourvis.depth);
417     #endif
418 greg 2.8 /* make appropriate adjustments */
419 greg 2.6 if (ourvis.class == GrayScale || ourvis.class == StaticGray)
420     greyscale = 1;
421 greg 2.7 if (ourvis.depth <= 8 && ourvis.colormap_size < maxcolors)
422     maxcolors = ourvis.colormap_size;
423 greg 2.6 if (maxcolors > 4)
424     maxcolors -= 2;
425 greg 2.8 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 greg 2.9 if ((ourblack|ourwhite) & ~255L) {
432     ourblack = 0;
433     ourwhite = 1;
434     }
435 greg 2.8 } else {
436     ourblack = 0;
437 greg 2.9 ourwhite = ourvis.red_mask|ourvis.green_mask|ourvis.blue_mask;
438 greg 2.8 }
439 greg 2.6 XFree((char *)xvi);
440     }
441    
442    
443 greg 1.1 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 greg 2.6 ourras = make_raster(thedisplay, &ourvis, 1, ourdata,
453 greg 1.1 xmax, ymax, 8);
454     if (ourras == NULL)
455     goto fail;
456     getmono();
457 greg 2.6 } else if (ourvis.class == TrueColor || ourvis.class == DirectColor) {
458     ourdata = (unsigned char *)malloc(4*xmax*ymax);
459 greg 1.1 if (ourdata == NULL)
460     goto fail;
461 greg 2.6 ourras = make_raster(thedisplay, &ourvis, 32,
462     ourdata, xmax, ymax, 32);
463 greg 1.1 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 greg 2.6 ourras = make_raster(thedisplay, &ourvis, 8, ourdata,
471 greg 1.1 xmax, ymax, 8);
472     if (ourras == NULL)
473     goto fail;
474 greg 2.7 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 greg 1.1 }
486 greg 2.7 return;
487 greg 1.1 fail:
488 greg 1.9 quiterr("could not create raster image");
489 greg 1.1 }
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 greg 2.6 make_rpixmap(ourras, wind);
515 greg 1.1 break;
516     case UnmapNotify:
517 greg 2.7 if (!fast)
518     unmap_rcolors(ourras);
519 greg 1.1 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 greg 1.26 FLOAT hv[2];
542 greg 1.1 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 greg 2.3 case CTRL('D'): /* quit */
551 greg 1.1 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 greg 1.16 sprintf(buf, "%.0fL", luminance(cval)/exposure);
565 greg 1.1 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 greg 1.3 XDrawImageString(thedisplay, wind, ourgc,
575     box.xmin, box.ymin+box.ysiz, buf, strlen(buf));
576 greg 1.1 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 greg 1.2 cvx.flags = DoRed|DoGreen|DoBlue;
587     XStoreColor(thedisplay, ourras->cmap, &cvx);
588 greg 1.1 return(0);
589     case 'p': /* position */
590 greg 1.26 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 greg 1.1 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 greg 1.26 pix2loc(hv, &inpres, ekey->x-xoff, ekey->y-yoff);
602     if (viewray(rorg, rdir, &ourview, hv[0], hv[1]) < 0)
603 greg 1.8 return(-1);
604 greg 1.1 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 greg 1.3 XDrawImageString(thedisplay, wind, ourgc,
618     box.xmin, box.ymin+box.ysiz, buf, strlen(buf));
619 greg 1.1 XFlush(thedisplay);
620     free(ourdata);
621     free_raster(ourras);
622     getras();
623     /* fall through */
624 greg 2.3 case CTRL('R'): /* redraw */
625     case CTRL('L'):
626 greg 1.1 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 greg 1.2 XBell(thedisplay, 0);
638 greg 1.1 return(-1);
639     }
640     }
641    
642    
643 greg 1.2 moveimage(ebut) /* shift the image */
644     XButtonPressedEvent *ebut;
645 greg 1.1 {
646 greg 1.2 union {
647 greg 1.3 XEvent u;
648     XButtonReleasedEvent b;
649     XPointerMovedEvent m;
650     } e;
651 greg 1.5 int mxo, myo;
652 greg 1.1
653 greg 1.3 XMaskEvent(thedisplay, ButtonReleaseMask|ButtonMotionMask, &e.u);
654     while (e.u.type == MotionNotify) {
655 greg 1.5 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 greg 1.3 XMaskEvent(thedisplay,ButtonReleaseMask|ButtonMotionMask,&e.u);
661 greg 1.5 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 greg 1.3 }
665 greg 1.2 xoff += e.b.x - ebut->x;
666     yoff += e.b.y - ebut->y;
667 greg 1.1 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 greg 1.2 XEvent u;
677 greg 1.1 XButtonReleasedEvent b;
678     XPointerMovedEvent m;
679     } e;
680    
681 greg 1.2 XMaskEvent(thedisplay, ButtonReleaseMask|ButtonMotionMask, &e.u);
682     while (e.u.type == MotionNotify) {
683 greg 1.1 revbox(ebut->x, ebut->y, box.xmin = e.m.x, box.ymin = e.m.y);
684 greg 1.2 XMaskEvent(thedisplay,ButtonReleaseMask|ButtonMotionMask,&e.u);
685 greg 1.1 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 greg 1.5 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 greg 1.1
713    
714     avgbox(clr) /* average color over current box */
715     COLOR clr;
716     {
717 greg 1.25 static COLOR lc;
718     static int ll, lr, lt, lb;
719 greg 1.1 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 greg 1.25 if (left == ll && right == lr && top == lt && bottom == lb) {
743     copycolor(clr, lc);
744     return;
745     }
746 greg 1.1 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 greg 1.25 ll = left; lr = right; lt = top; lb = bottom;
757     copycolor(lc, clr);
758 greg 1.1 return(0);
759     }
760    
761    
762     getmono() /* get monochrome data */
763     {
764     register unsigned char *dp;
765     register int x, err;
766 greg 1.23 int y, errp;
767 greg 1.1 short *cerr;
768    
769 greg 1.10 if ((cerr = (short *)calloc(xmax,sizeof(short))) == NULL)
770 greg 1.9 quiterr("out of memory in getmono");
771 greg 1.1 dp = ourdata - 1;
772     for (y = 0; y < ymax; y++) {
773 greg 1.10 if (getscan(y) < 0)
774     quiterr("seek error in getmono");
775     normcolrs(scanline, xmax, scale);
776 greg 1.17 add2icon(y, scanline);
777 greg 1.1 err = 0;
778     for (x = 0; x < xmax; x++) {
779     if (!(x&7))
780     *++dp = 0;
781 greg 1.23 errp = err;
782 greg 1.10 err += normbright(scanline[x]) + cerr[x];
783 greg 1.1 if (err > 127)
784     err -= 255;
785     else
786 greg 1.3 *dp |= 1<<(7-(x&07));
787 greg 1.23 err /= 3;
788     cerr[x] = err + errp;
789 greg 1.1 }
790     }
791     free((char *)cerr);
792     }
793    
794    
795 greg 1.17 add2icon(y, scan) /* add a scanline to our icon data */
796     int y;
797     COLR *scan;
798     {
799     static short cerr[ICONSIZ];
800 greg 1.20 static int ynext;
801     static char *dp;
802 greg 1.17 register int err;
803 greg 1.20 register int x, ti;
804 greg 1.23 int errp;
805 greg 1.17
806     if (iconheight == 0) { /* initialize */
807 greg 1.18 if (xmax <= ICONSIZ && ymax <= ICONSIZ) {
808 greg 1.17 iconwidth = xmax;
809     iconheight = ymax;
810     } else if (xmax > ymax) {
811     iconwidth = ICONSIZ;
812     iconheight = ICONSIZ*ymax/xmax;
813 greg 1.24 if (iconheight < 1)
814     iconheight = 1;
815 greg 1.17 } else {
816     iconwidth = ICONSIZ*xmax/ymax;
817 greg 1.24 if (iconwidth < 1)
818     iconwidth = 1;
819 greg 1.17 iconheight = ICONSIZ;
820     }
821 greg 1.20 ynext = 0;
822 greg 1.17 dp = icondata - 1;
823     }
824 greg 1.20 if (y < ynext*ymax/iconheight) /* skip this one */
825 greg 1.17 return;
826     err = 0;
827     for (x = 0; x < iconwidth; x++) {
828     if (!(x&7))
829     *++dp = 0;
830 greg 1.23 errp = err;
831 greg 1.20 ti = x*xmax/iconwidth;
832     err += normbright(scan[ti]) + cerr[x];
833 greg 1.17 if (err > 127)
834     err -= 255;
835     else
836     *dp |= 1<<(x&07);
837 greg 1.23 err /= 3;
838     cerr[x] = err + errp;
839 greg 1.17 }
840 greg 1.20 ynext++;
841 greg 1.17 }
842    
843    
844 greg 1.1 getfull() /* get full (24-bit) data */
845     {
846     int y;
847 greg 2.6 register unsigned long *dp;
848 greg 1.10 register int x;
849     /* set gamma correction */
850     setcolrgam(gamcor);
851     /* read and convert file */
852 greg 2.6 dp = (unsigned long *)ourdata;
853 greg 1.10 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 greg 1.17 add2icon(y, scanline);
860 greg 2.6 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 greg 1.10 }
871 greg 1.1 }
872    
873    
874 greg 2.7 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 greg 1.1 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 greg 1.9 quiterr("fseek error");
937 greg 1.1 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 greg 1.17 add2icon(y, scanline);
960 greg 1.1 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 greg 1.11 val = pow((i+0.5)/256.0, 1.0/gamcor) * 256.0;
984 greg 1.1 map[0][i] = map[1][i] = map[2][i] = val;
985     }
986     }
987    
988    
989     picwritecm(map) /* handled elsewhere */
990     colormap map;
991     {
992 greg 2.7 #if 0
993 greg 1.1 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     }