home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / xpaint-244 / src / image.c < prev    next >
C/C++ Source or Header  |  1996-05-31  |  18KB  |  766 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1993, David Koblas (koblas@netcom.com)               | */
  3. /* | Copyright 1995, 1996 Torsten Martinsen (bullestock@dk-online.dk)  | */
  4. /* |                                       | */
  5. /* | Permission to use, copy, modify, and to distribute this software  | */
  6. /* | and its documentation for any purpose is hereby granted without   | */
  7. /* | fee, provided that the above copyright notice appear in all       | */
  8. /* | copies and that both that copyright notice and this permission    | */
  9. /* | notice appear in supporting documentation.     There is no           | */
  10. /* | representations about the suitability of this software for           | */
  11. /* | any purpose.  this software is provided "as is" without express   | */
  12. /* | or implied warranty.                           | */
  13. /* |                                       | */
  14. /* +-------------------------------------------------------------------+ */
  15.  
  16. /* $Id: image.c,v 1.5 1996/05/31 06:31:44 torsten Exp $ */
  17.  
  18. #include <X11/Intrinsic.h>
  19. #include "image.h"
  20. #include "hash.h"
  21. #include "palette.h"
  22. #include "misc.h"
  23. #include "protocol.h"
  24.  
  25. #define HASH_SIZE    128
  26.  
  27. /*
  28. **  Faster macros for "fast" Image <-> XImage loops
  29.  */
  30.  
  31. #define ZINDEX(x, y, img) (((y) * img->bytes_per_line) + \
  32.                (((x) * img->bits_per_pixel) >> 3))
  33.  
  34. #define ZINDEX32(x, y, img) ((y) * img->bytes_per_line) + ((x) << 2)
  35. #define ZINDEX8(x, y, img)  ((y) * img->bytes_per_line) + (x)
  36. #define ZINDEX1(x, y, img)  ((y) * img->bytes_per_line) + ((x) >> 3)
  37.  
  38. static void imageToPixmapLoop(Display *, Image *, Palette *, XImage *, Pixmap *);
  39.  
  40. /*
  41.  * The functions below are written from X11R5 MIT's code (XImUtil.c)
  42.  *
  43.  * The idea is to have faster functions than the standard XGetPixel function
  44.  * to scan the image data. Indeed we can speed up things by suppressing tests
  45.  * performed for each pixel. We do exactly the same tests but at the image
  46.  * level. Assuming that we use only ZPixmap images.
  47.  */
  48.  
  49. static unsigned long low_bits_table[] =
  50. {
  51.     0x00000000, 0x00000001, 0x00000003, 0x00000007,
  52.     0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
  53.     0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
  54.     0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
  55.     0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
  56.     0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
  57.     0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
  58.     0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
  59.     0xffffffff
  60. };
  61.  
  62. /*
  63. **  Actual Image routines
  64. **
  65. **
  66.  */
  67.  
  68.  
  69. Image *
  70. ImageNew(int width, int height)
  71. {
  72.     Image *image = XtNew(Image);
  73.  
  74.     image->refCount = 1;
  75.     image->isBW = False;
  76.     image->isGrey = False;
  77.     image->cmapPacked = False;
  78.     image->cmapSize = 0;
  79.     image->cmapData = NULL;
  80.     image->width = width;
  81.     image->height = height;
  82.     image->sourceColormap = None;
  83.     image->sourcePixmap = None;
  84.     image->sourceMask = None;
  85.     image->scale = 3;
  86.     if (width == 0 || height == 0)
  87.     image->data = NULL;
  88.     else
  89.     image->data = (unsigned char *) XtMalloc(width * height * sizeof(char) * 3);
  90.     image->maskData = NULL;
  91.     return image;
  92. }
  93.  
  94. Image *
  95. ImageNewCmap(int width, int height, int size)
  96. {
  97.     Image *image = ImageNew(0, 0);
  98.  
  99.     if (size == 0)
  100.     image->scale = 3;
  101.     else if (size <= 256)
  102.     image->scale = 1;
  103.     else
  104.     image->scale = sizeof(short) / sizeof(char);
  105.  
  106.     image->width = width;
  107.     image->height = height;
  108.     image->data = (unsigned char *)
  109.     XtMalloc(width * height * sizeof(char) * image->scale);
  110.     if (size != 0)
  111.     image->cmapData = (unsigned char *) XtMalloc(size * sizeof(char) * 3);
  112.     image->cmapSize = size;
  113.  
  114.     return image;
  115. }
  116.  
  117. Image *
  118. ImageNewBW(int width, int height)
  119. {
  120.     Image *image = ImageNewCmap(width, height, 2);
  121.  
  122.     image->isBW = True;
  123.     image->cmapData[0] = 0;
  124.     image->cmapData[1] = 0;
  125.     image->cmapData[2] = 0;
  126.     image->cmapData[3] = 255;
  127.     image->cmapData[4] = 255;
  128.     image->cmapData[5] = 255;
  129.  
  130.     return image;
  131. }
  132.  
  133. Image *
  134. ImageNewGrey(int width, int height)
  135. {
  136.     int i;
  137.     Image *image = ImageNewCmap(width, height, 256);
  138.  
  139.     image->isGrey = True;
  140.     for (i = 0; i < image->cmapSize; i++) {
  141.     image->cmapData[i * 3 + 0] = i;
  142.     image->cmapData[i * 3 + 1] = i;
  143.     image->cmapData[i * 3 + 2] = i;
  144.     }
  145.  
  146.     return image;
  147. }
  148.  
  149. void 
  150. ImageMakeMask(Image * image)
  151. {
  152.     image->maskData = (unsigned char *)
  153.     XtMalloc(image->width * image->height * sizeof(char));
  154. }
  155.  
  156.  
  157. void 
  158. ImageDelete(Image * image)
  159. {
  160.     image->refCount--;
  161.     if (image->refCount > 0)
  162.     return;
  163.  
  164.     if (image->cmapSize > 0 && image->cmapData != NULL)
  165.     XtFree((XtPointer) image->cmapData);
  166.     if (image->data != NULL)
  167.     XtFree((XtPointer) image->data);
  168.     if (image->maskData != NULL)
  169.     XtFree((XtPointer) image->maskData);
  170.     XtFree((XtPointer) image);
  171. }
  172.  
  173. /*
  174. **  Convert a colormap image into a RGB image
  175. **    useful for writers which only deal with RGB and not
  176. **    colormaps
  177.  */
  178. Image *
  179. ImageToRGB(Image * image)
  180. {
  181.     unsigned char *ip, *op;
  182.     Image *out;
  183.     int x, y;
  184.  
  185.     if (image->cmapSize == 0) {
  186.     image->refCount++;
  187.     return image;
  188.     }
  189.     out = ImageNew(image->width, image->height);
  190.     op = image->data;
  191.  
  192.     for (y = 0; y < image->height; y++) {
  193.     for (x = 0; x < image->width; x++) {
  194.         ip = ImagePixel(image, x, y);
  195.         *op++ = *ip++;
  196.         *op++ = *ip++;
  197.         *op++ = *ip++;
  198.     }
  199.     }
  200.  
  201.     out->isBW = image->isBW;
  202.     out->isGrey = False;
  203.     out->width = image->width;
  204.     out->height = image->height;
  205.  
  206.     image->cmapPacked = False;
  207.  
  208.     return out;
  209. }
  210.  
  211. /*
  212. **  Create a nice image for writing routines.
  213.  */
  214. Image *
  215. PixmapToImage(Widget w, Pixmap pix, Colormap cmap)
  216. {
  217.     XImage *xim;
  218.     Image *image;
  219.     Display *dpy = XtDisplay(w);
  220.     int x, y;
  221.     int width, height;
  222.     unsigned char *ptr, *data;
  223.     unsigned short *sptr;
  224.     int format = 0;
  225.     void *htable = NULL;
  226.     Palette *map = PaletteFind(w, cmap);
  227.     unsigned long lbt;
  228.  
  229.     GetPixmapWHD(dpy, pix, &width, &height, NULL);
  230.     xim = XGetImage(dpy, pix, 0, 0, width, height, AllPlanes, ZPixmap);
  231.  
  232.     if (map == NULL)
  233.     map = PaletteGetDefault(w);
  234.  
  235.     if (map->isMapped) {
  236.     unsigned char *cptr;
  237.  
  238.     image = ImageNewCmap(width, height, map->ncolors);
  239.     cptr = image->cmapData;
  240.  
  241.     for (y = 0; y < map->ncolors; y++, cptr += 3) {
  242.         XColor *col = PaletteLookup(map, y);
  243.         unsigned char r = col->red >> 8;
  244.         unsigned char g = col->green >> 8;
  245.         unsigned char b = col->blue >> 8;
  246.  
  247.         cptr[0] = r;
  248.         cptr[1] = g;
  249.         cptr[2] = b;
  250.     }
  251.     } else {
  252.     image = ImageNew(width, height);
  253.     }
  254.  
  255.     ptr = image->data;
  256.     sptr = (unsigned short *) image->data;
  257.     data = (unsigned char *) xim->data;
  258.     lbt = low_bits_table[xim->depth];
  259.  
  260.     for (y = 0; y < height; y++) {
  261.     for (x = 0; x < width; x++) {
  262.         XColor *col;
  263.         Pixel pixel;
  264.         unsigned char r, g, b;
  265.  
  266.         if (xim->bits_per_pixel == 8)
  267.         pixel = data[ZINDEX8(x, y, xim)] & lbt;
  268.         else
  269.         pixel = XGetPixel(xim, x, y);
  270.  
  271.         if (map->isMapped) {
  272.         if (map->ncolors <= 256)
  273.             *ptr++ = pixel;
  274.         else
  275.             *sptr++ = pixel;
  276.  
  277.         r = image->cmapData[pixel * 3 + 0];
  278.         g = image->cmapData[pixel * 3 + 1];
  279.         b = image->cmapData[pixel * 3 + 2];
  280.         } else {
  281.         col = PaletteLookup(map, pixel);
  282.  
  283.         *ptr++ = r = col->red >> 8;
  284.         *ptr++ = g = col->green >> 8;
  285.         *ptr++ = b = col->blue >> 8;
  286.         }
  287.  
  288.         if (r != g || g != b)
  289.         format = 2;
  290.         else if (format == 0 && r != 0 && r != 255)
  291.         format = 1;
  292.     }
  293.  
  294.     if (y % 64 == 0)
  295.         StateTimeStep();
  296.     }
  297.  
  298.     /*
  299.     **    Check to see if we just created a B&W or Grey scale image?
  300.      */
  301.     if (format == 0 || format == 1) {
  302.     int newSize;
  303.     unsigned char *newMap;
  304.     unsigned char *ip;
  305.  
  306.     if (format == 0) {
  307.         newSize = 2;
  308.         newMap = (unsigned char *) XtCalloc(sizeof(char) * 3, 2);
  309.         newMap[0 + 0] = 0;
  310.         newMap[0 + 1] = 0;
  311.         newMap[0 + 2] = 0;
  312.         newMap[3 + 0] = 255;
  313.         newMap[3 + 1] = 255;
  314.         newMap[3 + 2] = 255;
  315.     } else {
  316.         newSize = 256;
  317.         newMap = (unsigned char *) XtCalloc(sizeof(char) * 3, 256);
  318.         for (y = 0; y < 256; y++) {
  319.         newMap[y * 3 + 0] = y;
  320.         newMap[y * 3 + 1] = y;
  321.         newMap[y * 3 + 2] = y;
  322.         }
  323.     }
  324.  
  325.     ip = image->data;
  326.     for (y = 0; y < height; y++) {
  327.         for (x = 0; x < width; x++, ip++) {
  328.         unsigned char *rgb;
  329.  
  330.         rgb = ImagePixel(image, x, y);
  331.  
  332.         if (format == 0 && *rgb == 255) {
  333.             *ip = 1;
  334.         } else {
  335.             *ip = *rgb;
  336.         }
  337.         }
  338.     }
  339.  
  340.     if (image->cmapData != NULL)
  341.         XtFree((XtPointer) image->cmapData);
  342.  
  343.     image->cmapSize = newSize;
  344.     image->cmapData = newMap;
  345.  
  346.     if (format == 0)
  347.         image->isBW = True;
  348.     else if (format == 1)
  349.         image->isGrey = True;
  350.     }
  351.     image->sourceColormap = (unsigned long) cmap;
  352.     image->sourcePixmap = (unsigned long) pix;
  353.  
  354.     if (htable != NULL)
  355.     HashDestroy(htable);
  356.     XDestroyImage(xim);
  357.  
  358.     return image;
  359. }
  360.  
  361. void 
  362. PixmapToImageMask(Widget w, Image * image, Pixmap mask)
  363. {
  364.     XImage *xim;
  365.     int width, height;
  366.     int x, y, endX, endY;
  367.     unsigned char *ip;
  368.     Display *dpy = XtDisplay(w);
  369.  
  370.     image->sourceMask = mask;
  371.     GetPixmapWHD(dpy, mask, &width, &height, NULL);
  372.     xim = XGetImage(dpy, mask, 0, 0, width, height, AllPlanes, ZPixmap);
  373.  
  374.     ImageMakeMask(image);
  375.     ip = image->maskData;
  376.  
  377.     if ((endX = image->width) > width)
  378.     endX = width;
  379.     if ((endY = image->height) > height)
  380.     endY = height;
  381.  
  382.     for (y = 0; y < endY; y++) {
  383.     for (x = 0; x < endX; x++)
  384.         *ip++ = (Boolean) XGetPixel(xim, x, y);
  385.     for (; x < image->width; x++)
  386.         *ip++ = True;
  387.     }
  388.     XDestroyImage(xim);
  389. }
  390.  
  391. /*
  392. **  Compress an image into a nice number of
  393. **   colors for display purposes.
  394.  */
  395. static Image *
  396. quantizeColormap(Image * input, Palette * map, Boolean flag)
  397. {
  398.     Image *output;
  399.     unsigned char *op;
  400.     int x, y;
  401.     int ncol;
  402.  
  403.     /*
  404.     **    If the output is either B&W or grey do something
  405.     **     fast and easy.
  406.      */
  407.     if (!map->isGrey)
  408.     return ImageCompress(input, map->ncolors, 0);
  409.  
  410.     ncol = map->ncolors > 256 ? 256 : map->ncolors;
  411.     output = ImageNewCmap(input->width, input->height, ncol);
  412.  
  413.     op = output->data;
  414.  
  415.     for (y = 0; y < ncol; y++) {
  416.     unsigned char v = ((float) y / (float) (ncol - 1)) * 255.0;
  417.     ImageSetCmap(output, y, v, v, v);
  418.     }
  419.  
  420.     for (y = 0; y < input->height; y++) {
  421.     for (x = 0; x < input->width; x++, op++) {
  422.         unsigned char *dp, v;
  423.  
  424.         dp = ImagePixel(input, x, y);
  425.         v = (dp[0] * 11 + dp[1] * 16 + dp[2] * 5) >> 5;    /* pp=.33R+.5G+.17B */
  426.         *op = (int) (((float) v / 256.0) * (float) ncol);
  427.     }
  428.     }
  429.  
  430.     output->maskData = input->maskData;
  431.     input->maskData = NULL;
  432.     ImageDelete(input);
  433.     return output;
  434. }
  435.  
  436. /* static */ void             /* GRR writePNG change */
  437. compressColormap(Image * image)
  438. {
  439.     unsigned char used[32768];
  440.     int size = image->width * image->height;
  441.     int i, count, newSize;
  442.     unsigned char *newMap;
  443.     unsigned short *isp;
  444.     unsigned char *icp;
  445.  
  446.     if (image->cmapSize <= 2 || image->cmapPacked)
  447.     return;
  448.  
  449.     memset(used, False, sizeof(used));
  450.  
  451.     /*
  452.     **    Find out usage information over the colormap 
  453.      */
  454.     count = 0;
  455.     if (image->cmapSize > 256) {
  456.     isp = (unsigned short *) image->data;
  457.     for (i = 0; i < size && count != image->cmapSize; i++, isp++) {
  458.         if (!used[*isp]) {
  459.         used[*isp] = True;
  460.         count++;
  461.         }
  462.     }
  463.     } else {
  464.     icp = image->data;
  465.     for (i = 0; i < size && count != image->cmapSize; i++, icp++) {
  466.         if (!used[*icp]) {
  467.         used[*icp] = True;
  468.         count++;
  469.         }
  470.     }
  471.     }
  472.  
  473.     /*
  474.     **    Colormap is fully used.
  475.      */
  476.     if (count == image->cmapSize) {
  477.     image->cmapPacked = True;
  478.     return;
  479.     }
  480.     /*
  481.     **    Now build the remapping colormap, and
  482.     **      set the index.
  483.      */
  484.     newSize = count;
  485.     newMap = (unsigned char *) XtCalloc(count, sizeof(unsigned char) * 3);
  486.     for (count = i = 0; i < image->cmapSize; i++) {
  487.     if (!used[i])
  488.         continue;
  489.     newMap[count * 3 + 0] = image->cmapData[i * 3 + 0];
  490.     newMap[count * 3 + 1] = image->cmapData[i * 3 + 1];
  491.     newMap[count * 3 + 2] = image->cmapData[i * 3 + 2];
  492.     used[i] = count++;
  493.     }
  494.  
  495.     if (image->cmapSize > 256 && newSize > 256) {
  496.     isp = (unsigned short *) image->data;
  497.     for (i = 0; i < size; i++, isp++)
  498.         *isp = used[*isp];
  499.     } else if (image->cmapSize > 256 && newSize <= 256) {
  500.     /*
  501.     **  Map a big colormap down to a small one.
  502.      */
  503.     isp = (unsigned short *) image->data;
  504.     icp = image->data;
  505.     for (i = 0; i < size; i++, icp++, isp++)
  506.         *icp = used[*isp];
  507.  
  508.     image->data = (unsigned char *)
  509.         XtRealloc((XtPointer) image->data, size * sizeof(unsigned char));
  510.     } else {
  511.     icp = image->data;
  512.     for (i = 0; i < size; i++, icp++)
  513.         *icp = used[*icp];
  514.     }
  515.  
  516.     XtFree((XtPointer) image->cmapData);
  517.     image->cmapData = newMap;
  518.     image->cmapSize = newSize;
  519.     image->cmapPacked = True;
  520.     image->isGrey = False;
  521. }
  522.  
  523. /*
  524. **  Convert an input image into a nice pixmap 
  525. **   so we can edit it.
  526. **
  527. **  Side effect     -- always destroy the input image
  528.  */
  529. Boolean
  530. ImageToPixmap(Image * image, Widget w, Pixmap * pix, Colormap * cmap)
  531. {
  532.     Display *dpy = XtDisplay(w);
  533.     Palette *map;
  534.     XImage *xim;
  535.     int width = image->width, height = image->height;
  536.  
  537.     map = PaletteCreate(w);
  538.     *cmap = map->cmap;
  539.  
  540.     if ((*pix = XCreatePixmap(dpy, DefaultRootWindow(dpy),
  541.                   width, height, map->depth)) == None)
  542.     return False;
  543.  
  544.     if ((xim = NewXImage(dpy, NULL, map->depth, width, height)) == NULL) {
  545.     XFreePixmap(dpy, *pix);
  546.     return False;
  547.     }
  548.     if ((image->cmapSize > map->ncolors) ||
  549.     (image->cmapSize == 0 && map->isMapped))
  550.     image = quantizeColormap(image, map, False);
  551.  
  552.     if (image->cmapSize > 0)
  553.     compressColormap(image);
  554.  
  555.     imageToPixmapLoop(dpy, image, map, xim, pix);
  556.  
  557.     return True;
  558. }
  559.  
  560. Pixmap
  561. MaskDataToPixmap(Widget w, int width, int height,
  562.          char *data, XRectangle * rect)
  563. {
  564.     Display *dpy = XtDisplay(w);
  565.     GC gc;
  566.     Pixmap mask;
  567.     XImage *xim;
  568.     int x, y;
  569.     int xs, ys;
  570.     unsigned char *ucp;
  571.     int pWidth, pHeight;
  572.  
  573.     if (data == NULL)
  574.     return None;
  575.  
  576.     if (rect == NULL) {
  577.     xs = 0;
  578.     ys = 0;
  579.     pWidth = width;
  580.     pHeight = height;
  581.     } else {
  582.     xs = rect->x;
  583.     ys = rect->y;
  584.     pWidth = rect->width;
  585.     pHeight = rect->height;
  586.     }
  587.  
  588.     mask = XCreatePixmap(dpy, DefaultRootWindow(dpy), pWidth, pHeight, 1);
  589.     gc = XCreateGC(dpy, mask, 0, 0);
  590.     xim = NewXImage(dpy, NULL, 1, pWidth, pHeight);
  591.  
  592.     if (xim->byte_order != xim->bitmap_bit_order) {
  593.     for (y = 0; y < pHeight; y++) {
  594.         ucp = (unsigned char *) (data + (width * (y + ys)) + xs);
  595.         for (x = 0; x < pWidth; x++, ucp++)
  596.         XPutPixel(xim, x, y, *ucp);
  597.     }
  598.     } else {
  599.     unsigned char *op = (unsigned char *) xim->data;
  600.     unsigned char *cp;
  601.  
  602.     if (xim->bitmap_bit_order == MSBFirst) {
  603.         for (y = 0; y < pHeight; y++) {
  604.         ucp = (unsigned char *) (data + (width * (y + ys)) + xs);
  605.         for (x = 0; x < pWidth; x++, ucp++) {
  606.             unsigned char v = 0x80 >> (x & 7);
  607.  
  608.             cp = &op[ZINDEX1(x, y, xim)];
  609.             if (*ucp)
  610.             *cp |= v;
  611.             else
  612.             *cp &= ~v;
  613.         }
  614.         }
  615.     } else {
  616.         for (y = 0; y < pHeight; y++) {
  617.         ucp = (unsigned char *) (data + (width * (y + ys)) + xs);
  618.         for (x = 0; x < pWidth; x++, ucp++) {
  619.             unsigned char v = 0x01 << (x & 7);
  620.  
  621.             cp = &op[ZINDEX1(x, y, xim)];
  622.             if (*ucp)
  623.             *cp |= v;
  624.             else
  625.             *cp &= ~v;
  626.         }
  627.         }
  628.     }
  629.  
  630.     }
  631.  
  632.     XPutImage(dpy, mask, gc, xim, 0, 0, 0, 0, pWidth, pHeight);
  633.     XFreeGC(dpy, gc);
  634.  
  635.     XDestroyImage(xim);
  636.  
  637.     return mask;
  638. }
  639.  
  640. Pixmap
  641. ImageMaskToPixmap(Widget w, Image * image)
  642. {
  643.     return MaskDataToPixmap(w, image->width,
  644.                 image->height, (char *) image->maskData, NULL);
  645. }
  646.  
  647. /*
  648. **  Convert an input image into a nice pixmap 
  649. **   so we can edit it.
  650. **
  651. **  Side effect     -- always destroy the input image
  652.  */
  653. static void 
  654. imageToPixmapLoop(Display * dpy, Image * image,
  655.           Palette * map, XImage * xim, Pixmap * pix)
  656. {
  657.     GC gc;
  658.     int x, y;
  659.     int width = image->width, height = image->height;
  660.  
  661.     if (image->cmapSize > 0) {
  662.     unsigned short *sdp = (unsigned short *) image->data;
  663.     unsigned char *cdp = (unsigned char *) image->data;
  664.     Pixel *list = (Pixel *) XtCalloc(sizeof(Pixel), image->cmapSize);
  665.     XColor *xcol = (XColor *) XtCalloc(sizeof(XColor), image->cmapSize);
  666.  
  667.     for (y = 0; y < image->cmapSize; y++) {
  668.         xcol[y].red = image->cmapData[y * 3 + 0] << 8;
  669.         xcol[y].green = image->cmapData[y * 3 + 1] << 8;
  670.         xcol[y].blue = image->cmapData[y * 3 + 2] << 8;
  671.     }
  672.  
  673.     PaletteAllocN(map, xcol, image->cmapSize, list);
  674.  
  675.     if (xim->bits_per_pixel == 8) {
  676.         unsigned char *data = (unsigned char *) xim->data;
  677.  
  678.         for (y = 0; y < height; y++)
  679.         for (x = 0; x < width; x++, sdp++, cdp++)
  680.             data[ZINDEX8(x, y, xim)] = list[image->cmapSize > 256 ? *sdp : *cdp];
  681.     } else {
  682.         /*
  683.         **    Slow loop
  684.          */
  685.         for (y = 0; y < height; y++) {
  686.         for (x = 0; x < width; x++, sdp++, cdp++)
  687.             XPutPixel(xim, x, y, list[image->cmapSize > 256 ? *sdp : *cdp]);
  688.         if (y % 256 == 0)
  689.             StateTimeStep();
  690.         }
  691.     }
  692.  
  693.     XtFree((XtPointer) list);
  694.     XtFree((XtPointer) xcol);
  695.     } else {
  696.     int step = 64 * 256 / width;
  697.     unsigned char *cp = image->data;
  698.  
  699.     for (y = 0; y < height; y++) {
  700.         for (x = 0; x < width; x++) {
  701.         XColor c;
  702.         Pixel p;
  703.  
  704.         c.red = *cp++ << 8;
  705.         c.green = *cp++ << 8;
  706.         c.blue = *cp++ << 8;
  707.  
  708.         p = PaletteAlloc(map, &c);
  709.  
  710.         if (xim->bits_per_pixel == 8)
  711.             xim->data[ZINDEX8(x, y, xim)] = p;
  712.         else
  713.             XPutPixel(xim, x, y, p);
  714.         }
  715.  
  716.         if (y % step == 0)
  717.         StateTimeStep();
  718.     }
  719.     }
  720.  
  721.     gc = XCreateGC(dpy, *pix, 0, 0);
  722.     XPutImage(dpy, *pix, gc, xim, 0, 0, 0, 0, width, height);
  723.     XFreeGC(dpy, gc);
  724.  
  725.     XDestroyImage(xim);
  726.  
  727.     ImageDelete(image);
  728. }
  729.  
  730.  
  731. /*
  732.  * Convert an Image to a Pixmap, using specified colormap.
  733.  * Unless pix == None, a new pixmap is created.
  734.  */
  735. Boolean
  736. ImageToPixmapCmap(Image * image, Widget w, Pixmap * pix, Colormap cmap)
  737. {
  738.     Display *dpy = XtDisplay(w);
  739.     Palette *map;
  740.     XImage *xim;
  741.     int width = image->width, height = image->height;
  742.  
  743.     if ((map = PaletteFind(w, cmap)) == NULL)
  744.     map = PaletteGetDefault(w);
  745.  
  746.     if (*pix == None) {
  747.     if ((*pix = XCreatePixmap(dpy, RootWindowOfScreen(XtScreen(w)),
  748.                   width, height, map->depth)) == None)
  749.         return False;
  750.     }
  751.     if ((xim = NewXImage(dpy, NULL, map->depth, width, height)) == NULL) {
  752.     XFreePixmap(dpy, *pix);
  753.     return False;
  754.     }
  755.     if ((image->cmapSize > map->ncolors) ||
  756.     (image->cmapSize == 0 && map->isMapped))
  757.     image = quantizeColormap(image, map, False);
  758.  
  759.     if (image->cmapSize > 0)
  760.     compressColormap(image);
  761.  
  762.     imageToPixmapLoop(dpy, image, map, xim, pix);
  763.  
  764.     return True;
  765. }
  766.