aa55152ea7fd0a21376ba96f3d4bca89e9d52de2
[rocksndiamonds.git] / src / send.c
1
2 /* send.c
3  *
4  * send an Image to an X pixmap
5  */
6
7 #include "xli.h"
8
9 /* extra colors to try allocating in private color maps to minimise flashing */
10 #define NOFLASH_COLORS 256
11
12 Image *monochrome(Image *cimage)
13 {
14   Image         *image;
15   unsigned char *sp, *dp, *dp2; /* data pointers */
16   unsigned int   spl;           /* source pixel length in bytes */
17   unsigned int   dll;           /* destination line length in bytes */
18   Pixel          color;         /* pixel color */
19   unsigned int   x, y;          /* random counters */
20   int bitmap_pixel;
21
22   if (BITMAPP(cimage))
23     return(NULL);
24
25   /*
26   printf("  Converting to monochrome...");
27   fflush(stdout);
28   */
29
30   image= newBitImage(cimage->width, cimage->height);
31   if (cimage->title)
32   {
33     image->title= (char *)lmalloc(strlen(cimage->title) + 13);
34     sprintf(image->title, "%s (monochrome)", cimage->title);
35   }
36
37   spl = cimage->pixlen;
38   dll = (image->width / 8) + (image->width % 8 ? 1 : 0);
39
40   sp = cimage->data;
41   dp = image->data;
42
43   for (y= 0; y < cimage->height; y++)
44   {
45     for (x= 0; x < cimage->width; x++)
46     {
47       dp2 = dp + (x / 8);       /* dp + x/8 */
48       color= memToVal(sp, spl);
49
50       if (cimage->rgb.red[color] > 0x0000 ||
51           cimage->rgb.green[color] > 0x0000 ||
52           cimage->rgb.blue[color] > 0x0000)
53         bitmap_pixel = 0x00;
54       else
55         bitmap_pixel = 0x80;
56
57       *dp2 |= bitmap_pixel >> ( x % 8);
58       sp += spl;
59     }
60
61     dp += dll;  /* next row */
62   }
63
64   /*
65   printf("done\n");
66   */
67
68   return(image);
69 }
70
71 static unsigned int *buildIndex(unsigned int width,
72                                 unsigned int zoom,
73                                 unsigned int *rwidth)
74 {
75   float         fzoom;
76   unsigned int *index;
77   unsigned int  a;
78
79   if (!zoom)
80   {
81     fzoom= 100.0;
82     *rwidth= width;
83   }
84   else
85   {
86     fzoom= (float)zoom / 100.0;
87     *rwidth= (unsigned int)(fzoom * width + 0.5);
88   }
89   index= (unsigned int *)lmalloc(sizeof(unsigned int) * *rwidth);
90   for (a= 0; a < *rwidth; a++)
91   {
92     if (zoom)
93       *(index + a)= (unsigned int)((float)a / fzoom + 0.5);
94     else
95       *(index + a)= a;
96   }
97   return(index);
98 }
99
100 Image *zoom(Image *oimage, unsigned int xzoom, unsigned int yzoom)
101 {
102   Image        *image;
103   unsigned int *xindex, *yindex;
104   unsigned int  xwidth, ywidth;
105   unsigned int  x, y, xsrc, ysrc;
106   unsigned int  pixlen;
107   unsigned int  srclinelen;
108   unsigned int  destlinelen;
109   byte         *srcline, *srcptr;
110   byte         *destline, *destptr;
111   byte          srcmask, destmask, bit;
112   Pixel         value;
113
114   if ((!xzoom || xzoom==100) && (!yzoom || yzoom==100)) 
115     return(oimage);
116
117   if (!xzoom)
118     printf("  Zooming image Y axis by %d%%...", yzoom);
119   else if (!yzoom)
120     printf("  Zooming image X axis by %d%%...", xzoom);
121   else if (xzoom == yzoom)
122     printf("  Zooming image by %d%%...", xzoom);
123   else
124     printf("  Zooming image X axis by %d%% and Y axis by %d%%...",
125              xzoom, yzoom);
126   fflush(stdout);
127
128   xindex= buildIndex(oimage->width, xzoom, &xwidth);
129   yindex= buildIndex(oimage->height, yzoom, &ywidth);
130
131   switch (oimage->type)
132   {
133     case IBITMAP:
134       image= newBitImage(xwidth, ywidth);
135       for (x= 0; x < oimage->rgb.used; x++)
136       {
137         *(image->rgb.red + x)= *(oimage->rgb.red + x);
138         *(image->rgb.green + x)= *(oimage->rgb.green + x);
139         *(image->rgb.blue + x)= *(oimage->rgb.blue + x);
140       }
141       image->rgb.used= oimage->rgb.used;
142       destline= image->data;
143       destlinelen= (xwidth / 8) + (xwidth % 8 ? 1 : 0);
144       srcline= oimage->data;
145       srclinelen= (oimage->width / 8) + (oimage->width % 8 ? 1 : 0);
146       for (y= 0, ysrc= *(yindex + y); y < ywidth; y++)
147       {
148         while (ysrc != *(yindex + y))
149         {
150           ysrc++;
151           srcline += srclinelen;
152         }
153         srcptr= srcline;
154         destptr= destline;
155         srcmask= 0x80;
156         destmask= 0x80;
157         bit= srcmask & *srcptr;
158         for (x= 0, xsrc= *(xindex + x); x < xwidth; x++)
159         {
160           if (xsrc != *(xindex + x))
161           {
162             do
163             {
164               xsrc++;
165               if (!(srcmask >>= 1))
166               {
167                 srcmask= 0x80;
168                 srcptr++;
169               }
170             }
171             while (xsrc != *(xindex + x));
172
173             bit= srcmask & *srcptr;
174           }
175           if (bit)
176             *destptr |= destmask;
177           if (!(destmask >>= 1))
178           {
179             destmask= 0x80;
180             destptr++;
181           }
182         }
183         destline += destlinelen;
184       }
185       break;
186
187     case IRGB:
188       image= newRGBImage(xwidth, ywidth, oimage->depth);
189       for (x= 0; x < oimage->rgb.used; x++)
190       {
191         *(image->rgb.red + x)= *(oimage->rgb.red + x);
192         *(image->rgb.green + x)= *(oimage->rgb.green + x);
193         *(image->rgb.blue + x)= *(oimage->rgb.blue + x);
194       }
195       image->rgb.used= oimage->rgb.used;
196
197       pixlen= oimage->pixlen;
198       destptr= image->data;
199       srcline= oimage->data;
200       srclinelen= oimage->width * pixlen;
201       for (y= 0, ysrc= *(yindex + y); y < ywidth; y++)
202       {
203         while (ysrc != *(yindex + y))
204         {
205           ysrc++;
206           srcline += srclinelen;
207         }
208
209         srcptr = srcline;
210         value = memToVal(srcptr, image->pixlen);
211
212         for (x=0, xsrc= *(xindex + x); x<xwidth; x++)
213         {
214           if (xsrc != *(xindex + x))
215           {
216             do
217             {
218               xsrc++;
219               srcptr++;
220             }
221             while (xsrc != *(xindex + x));
222             value = memToVal(srcptr, 1);
223           }
224           valToMem(value, destptr, 1);
225           destptr++;
226         }
227       }
228       break;
229
230     default:
231       /* no zooming */
232       return(oimage);
233       break;
234   }
235
236   image->title = dupString(oimage->title);
237   lfree((byte *)xindex);
238   lfree((byte *)yindex);
239
240   printf("done\n");
241
242   return(image);
243 }
244
245 void compress(Image *image)
246 {
247   unsigned char   *used, fast[32][32][32];
248   unsigned int     dmask;       /* Depth mask protection */
249   Pixel           *map;
250   unsigned int     next_index;
251   Intensity *red = image->rgb.red,
252             *green = image->rgb.green,
253             *blue = image->rgb.blue;
254   Intensity r,g,b;
255   unsigned int x, y, badcount = 0, dupcount = 0, unusedcount = 0;
256   unsigned char *pixptr, *pixend;
257
258   if (!RGBP(image) || image->rgb.compressed)
259     return;
260
261   /*
262   printf("  Compressing colormap...");
263   fflush(stdout);
264   */
265
266   used = (unsigned char *)lcalloc(sizeof(unsigned char) * depthToColors(image->depth));
267   dmask = (1 << image->depth) -1;       /* Mask any illegal bits for that depth */
268   map = (Pixel *)lcalloc(sizeof(Pixel) * depthToColors(image->depth));
269
270   /* init fast duplicate check table */
271   for(r=0;r<32;r++)
272     for(g=0;g<32;g++)
273       for(b=0;b<32;b++)
274         fast[r][g][b] = 0;
275
276   /* do pass 1 through the image to check index usage */
277
278   pixptr = image->data;
279   pixend = pixptr + (image->height * image->width);
280   for(;pixptr < pixend; pixptr++)
281     used[(*pixptr) & dmask] = 1;
282
283   /* count the bad pixels */
284   for (x = image->rgb.used; x < depthToColors(image->depth); x++)
285     if (used[x])
286       badcount++;
287
288   /* figure out duplicates and unuseds, and create the new mapping */
289   next_index = 0;
290   for (x = 0; x < image->rgb.used; x++)
291   {
292     if (!used[x])
293     {
294       unusedcount++;
295       continue;         /* delete this index */
296     }
297
298     /* check for duplicate */
299     r = red[x];
300     g = green[x];
301     b = blue[x];
302     if (fast[r>>11][g>>11][b>>11])      /* if matches fast check */
303     {
304       /* then do a linear search */
305       for (y = x+1; y < image->rgb.used; y++)
306       {
307         if (r == red[y] && g == green[y] && b == blue[y])
308           break;
309       }
310       if (y < image->rgb.used)  /* found match */
311       {
312         map[x] = y;
313         dupcount++;
314         continue;               /* delete this index */
315       }
316       fast[r>>11][g>>11][b>>11] = 1;
317     }
318     /* will map to this index */
319     map[x] = next_index;
320     next_index++;
321   }
322
323   /* change the image pixels */
324   pixptr = image->data;
325   pixend = pixptr + (image->height * image->width);
326   for(;pixptr < pixend; pixptr++)
327     *pixptr = map[(*pixptr) & dmask];
328
329   /* change the colormap */
330   for (x = 0; x < image->rgb.used; x++)
331   {
332     if (!used[x])
333       continue;
334     red[map[x]] = red[x];
335     green[map[x]] = green[x];
336     blue[map[x]] = blue[x];
337   }
338   image->rgb.used = next_index;
339
340   /* clean up */
341   lfree(map);
342   lfree(used);
343
344   /*
345   if (badcount)
346     printf("%d out-of-range pixels, ", badcount);
347
348   if (!unusedcount && !dupcount)
349     printf("no improvment\n");
350   else
351   {
352     if (dupcount)
353       printf("%d duplicate%s and %d unused color%s removed...",
354              dupcount, (dupcount == 1 ? "" : "s"),
355              unusedcount, (unusedcount == 1 ? "" : "s"));
356     printf("%d unique color%s\n",
357            next_index, (next_index == 1 ? "" : "s"));
358   }
359   */
360
361   image->rgb.compressed= TRUE;  /* don't do it again */
362 }
363
364
365
366
367 Pixmap ximageToPixmap(Display *disp, Window parent, XImageInfo *ximageinfo)
368 {
369   Pixmap pixmap;
370
371   pixmap = XCreatePixmap(disp, parent,
372                          ximageinfo->ximage->width, ximageinfo->ximage->height,
373                          ximageinfo->depth);
374
375   ximageinfo->drawable = pixmap;
376
377   sendXImage(ximageinfo, 0, 0, 0, 0,
378              ximageinfo->ximage->width, ximageinfo->ximage->height);
379   return(pixmap);
380 }
381
382 /* find the best pixmap depth supported by the server for a particular
383  * visual and return that depth.
384  *
385  * this is complicated by R3's lack of XListPixmapFormats so we fake it
386  * by looking at the structure ourselves.
387  */
388
389 static unsigned int bitsPerPixelAtDepth(Display *disp, int scrn,
390                                         unsigned int depth)
391 {
392 #if defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 4)
393   /* the way things are */
394   XPixmapFormatValues *xf;
395   int nxf, a;
396
397   xf = XListPixmapFormats(disp, &nxf);
398   for (a = 0; a < nxf; a++)
399   {
400     if (xf[a].depth == depth)
401     {
402       int bpp;
403       bpp = xf[a].bits_per_pixel;
404       XFree(xf);
405       return (unsigned int) bpp;
406     }
407   }
408   XFree(xf);
409 #else /* the way things were (X11R3) */
410   unsigned int a;
411
412   for (a= 0; a < disp->nformats; a++)
413     if (disp->pixmap_format[a].depth == depth)
414       return(disp->pixmap_format[a].bits_per_pixel);
415 #endif
416
417   /* this should never happen; if it does, we're in trouble
418    */
419
420   fprintf(stderr, "bitsPerPixelAtDepth: Can't find pixmap depth info!\n");
421   exit(1);
422 }
423
424 XImageInfo *imageToXImage(Display *disp,
425                           int scrn,
426                           Visual *visual,
427                           unsigned int ddepth,
428                           Image *image)
429 {
430   Pixel        *redvalue, *greenvalue, *bluevalue;
431   unsigned int  a, c=0, x, y, linelen, dpixlen, dbits;
432   XColor        xcolor;
433
434   static XColor xcolor_used[NOFLASH_COLORS];
435
436   XGCValues     gcv;
437   XImageInfo   *ximageinfo;
438   Image        *orig_image;
439
440   static Colormap our_default_cmap = 0;
441   static Pixel *our_default_index;
442   static int free_cmap_entries, max_cmap_entries;
443   int use_cmap_entry;
444
445
446   static unsigned long pixel_used[NOFLASH_COLORS];
447
448
449   if (!our_default_cmap)
450   {
451 #if 0
452     our_default_cmap = DefaultColormap(disp, scrn);
453 #endif
454
455     our_default_cmap = XCreateColormap(disp, RootWindow(disp, scrn),
456                                        visual, AllocNone);
457     our_default_index = (Pixel *)lmalloc(sizeof(Pixel) * NOFLASH_COLORS);
458
459     for (a=0; a<NOFLASH_COLORS; a++)    /* count entries we got */
460       if (!XAllocColorCells(disp, our_default_cmap, FALSE, NULL, 0,
461                             our_default_index + a, 1))
462         break;
463
464     free_cmap_entries = max_cmap_entries = a;
465
466     printf("We've got %d colormap entries.\n", free_cmap_entries);
467
468     for(a=0; a<max_cmap_entries; a++)   /* copy default colors */
469     {
470       xcolor.pixel = *(our_default_index + a);
471       XQueryColor(disp, DefaultColormap(disp, scrn), &xcolor);
472       XStoreColor(disp, our_default_cmap, &xcolor);
473
474       pixel_used[xcolor.pixel] = 0;
475       xcolor_used[xcolor.pixel] = xcolor;
476     }
477   }
478
479   xcolor.flags= DoRed | DoGreen | DoBlue;
480   redvalue= greenvalue= bluevalue= NULL;
481   orig_image= image;
482   ximageinfo= (XImageInfo *)lmalloc(sizeof(XImageInfo));
483   ximageinfo->disp= disp;
484   ximageinfo->scrn= scrn;
485   ximageinfo->depth= 0;
486   ximageinfo->drawable= None;
487   ximageinfo->index= NULL;
488   ximageinfo->rootimage= FALSE; /* assume not */
489   ximageinfo->foreground= ximageinfo->background= 0;
490   ximageinfo->gc= NULL;
491   ximageinfo->ximage= NULL;
492
493   /* do color allocation
494    */
495
496   switch (visual->class)
497   {
498     case TrueColor:
499     case DirectColor:
500     {
501       Pixel pixval;
502       unsigned int redcolors, greencolors, bluecolors;
503       unsigned int redstep, greenstep, bluestep;
504       unsigned int redbottom, greenbottom, bluebottom;
505       unsigned int redtop, greentop, bluetop;
506
507       redvalue= (Pixel *)lmalloc(sizeof(Pixel) * 256);
508       greenvalue= (Pixel *)lmalloc(sizeof(Pixel) * 256);
509       bluevalue= (Pixel *)lmalloc(sizeof(Pixel) * 256);
510
511 #if 1
512       if (visual == DefaultVisual(disp, scrn))
513         ximageinfo->cmap= DefaultColormap(disp, scrn);
514       else
515         ximageinfo->cmap= XCreateColormap(disp, RootWindow(disp, scrn),
516                                           visual, AllocNone);
517 #else
518       ximageinfo->cmap = our_default_cmap;
519 #endif
520
521       retry_direct: /* tag we hit if a DirectColor allocation fails on
522                      * default colormap */
523
524       /* calculate number of distinct colors in each band
525        */
526
527       redcolors= greencolors= bluecolors= 1;
528       for (pixval= 1; pixval; pixval <<= 1)
529       {
530         if (pixval & visual->red_mask)
531           redcolors <<= 1;
532         if (pixval & visual->green_mask)
533           greencolors <<= 1;
534         if (pixval & visual->blue_mask)
535           bluecolors <<= 1;
536       }
537       
538       /* sanity check
539        */
540
541       if ((redcolors > visual->map_entries) ||
542           (greencolors > visual->map_entries) ||
543           (bluecolors > visual->map_entries))
544       {
545         fprintf(stderr, "Warning: inconsistency in color information (this may be ugly)\n");
546       }
547
548       redstep = 256 / redcolors;
549       greenstep = 256 / greencolors;
550       bluestep = 256 / bluecolors;
551       redbottom = greenbottom = bluebottom = 0;
552       redtop = greentop = bluetop = 0;
553       for (a= 0; a < visual->map_entries; a++)
554       {
555         if (redbottom < 256)
556           redtop= redbottom + redstep;
557         if (greenbottom < 256)
558           greentop= greenbottom + greenstep;
559         if (bluebottom < 256)
560           bluetop= bluebottom + bluestep;
561
562         xcolor.red= (redtop - 1) << 8;
563         xcolor.green= (greentop - 1) << 8;
564         xcolor.blue= (bluetop - 1) << 8;
565         if (! XAllocColor(disp, ximageinfo->cmap, &xcolor))
566         {
567           /* if an allocation fails for a DirectColor default visual then
568            * we should create a private colormap and try again.
569            */
570
571           if ((visual->class == DirectColor) &&
572               (visual == DefaultVisual(disp, scrn)))
573           {
574 #if 1
575             ximageinfo->cmap = XCreateColormap(disp, RootWindow(disp, scrn),
576                                                visual, AllocNone);
577 #else
578             our_default_cmap = XCopyColormapAndFree(disp, our_default_cmap);
579             ximageinfo->cmap = our_default_cmap;
580 #endif
581             goto retry_direct;
582           }
583
584           /* something completely unexpected happened
585            */
586
587           fprintf(stderr, "imageToXImage: XAllocColor failed on a TrueColor/Directcolor visual\n");
588           lfree((byte *)redvalue);
589           lfree((byte *)greenvalue);
590           lfree((byte *)bluevalue);
591           lfree((byte *)ximageinfo);
592           return(NULL);
593         }
594
595         /* fill in pixel values for each band at this intensity
596          */
597
598         while ((redbottom < 256) && (redbottom < redtop))
599           redvalue[redbottom++]= xcolor.pixel & visual->red_mask;
600         while ((greenbottom < 256) && (greenbottom < greentop))
601           greenvalue[greenbottom++]= xcolor.pixel & visual->green_mask;
602         while ((bluebottom < 256) && (bluebottom < bluetop))
603           bluevalue[bluebottom++]= xcolor.pixel & visual->blue_mask;
604       }
605       break;
606     }
607
608     case PseudoColor:
609
610       ximageinfo->index= (Pixel *)lmalloc(sizeof(Pixel) * (image->rgb.used+NOFLASH_COLORS));
611
612
613       /* get the colormap to use.
614        */
615
616       ximageinfo->cmap = our_default_cmap;
617
618       /* allocate colors shareable (if we can)
619        */
620
621       for (a = 0; a < image->rgb.used; a++)
622       {
623         int i;
624         XColor xcolor2;
625   
626         xcolor2.flags = DoRed | DoGreen | DoBlue;
627   
628         xcolor.red= *(image->rgb.red + a);
629         xcolor.green= *(image->rgb.green + a);
630         xcolor.blue= *(image->rgb.blue + a);
631   
632         /* look if this color already exists in our colormap */
633   
634   #if 0
635         for (i=max_cmap_entries-1; i>=free_cmap_entries; i--)
636   
637   #else
638         for (i=max_cmap_entries-1; i>=0; i--)
639         {
640           /*
641           if (!pixel_used[i])
642             continue;
643             */
644   #endif
645   
646           xcolor2.pixel = *(our_default_index + i);
647   
648   #if 0
649           XQueryColor(disp, ximageinfo->cmap, &xcolor2);
650   #else
651           xcolor2 = xcolor_used[xcolor2.pixel];
652   #endif
653   
654           if ((xcolor.red >> 8) == (xcolor2.red >> 8) &&
655               (xcolor.green >> 8) == (xcolor2.green >> 8) &&
656               (xcolor.blue >> 8) == (xcolor2.blue >> 8))
657             break;
658         }
659   
660         use_cmap_entry = i;
661   
662         if (0 && use_cmap_entry < free_cmap_entries)    /* not found in colormap */
663         {
664           free_cmap_entries--;
665         }
666         else if (0 && use_cmap_entry < free_cmap_entries)       /* not found in colormap */
667         {
668         }
669         else if (use_cmap_entry < 0)    /* not found in colormap */
670         {
671           /* look for an existing 'unused' color near the one we want */
672   
673           for (i=free_cmap_entries-1; i>=0; i--)
674           {
675             int closeness = 14;
676   
677             if (pixel_used[i])
678               continue;
679   
680             xcolor2.pixel = *(our_default_index + i);
681   
682   #if 0
683             XQueryColor(disp, ximageinfo->cmap, &xcolor2);
684   #else
685             xcolor2 = xcolor_used[xcolor2.pixel];
686   #endif
687   
688   
689             if ((xcolor.red >> closeness) == (xcolor2.red >> closeness) &&
690                 (xcolor.green >> closeness) == (xcolor2.green >> closeness) &&
691                 (xcolor.blue >> closeness) == (xcolor2.blue >> closeness))
692               break;
693           }
694   
695           use_cmap_entry = i;
696   
697           if (use_cmap_entry < 0)               /* no 'near' color found */
698           {
699             /* look for the next free color */
700   
701             while (pixel_used[--free_cmap_entries])
702               ;
703             use_cmap_entry = free_cmap_entries;
704           }
705         }
706   
707         if (free_cmap_entries < 0)
708         {
709           printf("imageToXImage: too many global colors!\n");
710           exit(0);
711         }
712   
713   
714         /*
715           printf("--> eating color %d\n", use_cmap_entry);
716           */
717   
718   
719   
720         xcolor.pixel = use_cmap_entry;
721   
722         xcolor_used[xcolor.pixel] = xcolor;
723   
724         *(ximageinfo->index + a) = xcolor.pixel;
725   
726         XStoreColor(disp, ximageinfo->cmap, &xcolor);
727   
728         pixel_used[use_cmap_entry] = 1;
729       }
730       
731       ximageinfo->no = a;    /* number of pixels allocated in default visual */
732
733       /*  
734       printf("still %d free colormap entries\n", free_cmap_entries);
735       */
736
737       break;
738   
739     default:
740       printf("Sorry, only DirectColor, TrueColor and PseudoColor supported\n");
741       exit(0);
742       break;
743   }
744
745
746
747   /* create an XImage and related colormap based on the image type
748    * we have.
749    */
750
751   /*
752   printf("  Building XImage...");
753   fflush(stdout);
754   */
755
756   switch (image->type)
757   {
758     case IBITMAP:
759     {
760       byte *data;
761
762       /* we copy the data to be more consistent
763        */
764
765       linelen = ((image->width + 7) / 8);
766       data= lmalloc(linelen * image->height);
767
768       memcpy((char *)data, (char *)image->data, linelen * image->height);
769
770       gcv.function= GXcopy;
771       ximageinfo->ximage= XCreateImage(disp, visual, 1, XYBitmap,
772                                        0, (char *)data, image->width, image->height,
773                                        8, linelen);
774
775       /* use this if you want to use the bitmap as a mask */
776       ximageinfo->depth = image->depth;
777
778       if(visual->class == DirectColor || visual->class == TrueColor)
779       {
780         Pixel pixval;
781         dbits= bitsPerPixelAtDepth(disp, scrn, ddepth);
782         dpixlen= (dbits + 7) / 8;
783         pixval= redvalue[image->rgb.red[0] >> 8] |
784                 greenvalue[image->rgb.green[0] >> 8] |
785                 bluevalue[image->rgb.blue[0] >> 8];
786         ximageinfo->background = pixval;
787         pixval= redvalue[image->rgb.red[1] >> 8] |
788                 greenvalue[image->rgb.green[1] >> 8] |
789                 bluevalue[image->rgb.blue[1] >> 8];
790         ximageinfo->foreground = pixval;
791       }
792       else      /* Not Direct or True Color */
793       {
794         ximageinfo->foreground = BlackPixel(disp,scrn);
795         ximageinfo->background = WhitePixel(disp,scrn);
796       }
797       ximageinfo->ximage->bitmap_bit_order= MSBFirst;
798       ximageinfo->ximage->byte_order= MSBFirst;
799
800       break;
801     }
802
803     case IRGB:
804     {
805       /* modify image data to match visual and colormap
806        */
807
808       byte *data, *destptr, *srcptr;
809
810       dbits = bitsPerPixelAtDepth(disp, scrn, ddepth);  /* bits per pixel */
811       dpixlen = (dbits + 7) / 8;                        /* bytes per pixel */
812
813       ximageinfo->ximage = XCreateImage(disp, visual, ddepth, ZPixmap, 0,
814                                         NULL, image->width, image->height,
815                                         8, image->width * dpixlen);
816
817       data = (byte *)lmalloc(image->width * image->height * dpixlen);
818       ximageinfo->depth = ddepth;
819       ximageinfo->ximage->data = (char *)data;
820       ximageinfo->ximage->byte_order = MSBFirst;
821       srcptr = image->data;
822       destptr = data;
823
824       switch (visual->class)
825       {
826         case DirectColor:
827         case TrueColor:
828         {
829           Pixel pixval;
830
831           for (y=0; y<image->height; y++)
832           {
833             for (x=0; x<image->width; x++)
834             {
835               pixval = memToVal(srcptr, 1);
836               pixval = redvalue[image->rgb.red[pixval] >> 8] |
837                 greenvalue[image->rgb.green[pixval] >> 8] |
838                 bluevalue[image->rgb.blue[pixval] >> 8];
839               valToMem(pixval, destptr, dpixlen);
840               srcptr += 1;
841               destptr += dpixlen;
842             }
843           }
844           break;
845         }
846   
847         default:
848         {  
849           if (dpixlen == 1)                     /* most common */
850           {
851             for (y=0; y<image->height; y++)
852             {
853               for (x=0; x<image->width; x++)
854               {
855                 *destptr = ximageinfo->index[c + *srcptr];
856                 srcptr++;
857                 destptr++;
858               }
859             }
860           }
861           else                                  /* less common */
862           {
863             for (y=0; y<image->height; y++)
864             {
865               for (x=0; x<image->width; x++)
866               {
867                 register unsigned long temp;
868                 temp = memToVal(srcptr, 1);
869                 valToMem(ximageinfo->index[c + temp], destptr, dpixlen);
870                 srcptr += 1;
871                 destptr += dpixlen;
872               }
873             }
874           }
875         }
876         break;
877       }
878     }
879   }
880
881   /*
882   printf("done\n");
883   */
884
885   if (redvalue)
886   {
887     lfree((byte *)redvalue);
888     lfree((byte *)greenvalue);
889     lfree((byte *)bluevalue);
890   }
891
892   if (image != orig_image)
893     freeImage(image);
894   return(ximageinfo);
895 }
896
897 /* Given an XImage and a drawable, move a rectangle from the Ximage
898  * to the drawable.
899  */
900
901 void sendXImage(XImageInfo *ximageinfo,
902                 int src_x, int src_y, int dst_x, int dst_y,
903                 unsigned int w, unsigned int h)
904 {
905   XGCValues gcv;
906
907   /* build and cache the GC
908    */
909
910   if (!ximageinfo->gc)
911   {
912     gcv.function = GXcopy;
913     if (ximageinfo->ximage->depth == 1)
914     {
915       gcv.foreground = ximageinfo->foreground;
916       gcv.background = ximageinfo->background;
917       ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable,
918                                  GCFunction | GCForeground | GCBackground,
919                                  &gcv);
920     }
921     else
922       ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable,
923                                  GCFunction, &gcv);
924   }
925
926   XPutImage(ximageinfo->disp, ximageinfo->drawable, ximageinfo->gc,
927             ximageinfo->ximage, src_x, src_y, dst_x, dst_y, w, h);
928 }
929
930 /* free up anything cached in the local Ximage structure.
931  */
932
933 void freeXImage(Image *image, XImageInfo *ximageinfo)
934 {
935   if (ximageinfo->index != NULL)        /* if we allocated colors */
936   {
937     if (ximageinfo->no > 0 && !ximageinfo->rootimage)   /* don't free root colors */
938       XFreeColors(ximageinfo->disp, ximageinfo->cmap, ximageinfo->index, ximageinfo->no, 0);
939     lfree(ximageinfo->index);
940   }
941   if (ximageinfo->gc)
942     XFreeGC(ximageinfo->disp, ximageinfo->gc);
943   lfree((byte *)ximageinfo->ximage->data);
944   ximageinfo->ximage->data= NULL;
945   XDestroyImage(ximageinfo->ximage);
946   lfree((byte *)ximageinfo);
947   /* should we free private color map to ??? */
948 }