Edit

IABSD.fr/xenocara/lib/libXpm/src/scan.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2012-03-10 14:30:32
    Hash : 0a69d040
    Message : Update to libXpm 3.5.10

  • lib/libXpm/src/scan.c
  • /*
     * Copyright (C) 1989-95 GROUPE BULL
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy
     * of this software and associated documentation files (the "Software"), to
     * deal in the Software without restriction, including without limitation the
     * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     * sell copies of the Software, and to permit persons to whom the Software is
     * furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice shall be included in
     * all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the name of GROUPE BULL shall not be
     * used in advertising or otherwise to promote the sale, use or other dealings
     * in this Software without prior written authorization from GROUPE BULL.
     */
    
    /*****************************************************************************\
    * scan.c:                                                                     *
    *                                                                             *
    *  XPM library                                                                *
    *  Scanning utility for XPM file format                                       *
    *                                                                             *
    *  Developed by Arnaud Le Hors                                                *
    \*****************************************************************************/
    
    /*
     * The code related to FOR_MSW has been added by
     * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
     */
    
    /*
     * The code related to AMIGA has been added by
     * Lorens Younes (d93-hyo@nada.kth.se) 4/96
     */
    
    /* October 2004, source code review by Thomas Biege <thomas@suse.de> */
    
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    #include "XpmI.h"
    
    #define MAXPRINTABLE 92			/* number of printable ascii chars
    					 * minus \ and " for string compat
    					 * and ? to avoid ANSI trigraphs. */
    
    static const char *printable =
    " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\
    ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
    
    /*
     * printable begin with a space, so in most case, due to my algorithm, when
     * the number of different colors is less than MAXPRINTABLE, it will give a
     * char follow by "nothing" (a space) in the readable xpm file
     */
    
    
    typedef struct {
        Pixel *pixels;
        unsigned int *pixelindex;
        unsigned int size;
        unsigned int ncolors;
        unsigned int mask_pixel;		/* whether there is or not */
    }      PixelsMap;
    
    LFUNC(storePixel, int, (Pixel pixel, PixelsMap *pmap,
    			unsigned int *index_return));
    
    LFUNC(storeMaskPixel, int, (Pixel pixel, PixelsMap *pmap,
    			    unsigned int *index_return));
    
    typedef int (*storeFuncPtr)(Pixel pixel, PixelsMap *pmap,
    			    unsigned int *index_return);
    
    #ifndef FOR_MSW
    # ifndef AMIGA
    LFUNC(GetImagePixels, int, (XImage *image, unsigned int width,
    			    unsigned int height, PixelsMap *pmap));
    
    LFUNC(GetImagePixels32, int, (XImage *image, unsigned int width,
    			      unsigned int height, PixelsMap *pmap));
    
    LFUNC(GetImagePixels16, int, (XImage *image, unsigned int width,
    			      unsigned int height, PixelsMap *pmap));
    
    LFUNC(GetImagePixels8, int, (XImage *image, unsigned int width,
    			     unsigned int height, PixelsMap *pmap));
    
    LFUNC(GetImagePixels1, int, (XImage *image, unsigned int width,
    			     unsigned int height, PixelsMap *pmap,
    			     storeFuncPtr storeFunc));
    # else /* AMIGA */
    LFUNC(AGetImagePixels, int, (XImage *image, unsigned int width,
    			     unsigned int height, PixelsMap *pmap,
    			     storeFuncPtr storeFunc));
    # endif/* AMIGA */
    #else  /* ndef FOR_MSW */
    LFUNC(MSWGetImagePixels, int, (Display *d, XImage *image, unsigned int width,
    			       unsigned int height, PixelsMap *pmap,
    			       storeFuncPtr storeFunc));
    #endif
    LFUNC(ScanTransparentColor, int, (XpmColor *color, unsigned int cpp,
    				  XpmAttributes *attributes));
    
    LFUNC(ScanOtherColors, int, (Display *display, XpmColor *colors,
    			     unsigned int ncolors,
    			     Pixel *pixels, unsigned int mask,
    			     unsigned int cpp, XpmAttributes *attributes));
    
    /*
     * This function stores the given pixel in the given arrays which are grown
     * if not large enough.
     */
    static int
    storePixel(
        Pixel		 pixel,
        PixelsMap		*pmap,
        unsigned int	*index_return)
    {
        unsigned int i;
        Pixel *p;
        unsigned int ncolors;
    
        if (*index_return) {		/* this is a transparent pixel! */
    	*index_return = 0;
    	return 0;
        }
        ncolors = pmap->ncolors;
        p = pmap->pixels + pmap->mask_pixel;
        for (i = pmap->mask_pixel; i < ncolors; i++, p++)
    	if (*p == pixel)
    	    break;
        if (i == ncolors) {
    	if (ncolors >= pmap->size) {
    	    pmap->size *= 2;
    	    p = (Pixel *) XpmRealloc(pmap->pixels, sizeof(Pixel) * pmap->size);
    	    if (!p)
    		return (1);
    	    pmap->pixels = p;
    
    	}
    	(pmap->pixels)[ncolors] = pixel;
    	pmap->ncolors++;
        }
        *index_return = i;
        return 0;
    }
    
    static int
    storeMaskPixel(
        Pixel		 pixel,
        PixelsMap		*pmap,
        unsigned int	*index_return)
    {
        if (!pixel) {
    	if (!pmap->ncolors) {
    	    pmap->ncolors = 1;
    	    (pmap->pixels)[0] = 0;
    	    pmap->mask_pixel = 1;
    	}
    	*index_return = 1;
        } else
    	*index_return = 0;
        return 0;
    }
    
    /* function call in case of error */
    #undef RETURN
    #define RETURN(status) \
    do { \
          ErrorStatus = status; \
          goto error; \
    } while(0)
    
    /*
     * This function scans the given image and stores the found informations in
     * the given XpmImage structure.
     */
    int
    XpmCreateXpmImageFromImage(
        Display		*display,
        XImage		*image,
        XImage		*shapeimage,
        XpmImage		*xpmimage,
        XpmAttributes	*attributes)
    {
        /* variables stored in the XpmAttributes structure */
        unsigned int cpp;
    
        /* variables to return */
        PixelsMap pmap;
        XpmColor *colorTable = NULL;
        int ErrorStatus = 0;
    
        /* calculation variables */
        unsigned int width = 0;
        unsigned int height = 0;
        unsigned int cppm;			/* minimum chars per pixel */
        unsigned int c;
    
        /* initialize pmap */
        pmap.pixels = NULL;
        pmap.pixelindex = NULL;
        pmap.size = 256;			/* should be enough most of the time */
        pmap.ncolors = 0;
        pmap.mask_pixel = 0;
    
        /*
         * get geometry
         */
        if (image) {
    	width = image->width;
    	height = image->height;
        } else if (shapeimage) {
    	width = shapeimage->width;
    	height = shapeimage->height;
        }
    
        /*
         * retrieve information from the XpmAttributes
         */
        if (attributes && (attributes->valuemask & XpmCharsPerPixel
    /* 3.2 backward compatibility code */
    		       || attributes->valuemask & XpmInfos))
    /* end 3.2 bc */
    	cpp = attributes->cpp;
        else
    	cpp = 0;
    
        if ((height > 0 && width >= UINT_MAX / height) ||
    	width * height >= UINT_MAX / sizeof(unsigned int))
    	RETURN(XpmNoMemory);
        pmap.pixelindex =
    	(unsigned int *) XpmCalloc(width * height, sizeof(unsigned int));
        if (!pmap.pixelindex)
    	RETURN(XpmNoMemory);
    
        if (pmap.size >= UINT_MAX / sizeof(Pixel))
    	RETURN(XpmNoMemory);
    
        pmap.pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * pmap.size);
        if (!pmap.pixels)
    	RETURN(XpmNoMemory);
    
        /*
         * scan shape mask if any
         */
        if (shapeimage) {
    #ifndef FOR_MSW
    # ifndef AMIGA
    	ErrorStatus = GetImagePixels1(shapeimage, width, height, &pmap,
    				      storeMaskPixel);
    # else
    	ErrorStatus = AGetImagePixels(shapeimage, width, height, &pmap,
    				      storeMaskPixel);
    # endif
    #else
    	ErrorStatus = MSWGetImagePixels(display, shapeimage, width, height,
    					&pmap, storeMaskPixel);
    #endif
    	if (ErrorStatus != XpmSuccess)
    	    RETURN(ErrorStatus);
        }
    
        /*
         * scan the image data
         *
         * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use optimized
         * functions, otherwise use slower but sure general one.
         *
         */
    
        if (image) {
    #ifndef FOR_MSW
    # ifndef AMIGA
    	if (((image->bits_per_pixel | image->depth) == 1)  &&
    	    (image->byte_order == image->bitmap_bit_order))
    	    ErrorStatus = GetImagePixels1(image, width, height, &pmap,
    					  storePixel);
    	else if (image->format == ZPixmap) {
    	    if (image->bits_per_pixel == 8)
    		ErrorStatus = GetImagePixels8(image, width, height, &pmap);
    	    else if (image->bits_per_pixel == 16)
    		ErrorStatus = GetImagePixels16(image, width, height, &pmap);
    	    else if (image->bits_per_pixel == 32)
    		ErrorStatus = GetImagePixels32(image, width, height, &pmap);
    	} else
    	    ErrorStatus = GetImagePixels(image, width, height, &pmap);
    # else
    	ErrorStatus = AGetImagePixels(image, width, height, &pmap,
    				      storePixel);
    # endif
    #else
    	ErrorStatus = MSWGetImagePixels(display, image, width, height, &pmap,
    					storePixel);
    #endif
    	if (ErrorStatus != XpmSuccess)
    	    RETURN(ErrorStatus);
        }
    
        /*
         * get rgb values and a string of char, and possibly a name for each
         * color
         */
        if (pmap.ncolors >= UINT_MAX / sizeof(XpmColor))
    	RETURN(XpmNoMemory);
        colorTable = (XpmColor *) XpmCalloc(pmap.ncolors, sizeof(XpmColor));
        if (!colorTable)
    	RETURN(XpmNoMemory);
    
        /* compute the minimal cpp */
        for (cppm = 1, c = MAXPRINTABLE; pmap.ncolors > c; cppm++)
    	c *= MAXPRINTABLE;
        if (cpp < cppm)
    	cpp = cppm;
    
        if (pmap.mask_pixel) {
    	ErrorStatus = ScanTransparentColor(colorTable, cpp, attributes);
    	if (ErrorStatus != XpmSuccess)
    	    RETURN(ErrorStatus);
        }
    
        ErrorStatus = ScanOtherColors(display, colorTable, pmap.ncolors,
    				  pmap.pixels, pmap.mask_pixel, cpp,
    				  attributes);
        if (ErrorStatus != XpmSuccess)
    	RETURN(ErrorStatus);
    
        /*
         * store found informations in the XpmImage structure
         */
        xpmimage->width = width;
        xpmimage->height = height;
        xpmimage->cpp = cpp;
        xpmimage->ncolors = pmap.ncolors;
        xpmimage->colorTable = colorTable;
        xpmimage->data = pmap.pixelindex;
    
        XpmFree(pmap.pixels);
        return (XpmSuccess);
    
    /* exit point in case of error, free only locally allocated variables */
    error:
        if (pmap.pixelindex)
    	XpmFree(pmap.pixelindex);
        if (pmap.pixels)
    	XpmFree(pmap.pixels);
        if (colorTable)
    	xpmFreeColorTable(colorTable, pmap.ncolors);
    
        return (ErrorStatus);
    }
    
    static int
    ScanTransparentColor(
        XpmColor		*color,
        unsigned int	 cpp,
        XpmAttributes	*attributes)
    {
        char *s;
        unsigned int a, b, c;
    
        /* first get a character string */
        a = 0;
        if (cpp >= UINT_MAX - 1)
    	return (XpmNoMemory);
        if (!(s = color->string = (char *) XpmMalloc(cpp + 1)))
    	return (XpmNoMemory);
        *s++ = printable[c = a % MAXPRINTABLE];
        for (b = 1; b < cpp; b++, s++)
    	*s = printable[c = ((a - c) / MAXPRINTABLE) % MAXPRINTABLE];
        *s = '\0';
    
        /* then retreive related info from the attributes if any */
        if (attributes && (attributes->valuemask & XpmColorTable
    /* 3.2 backward compatibility code */
    		       || attributes->valuemask & XpmInfos)
    /* end 3.2 bc */
    	&& attributes->mask_pixel != XpmUndefPixel) {
    
    	unsigned int key;
    	char **defaults = (char **) color;
    	char **mask_defaults;
    
    /* 3.2 backward compatibility code */
    	if (attributes->valuemask & XpmColorTable)
    /* end 3.2 bc */
    	    mask_defaults = (char **) (
    		attributes->colorTable + attributes->mask_pixel);
    /* 3.2 backward compatibility code */
    	else
    	    mask_defaults = (char **)
    		((XpmColor **) attributes->colorTable)[attributes->mask_pixel];
    /* end 3.2 bc */
    	for (key = 1; key <= NKEYS; key++) {
    	    if ((s = mask_defaults[key])) {
    		defaults[key] = (char *) xpmstrdup(s);
    		if (!defaults[key])
    		    return (XpmNoMemory);
    	    }
    	}
        } else {
    	color->c_color = (char *) xpmstrdup(TRANSPARENT_COLOR);
    	if (!color->c_color)
    	    return (XpmNoMemory);
        }
        return (XpmSuccess);
    }
    
    static int
    ScanOtherColors(
        Display		*display,
        XpmColor		*colors,
        unsigned int	 ncolors,
        Pixel		*pixels,
        unsigned int	 mask,
        unsigned int	 cpp,
        XpmAttributes	*attributes)
    {
        /* variables stored in the XpmAttributes structure */
        Colormap colormap;
        char *rgb_fname;
    
    #ifndef FOR_MSW
        xpmRgbName rgbn[MAX_RGBNAMES];
    #else
        xpmRgbName *rgbn = NULL;
    #endif
        int rgbn_max = 0;
        unsigned int i, j, c, i2;
        XpmColor *color;
        XColor *xcolors = NULL, *xcolor;
        char *colorname, *s;
        XpmColor *colorTable = NULL, **oldColorTable = NULL;
        unsigned int ancolors = 0;
        Pixel *apixels = NULL;
        unsigned int mask_pixel = 0;
        Bool found;
    
        /* retrieve information from the XpmAttributes */
        if (attributes && (attributes->valuemask & XpmColormap))
    	colormap = attributes->colormap;
        else
    	colormap = XDefaultColormap(display, XDefaultScreen(display));
        if (attributes && (attributes->valuemask & XpmRgbFilename))
    	rgb_fname = attributes->rgb_fname;
        else
    	rgb_fname = NULL;
    
        /* start from the right element */
        if (mask) {
    	colors++;
    	ncolors--;
    	pixels++;
        }
    
        /* first get character strings and rgb values */
        if (ncolors >= UINT_MAX / sizeof(XColor) || cpp >= UINT_MAX - 1)
    	return (XpmNoMemory);
        xcolors = (XColor *) XpmMalloc(sizeof(XColor) * ncolors);
        if (!xcolors)
    	return (XpmNoMemory);
    
        for (i = 0, i2 = mask, color = colors, xcolor = xcolors;
    	 i < ncolors; i++, i2++, color++, xcolor++, pixels++) {
    
    	if (!(s = color->string = (char *) XpmMalloc(cpp + 1))) {
    	    XpmFree(xcolors);
    	    return (XpmNoMemory);
    	}
    	*s++ = printable[c = i2 % MAXPRINTABLE];
    	for (j = 1; j < cpp; j++, s++)
    	    *s = printable[c = ((i2 - c) / MAXPRINTABLE) % MAXPRINTABLE];
    	*s = '\0';
    
    	xcolor->pixel = *pixels;
        }
        XQueryColors(display, colormap, xcolors, ncolors);
    
    #ifndef FOR_MSW
        /* read the rgb file if any was specified */
        if (rgb_fname)
    	rgbn_max = xpmReadRgbNames(attributes->rgb_fname, rgbn);
    #else
        /* FOR_MSW: rgb names and values are hardcoded in rgbtab.h */
        rgbn_max = xpmReadRgbNames(NULL, NULL);
    #endif
    
        if (attributes && attributes->valuemask & XpmColorTable) {
    	colorTable = attributes->colorTable;
    	ancolors = attributes->ncolors;
    	apixels = attributes->pixels;
    	mask_pixel = attributes->mask_pixel;
        }
    /* 3.2 backward compatibility code */
        else if (attributes && attributes->valuemask & XpmInfos) {
    	oldColorTable = (XpmColor **) attributes->colorTable;
    	ancolors = attributes->ncolors;
    	apixels = attributes->pixels;
    	mask_pixel = attributes->mask_pixel;
        }
    /* end 3.2 bc */
    
        for (i = 0, color = colors, xcolor = xcolors; i < ncolors;
    						  i++, color++, xcolor++) {
    
    	/* look for related info from the attributes if any */
    	found = False;
    	if (ancolors) {
    	    unsigned int offset = 0;
    
    	    for (j = 0; j < ancolors; j++) {
    		if (j == mask_pixel) {
    		    offset = 1;
    		    continue;
    		}
    		if (apixels[j - offset] == xcolor->pixel)
    		    break;
    	    }
    	    if (j != ancolors) {
    		unsigned int key;
    		char **defaults = (char **) color;
    		char **adefaults;
    
    /* 3.2 backward compatibility code */
    		if (oldColorTable)
    		    adefaults = (char **) oldColorTable[j];
    		else
    /* end 3.2 bc */
    		    adefaults = (char **) (colorTable + j);
    
    		found = True;
    		for (key = 1; key <= NKEYS; key++) {
    		    if ((s = adefaults[key]))
    			defaults[key] = (char *) xpmstrdup(s);
    		}
    	    }
    	}
    	if (!found) {
    	    /* if nothing found look for a color name */
    	    colorname = NULL;
    	    if (rgbn_max)
    		colorname = xpmGetRgbName(rgbn, rgbn_max, xcolor->red,
    					  xcolor->green, xcolor->blue);
    	    if (colorname)
    		color->c_color = (char *) xpmstrdup(colorname);
    	    else {
    		/* at last store the rgb value */
    		char buf[BUFSIZ];
    #ifndef FOR_MSW
    		sprintf(buf, "#%04X%04X%04X",
    			xcolor->red, xcolor->green, xcolor->blue);
    #else
    		sprintf(buf, "#%02x%02x%02x",
    			xcolor->red, xcolor->green, xcolor->blue);
    #endif
    		color->c_color = (char *) xpmstrdup(buf);
    	    }
    	    if (!color->c_color) {
    		XpmFree(xcolors);
    		xpmFreeRgbNames(rgbn, rgbn_max);
    		return (XpmNoMemory);
    	    }
    	}
        }
    
        XpmFree(xcolors);
        xpmFreeRgbNames(rgbn, rgbn_max);
        return (XpmSuccess);
    }
    
    #ifndef FOR_MSW
    # ifndef AMIGA
    /*
     * The functions below are written from X11R5 MIT's code (XImUtil.c)
     *
     * The idea is to have faster functions than the standard XGetPixel function
     * to scan the image data. Indeed we can speed up things by suppressing tests
     * performed for each pixel. We do exactly the same tests but at the image
     * level.
     */
    
    static unsigned long const low_bits_table[] = {
        0x00000000, 0x00000001, 0x00000003, 0x00000007,
        0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
        0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
        0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
        0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
        0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
        0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
        0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
        0xffffffff
    };
    
    /*
     * Default method to scan pixels of an image data structure.
     * The algorithm used is:
     *
     *	copy the source bitmap_unit or Zpixel into temp
     *	normalize temp if needed
     *	extract the pixel bits into return value
     *
     */
    
    static int
    GetImagePixels(
        XImage		*image,
        unsigned int	 width,
        unsigned int	 height,
        PixelsMap		*pmap)
    {
        char *src;
        char *dst;
        unsigned int *iptr;
        char *data;
        unsigned int x, y;
        int bits, depth, ibu, ibpp, offset, i;
        unsigned long lbt;
        Pixel pixel, px;
    
        data = image->data;
        iptr = pmap->pixelindex;
        depth = image->depth;
        lbt = low_bits_table[depth];
        ibpp = image->bits_per_pixel;
        offset = image->xoffset;
    
        if (image->bitmap_unit < 0)
    	    return (XpmNoMemory);
    
        if ((image->bits_per_pixel | image->depth) == 1) {
    	ibu = image->bitmap_unit;
    	for (y = 0; y < height; y++)
    	    for (x = 0; x < width; x++, iptr++) {
    		src = &data[XYINDEX(x, y, image)];
    		dst = (char *) &pixel;
    		pixel = 0;
    		for (i = ibu >> 3; --i >= 0;)
    		    *dst++ = *src++;
    		XYNORMALIZE(&pixel, image);
    		bits = (x + offset) % ibu;
    		pixel = ((((char *) &pixel)[bits >> 3]) >> (bits & 7)) & 1;
    		if (ibpp != depth)
    		    pixel &= lbt;
    		if (storePixel(pixel, pmap, iptr))
    		    return (XpmNoMemory);
    	    }
        } else if (image->format == XYPixmap) {
    	int nbytes, bpl, j;
    	long plane = 0;
    	ibu = image->bitmap_unit;
    	nbytes = ibu >> 3;
    	bpl = image->bytes_per_line;
    	for (y = 0; y < height; y++)
    	    for (x = 0; x < width; x++, iptr++) {
    		pixel = 0;
    		plane = 0;
    		for (i = depth; --i >= 0;) {
    		    src = &data[XYINDEX(x, y, image) + plane];
    		    dst = (char *) &px;
    		    px = 0;
    		    for (j = nbytes; --j >= 0;)
    			*dst++ = *src++;
    		    XYNORMALIZE(&px, image);
    		    bits = (x + offset) % ibu;
    		    pixel = (pixel << 1) |
    			    (((((char *) &px)[bits >> 3]) >> (bits & 7)) & 1);
    		    plane = plane + (bpl * height);
    		}
    		if (ibpp != depth)
    		    pixel &= lbt;
    		if (storePixel(pixel, pmap, iptr))
    		    return (XpmNoMemory);
    	    }
        } else if (image->format == ZPixmap) {
    	for (y = 0; y < height; y++)
    	    for (x = 0; x < width; x++, iptr++) {
    		src = &data[ZINDEX(x, y, image)];
    		dst = (char *) &px;
    		px = 0;
    		for (i = (ibpp + 7) >> 3; --i >= 0;)
    		    *dst++ = *src++;
    		ZNORMALIZE(&px, image);
    		pixel = 0;
    		for (i = sizeof(unsigned long); --i >= 0;)
    		    pixel = (pixel << 8) | ((unsigned char *) &px)[i];
    		if (ibpp == 4) {
    		    if (x & 1)
    			pixel >>= 4;
    		    else
    			pixel &= 0xf;
    		}
    		if (ibpp != depth)
    		    pixel &= lbt;
    		if (storePixel(pixel, pmap, iptr))
    		    return (XpmNoMemory);
    	    }
        } else
    	return (XpmColorError); /* actually a bad image */
        return (XpmSuccess);
    }
    
    /*
     * scan pixels of a 32-bits Z image data structure
     */
    
    #if !defined(WORD64) && !defined(LONG64)
    static unsigned long byteorderpixel = MSBFirst << 24;
    #endif
    
    static int
    GetImagePixels32(
        XImage		 *image,
        unsigned int	 width,
        unsigned int	 height,
        PixelsMap		*pmap)
    {
        unsigned char *addr;
        unsigned char *data;
        unsigned int *iptr;
        unsigned int x, y;
        unsigned long lbt;
        Pixel pixel;
        int depth;
    
        data = (unsigned char *) image->data;
        iptr = pmap->pixelindex;
        depth = image->depth;
        lbt = low_bits_table[depth];
    #if !defined(WORD64) && !defined(LONG64)
        if (*((char *) &byteorderpixel) == image->byte_order) {
    	for (y = 0; y < height; y++)
    	    for (x = 0; x < width; x++, iptr++) {
    		addr = &data[ZINDEX32(x, y, image)];
    		pixel = *((unsigned long *) addr);
    		if (depth != 32)
    		    pixel &= lbt;
    		if (storePixel(pixel, pmap, iptr))
    		    return (XpmNoMemory);
    	    }
        } else
    #endif
        if (image->byte_order == MSBFirst)
    	for (y = 0; y < height; y++)
    	    for (x = 0; x < width; x++, iptr++) {
    		addr = &data[ZINDEX32(x, y, image)];
    		pixel = ((unsigned long) addr[0] << 24 |
    			 (unsigned long) addr[1] << 16 |
    			 (unsigned long) addr[2] << 8 |
    			 addr[3]);
    		if (depth != 32)
    		    pixel &= lbt;
    		if (storePixel(pixel, pmap, iptr))
    		    return (XpmNoMemory);
    	    }
        else
    	for (y = 0; y < height; y++)
    	    for (x = 0; x < width; x++, iptr++) {
    		addr = &data[ZINDEX32(x, y, image)];
    		pixel = (addr[0] |
    			 (unsigned long) addr[1] << 8 |
    			 (unsigned long) addr[2] << 16 |
    			 (unsigned long) addr[3] << 24);
    		if (depth != 32)
    		    pixel &= lbt;
    		if (storePixel(pixel, pmap, iptr))
    		    return (XpmNoMemory);
    	    }
        return (XpmSuccess);
    }
    
    /*
     * scan pixels of a 16-bits Z image data structure
     */
    
    static int
    GetImagePixels16(
        XImage		*image,
        unsigned int	 width,
        unsigned int	 height,
        PixelsMap		*pmap)
    {
        unsigned char *addr;
        unsigned char *data;
        unsigned int *iptr;
        unsigned int x, y;
        unsigned long lbt;
        Pixel pixel;
        int depth;
    
        data = (unsigned char *) image->data;
        iptr = pmap->pixelindex;
        depth = image->depth;
        lbt = low_bits_table[depth];
        if (image->byte_order == MSBFirst)
    	for (y = 0; y < height; y++)
    	    for (x = 0; x < width; x++, iptr++) {
    		addr = &data[ZINDEX16(x, y, image)];
    		pixel = addr[0] << 8 | addr[1];
    		if (depth != 16)
    		    pixel &= lbt;
    		if (storePixel(pixel, pmap, iptr))
    		    return (XpmNoMemory);
    	    }
        else
    	for (y = 0; y < height; y++)
    	    for (x = 0; x < width; x++, iptr++) {
    		addr = &data[ZINDEX16(x, y, image)];
    		pixel = addr[0] | addr[1] << 8;
    		if (depth != 16)
    		    pixel &= lbt;
    		if (storePixel(pixel, pmap, iptr))
    		    return (XpmNoMemory);
    	    }
        return (XpmSuccess);
    }
    
    /*
     * scan pixels of a 8-bits Z image data structure
     */
    
    static int
    GetImagePixels8(
        XImage		*image,
        unsigned int	 width,
        unsigned int	 height,
        PixelsMap		*pmap)
    {
        unsigned int *iptr;
        unsigned char *data;
        unsigned int x, y;
        unsigned long lbt;
        Pixel pixel;
        int depth;
    
        data = (unsigned char *) image->data;
        iptr = pmap->pixelindex;
        depth = image->depth;
        lbt = low_bits_table[depth];
        for (y = 0; y < height; y++)
    	for (x = 0; x < width; x++, iptr++) {
    	    pixel = data[ZINDEX8(x, y, image)];
    	    if (depth != 8)
    		pixel &= lbt;
    	    if (storePixel(pixel, pmap, iptr))
    		return (XpmNoMemory);
    	}
        return (XpmSuccess);
    }
    
    /*
     * scan pixels of a 1-bit depth Z image data structure
     */
    
    static int
    GetImagePixels1(
        XImage		*image,
        unsigned int	 width,
        unsigned int	 height,
        PixelsMap		 *pmap,
        storeFuncPtr	 storeFunc)
    {
        unsigned int *iptr;
        unsigned int x, y;
        char *data;
        Pixel pixel;
        int xoff, yoff, offset, bpl;
    
        data = image->data;
        iptr = pmap->pixelindex;
        offset = image->xoffset;
        bpl = image->bytes_per_line;
    
        if (image->bitmap_bit_order == MSBFirst)
    	for (y = 0; y < height; y++)
    	    for (x = 0; x < width; x++, iptr++) {
    		xoff = x + offset;
    		yoff = y * bpl + (xoff >> 3);
    		xoff &= 7;
    		pixel = (data[yoff] & (0x80 >> xoff)) ? 1 : 0;
    		if ((*storeFunc) (pixel, pmap, iptr))
    		    return (XpmNoMemory);
    	    }
        else
    	for (y = 0; y < height; y++)
    	    for (x = 0; x < width; x++, iptr++) {
    		xoff = x + offset;
    		yoff = y * bpl + (xoff >> 3);
    		xoff &= 7;
    		pixel = (data[yoff] & (1 << xoff)) ? 1 : 0;
    		if ((*storeFunc) (pixel, pmap, iptr))
    		    return (XpmNoMemory);
    	    }
        return (XpmSuccess);
    }
    
    # else /* AMIGA */
    
    #define CLEAN_UP(status) \
    do {\
        if (pixels) XpmFree (pixels);\
        if (tmp_img) FreeXImage (tmp_img);\
        return (status);\
    } while(0)
    
    static int
    AGetImagePixels (
        XImage        *image,
        unsigned int   width,
        unsigned int   height,
        PixelsMap     *pmap,
        int          (*storeFunc) (Pixel, PixelsMap *, unsigned int *))
    {
        unsigned int   *iptr;
        unsigned int    x, y;
        unsigned char  *pixels;
        XImage         *tmp_img;
    
        pixels = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*pixels));
        if (pixels == NULL)
    	return XpmNoMemory;
    
        tmp_img = AllocXImage ((((width+15)>>4)<<4), 1, image->rp->BitMap->Depth);
        if (tmp_img == NULL)
    	CLEAN_UP (XpmNoMemory);
    
        iptr = pmap->pixelindex;
        for (y = 0; y < height; ++y)
        {
    	ReadPixelLine8 (image->rp, 0, y, width, pixels, tmp_img->rp);
    	for (x = 0; x < width; ++x, ++iptr)
    	{
    	    if ((*storeFunc) (pixels[x], pmap, iptr))
    		CLEAN_UP (XpmNoMemory);
    	}
        }
    
        CLEAN_UP (XpmSuccess);
    }
    
    #undef CLEAN_UP
    
    # endif/* AMIGA */
    #else  /* ndef FOR_MSW */
    static int
    MSWGetImagePixels(
        Display	 *display,
        XImage	 *image,
        unsigned int  width,
        unsigned int  height,
        PixelsMap	 *pmap,
        int		(*storeFunc) (Pixel, PixelsMap*, unsigned int *))
    {
        unsigned int *iptr;
        unsigned int x, y;
        Pixel pixel;
    
        iptr = pmap->pixelindex;
    
        SelectObject(*display, image->bitmap);
        for (y = 0; y < height; y++) {
    	for (x = 0; x < width; x++, iptr++) {
    	    pixel = GetPixel(*display, x, y);
    	    if ((*storeFunc) (pixel, pmap, iptr))
    		return (XpmNoMemory);
    	}
        }
        return (XpmSuccess);
    }
    
    #endif
    
    #ifndef FOR_MSW
    # ifndef AMIGA
    int
    XpmCreateXpmImageFromPixmap(
        Display		*display,
        Pixmap		 pixmap,
        Pixmap		 shapemask,
        XpmImage		*xpmimage,
        XpmAttributes	*attributes)
    {
        XImage *ximage = NULL;
        XImage *shapeimage = NULL;
        unsigned int width = 0;
        unsigned int height = 0;
        int ErrorStatus;
    
        /* get geometry */
        if (attributes && attributes->valuemask & XpmSize) {
    	width = attributes->width;
    	height = attributes->height;
        }
        /* get the ximages */
        if (pixmap)
    	xpmCreateImageFromPixmap(display, pixmap, &ximage, &width, &height);
        if (shapemask)
    	xpmCreateImageFromPixmap(display, shapemask, &shapeimage,
    				 &width, &height);
    
        /* create the related XpmImage */
        ErrorStatus = XpmCreateXpmImageFromImage(display, ximage, shapeimage,
    					     xpmimage, attributes);
    
        /* destroy the ximages */
        if (ximage)
    	XDestroyImage(ximage);
        if (shapeimage)
    	XDestroyImage(shapeimage);
    
        return (ErrorStatus);
    }
    
    # endif/* not AMIGA */
    #endif /* ndef FOR_MSW */