1a966c04fSmrg/*
2a966c04fSmrg * Copyright (C) 1989-95 GROUPE BULL
3a966c04fSmrg *
4a966c04fSmrg * Permission is hereby granted, free of charge, to any person obtaining a copy
5a966c04fSmrg * of this software and associated documentation files (the "Software"), to
6a966c04fSmrg * deal in the Software without restriction, including without limitation the
7a966c04fSmrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8a966c04fSmrg * sell copies of the Software, and to permit persons to whom the Software is
9a966c04fSmrg * furnished to do so, subject to the following conditions:
10a966c04fSmrg *
11a966c04fSmrg * The above copyright notice and this permission notice shall be included in
12a966c04fSmrg * all copies or substantial portions of the Software.
13a966c04fSmrg *
14a966c04fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15a966c04fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16a966c04fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17a966c04fSmrg * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18a966c04fSmrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19a966c04fSmrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20a966c04fSmrg *
21a966c04fSmrg * Except as contained in this notice, the name of GROUPE BULL shall not be
22a966c04fSmrg * used in advertising or otherwise to promote the sale, use or other dealings
23a966c04fSmrg * in this Software without prior written authorization from GROUPE BULL.
24a966c04fSmrg */
25a966c04fSmrg
26a966c04fSmrg/*****************************************************************************\
27a966c04fSmrg* scan.c:                                                                     *
28a966c04fSmrg*                                                                             *
29a966c04fSmrg*  XPM library                                                                *
30a966c04fSmrg*  Scanning utility for XPM file format                                       *
31a966c04fSmrg*                                                                             *
32a966c04fSmrg*  Developed by Arnaud Le Hors                                                *
33a966c04fSmrg\*****************************************************************************/
34a966c04fSmrg
35a966c04fSmrg/*
36a966c04fSmrg * The code related to FOR_MSW has been added by
37a966c04fSmrg * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
38a966c04fSmrg */
39a966c04fSmrg
40a966c04fSmrg/*
41a966c04fSmrg * The code related to AMIGA has been added by
42a966c04fSmrg * Lorens Younes (d93-hyo@nada.kth.se) 4/96
43a966c04fSmrg */
44a966c04fSmrg
45a966c04fSmrg/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
46a966c04fSmrg
47a966c04fSmrg#ifdef HAVE_CONFIG_H
48a966c04fSmrg#include <config.h>
49a966c04fSmrg#endif
50a966c04fSmrg#include "XpmI.h"
51a966c04fSmrg
52a966c04fSmrg#define MAXPRINTABLE 92			/* number of printable ascii chars
53a966c04fSmrg					 * minus \ and " for string compat
54a966c04fSmrg					 * and ? to avoid ANSI trigraphs. */
55a966c04fSmrg
5697cf2ee2Smrgstatic const char *printable =
57a966c04fSmrg" .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\
58a966c04fSmrgASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
59a966c04fSmrg
60a966c04fSmrg/*
61a966c04fSmrg * printable begin with a space, so in most case, due to my algorithm, when
62a966c04fSmrg * the number of different colors is less than MAXPRINTABLE, it will give a
63a966c04fSmrg * char follow by "nothing" (a space) in the readable xpm file
64a966c04fSmrg */
65a966c04fSmrg
66a966c04fSmrg
67a966c04fSmrgtypedef struct {
68a966c04fSmrg    Pixel *pixels;
69a966c04fSmrg    unsigned int *pixelindex;
70a966c04fSmrg    unsigned int size;
71a966c04fSmrg    unsigned int ncolors;
72a966c04fSmrg    unsigned int mask_pixel;		/* whether there is or not */
73a966c04fSmrg}      PixelsMap;
74a966c04fSmrg
75a966c04fSmrgLFUNC(storePixel, int, (Pixel pixel, PixelsMap *pmap,
76a966c04fSmrg			unsigned int *index_return));
77a966c04fSmrg
78a966c04fSmrgLFUNC(storeMaskPixel, int, (Pixel pixel, PixelsMap *pmap,
79a966c04fSmrg			    unsigned int *index_return));
80a966c04fSmrg
81a966c04fSmrgtypedef int (*storeFuncPtr)(Pixel pixel, PixelsMap *pmap,
82a966c04fSmrg			    unsigned int *index_return);
83a966c04fSmrg
84a966c04fSmrg#ifndef FOR_MSW
85a966c04fSmrg# ifndef AMIGA
86a966c04fSmrgLFUNC(GetImagePixels, int, (XImage *image, unsigned int width,
87a966c04fSmrg			    unsigned int height, PixelsMap *pmap));
88a966c04fSmrg
89a966c04fSmrgLFUNC(GetImagePixels32, int, (XImage *image, unsigned int width,
90a966c04fSmrg			      unsigned int height, PixelsMap *pmap));
91a966c04fSmrg
92a966c04fSmrgLFUNC(GetImagePixels16, int, (XImage *image, unsigned int width,
93a966c04fSmrg			      unsigned int height, PixelsMap *pmap));
94a966c04fSmrg
95a966c04fSmrgLFUNC(GetImagePixels8, int, (XImage *image, unsigned int width,
96a966c04fSmrg			     unsigned int height, PixelsMap *pmap));
97a966c04fSmrg
98a966c04fSmrgLFUNC(GetImagePixels1, int, (XImage *image, unsigned int width,
99a966c04fSmrg			     unsigned int height, PixelsMap *pmap,
100a966c04fSmrg			     storeFuncPtr storeFunc));
101a966c04fSmrg# else /* AMIGA */
102a966c04fSmrgLFUNC(AGetImagePixels, int, (XImage *image, unsigned int width,
103a966c04fSmrg			     unsigned int height, PixelsMap *pmap,
104a966c04fSmrg			     storeFuncPtr storeFunc));
105a966c04fSmrg# endif/* AMIGA */
106a966c04fSmrg#else  /* ndef FOR_MSW */
107a966c04fSmrgLFUNC(MSWGetImagePixels, int, (Display *d, XImage *image, unsigned int width,
108a966c04fSmrg			       unsigned int height, PixelsMap *pmap,
109a966c04fSmrg			       storeFuncPtr storeFunc));
110a966c04fSmrg#endif
111a966c04fSmrgLFUNC(ScanTransparentColor, int, (XpmColor *color, unsigned int cpp,
112a966c04fSmrg				  XpmAttributes *attributes));
113a966c04fSmrg
11497cf2ee2SmrgLFUNC(ScanOtherColors, int, (Display *display, XpmColor *colors,
11597cf2ee2Smrg			     unsigned int ncolors,
116a966c04fSmrg			     Pixel *pixels, unsigned int mask,
117a966c04fSmrg			     unsigned int cpp, XpmAttributes *attributes));
118a966c04fSmrg
119a966c04fSmrg/*
120a966c04fSmrg * This function stores the given pixel in the given arrays which are grown
121a966c04fSmrg * if not large enough.
122a966c04fSmrg */
123a966c04fSmrgstatic int
1242e2dd055SmrgstorePixel(
1252e2dd055Smrg    Pixel		 pixel,
1262e2dd055Smrg    PixelsMap		*pmap,
1272e2dd055Smrg    unsigned int	*index_return)
128a966c04fSmrg{
129a966c04fSmrg    unsigned int i;
130a966c04fSmrg    Pixel *p;
131a966c04fSmrg    unsigned int ncolors;
132a966c04fSmrg
133a966c04fSmrg    if (*index_return) {		/* this is a transparent pixel! */
134a966c04fSmrg	*index_return = 0;
135a966c04fSmrg	return 0;
136a966c04fSmrg    }
137a966c04fSmrg    ncolors = pmap->ncolors;
138a966c04fSmrg    p = pmap->pixels + pmap->mask_pixel;
139a966c04fSmrg    for (i = pmap->mask_pixel; i < ncolors; i++, p++)
140a966c04fSmrg	if (*p == pixel)
141a966c04fSmrg	    break;
142a966c04fSmrg    if (i == ncolors) {
143a966c04fSmrg	if (ncolors >= pmap->size) {
144a966c04fSmrg	    pmap->size *= 2;
145a966c04fSmrg	    p = (Pixel *) XpmRealloc(pmap->pixels, sizeof(Pixel) * pmap->size);
146a966c04fSmrg	    if (!p)
147a966c04fSmrg		return (1);
148a966c04fSmrg	    pmap->pixels = p;
149a966c04fSmrg
150a966c04fSmrg	}
151a966c04fSmrg	(pmap->pixels)[ncolors] = pixel;
152a966c04fSmrg	pmap->ncolors++;
153a966c04fSmrg    }
154a966c04fSmrg    *index_return = i;
155a966c04fSmrg    return 0;
156a966c04fSmrg}
157a966c04fSmrg
158a966c04fSmrgstatic int
1592e2dd055SmrgstoreMaskPixel(
1602e2dd055Smrg    Pixel		 pixel,
1612e2dd055Smrg    PixelsMap		*pmap,
1622e2dd055Smrg    unsigned int	*index_return)
163a966c04fSmrg{
164a966c04fSmrg    if (!pixel) {
165a966c04fSmrg	if (!pmap->ncolors) {
166a966c04fSmrg	    pmap->ncolors = 1;
167a966c04fSmrg	    (pmap->pixels)[0] = 0;
168a966c04fSmrg	    pmap->mask_pixel = 1;
169a966c04fSmrg	}
170a966c04fSmrg	*index_return = 1;
171a966c04fSmrg    } else
172a966c04fSmrg	*index_return = 0;
173a966c04fSmrg    return 0;
174a966c04fSmrg}
175a966c04fSmrg
176a966c04fSmrg/* function call in case of error */
177a966c04fSmrg#undef RETURN
178a966c04fSmrg#define RETURN(status) \
179a966c04fSmrgdo { \
180a966c04fSmrg      ErrorStatus = status; \
181a966c04fSmrg      goto error; \
182a966c04fSmrg} while(0)
183a966c04fSmrg
184a966c04fSmrg/*
18519569120Smrg * This function scans the given image and stores the found information in
186a966c04fSmrg * the given XpmImage structure.
187a966c04fSmrg */
188a966c04fSmrgint
1892e2dd055SmrgXpmCreateXpmImageFromImage(
1902e2dd055Smrg    Display		*display,
1912e2dd055Smrg    XImage		*image,
1922e2dd055Smrg    XImage		*shapeimage,
1932e2dd055Smrg    XpmImage		*xpmimage,
1942e2dd055Smrg    XpmAttributes	*attributes)
195a966c04fSmrg{
196a966c04fSmrg    /* variables stored in the XpmAttributes structure */
197a966c04fSmrg    unsigned int cpp;
198a966c04fSmrg
199a966c04fSmrg    /* variables to return */
200a966c04fSmrg    PixelsMap pmap;
201a966c04fSmrg    XpmColor *colorTable = NULL;
202a966c04fSmrg    int ErrorStatus = 0;
203a966c04fSmrg
204a966c04fSmrg    /* calculation variables */
205a966c04fSmrg    unsigned int width = 0;
206a966c04fSmrg    unsigned int height = 0;
207a966c04fSmrg    unsigned int cppm;			/* minimum chars per pixel */
208a966c04fSmrg    unsigned int c;
209a966c04fSmrg
210a966c04fSmrg    /* initialize pmap */
211a966c04fSmrg    pmap.pixels = NULL;
212a966c04fSmrg    pmap.pixelindex = NULL;
213a966c04fSmrg    pmap.size = 256;			/* should be enough most of the time */
214a966c04fSmrg    pmap.ncolors = 0;
215a966c04fSmrg    pmap.mask_pixel = 0;
216a966c04fSmrg
217a966c04fSmrg    /*
218a966c04fSmrg     * get geometry
219a966c04fSmrg     */
220a966c04fSmrg    if (image) {
221a966c04fSmrg	width = image->width;
222a966c04fSmrg	height = image->height;
223a966c04fSmrg    } else if (shapeimage) {
224a966c04fSmrg	width = shapeimage->width;
225a966c04fSmrg	height = shapeimage->height;
226a966c04fSmrg    }
227a966c04fSmrg
228a966c04fSmrg    /*
229a966c04fSmrg     * retrieve information from the XpmAttributes
230a966c04fSmrg     */
231a966c04fSmrg    if (attributes && (attributes->valuemask & XpmCharsPerPixel
232a966c04fSmrg/* 3.2 backward compatibility code */
233a966c04fSmrg		       || attributes->valuemask & XpmInfos))
234a966c04fSmrg/* end 3.2 bc */
235a966c04fSmrg	cpp = attributes->cpp;
236a966c04fSmrg    else
237a966c04fSmrg	cpp = 0;
238a966c04fSmrg
239a966c04fSmrg    if ((height > 0 && width >= UINT_MAX / height) ||
240a966c04fSmrg	width * height >= UINT_MAX / sizeof(unsigned int))
241a966c04fSmrg	RETURN(XpmNoMemory);
242a966c04fSmrg    pmap.pixelindex =
243a966c04fSmrg	(unsigned int *) XpmCalloc(width * height, sizeof(unsigned int));
244a966c04fSmrg    if (!pmap.pixelindex)
245a966c04fSmrg	RETURN(XpmNoMemory);
246a966c04fSmrg
24797cf2ee2Smrg    if (pmap.size >= UINT_MAX / sizeof(Pixel))
248a966c04fSmrg	RETURN(XpmNoMemory);
249a966c04fSmrg
250a966c04fSmrg    pmap.pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * pmap.size);
251a966c04fSmrg    if (!pmap.pixels)
252a966c04fSmrg	RETURN(XpmNoMemory);
253a966c04fSmrg
254a966c04fSmrg    /*
255a966c04fSmrg     * scan shape mask if any
256a966c04fSmrg     */
257a966c04fSmrg    if (shapeimage) {
258a966c04fSmrg#ifndef FOR_MSW
259a966c04fSmrg# ifndef AMIGA
260a966c04fSmrg	ErrorStatus = GetImagePixels1(shapeimage, width, height, &pmap,
261a966c04fSmrg				      storeMaskPixel);
262a966c04fSmrg# else
263a966c04fSmrg	ErrorStatus = AGetImagePixels(shapeimage, width, height, &pmap,
264a966c04fSmrg				      storeMaskPixel);
265a966c04fSmrg# endif
266a966c04fSmrg#else
267a966c04fSmrg	ErrorStatus = MSWGetImagePixels(display, shapeimage, width, height,
268a966c04fSmrg					&pmap, storeMaskPixel);
269a966c04fSmrg#endif
270a966c04fSmrg	if (ErrorStatus != XpmSuccess)
271a966c04fSmrg	    RETURN(ErrorStatus);
272a966c04fSmrg    }
273a966c04fSmrg
274a966c04fSmrg    /*
275a966c04fSmrg     * scan the image data
27697cf2ee2Smrg     *
277a966c04fSmrg     * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use optimized
278a966c04fSmrg     * functions, otherwise use slower but sure general one.
27997cf2ee2Smrg     *
280a966c04fSmrg     */
281a966c04fSmrg
282a966c04fSmrg    if (image) {
283a966c04fSmrg#ifndef FOR_MSW
284a966c04fSmrg# ifndef AMIGA
285a966c04fSmrg	if (((image->bits_per_pixel | image->depth) == 1)  &&
286a966c04fSmrg	    (image->byte_order == image->bitmap_bit_order))
287a966c04fSmrg	    ErrorStatus = GetImagePixels1(image, width, height, &pmap,
288a966c04fSmrg					  storePixel);
289a966c04fSmrg	else if (image->format == ZPixmap) {
290a966c04fSmrg	    if (image->bits_per_pixel == 8)
291a966c04fSmrg		ErrorStatus = GetImagePixels8(image, width, height, &pmap);
292a966c04fSmrg	    else if (image->bits_per_pixel == 16)
293a966c04fSmrg		ErrorStatus = GetImagePixels16(image, width, height, &pmap);
294a966c04fSmrg	    else if (image->bits_per_pixel == 32)
295a966c04fSmrg		ErrorStatus = GetImagePixels32(image, width, height, &pmap);
296a966c04fSmrg	} else
297a966c04fSmrg	    ErrorStatus = GetImagePixels(image, width, height, &pmap);
298a966c04fSmrg# else
299a966c04fSmrg	ErrorStatus = AGetImagePixels(image, width, height, &pmap,
300a966c04fSmrg				      storePixel);
301a966c04fSmrg# endif
302a966c04fSmrg#else
303a966c04fSmrg	ErrorStatus = MSWGetImagePixels(display, image, width, height, &pmap,
304a966c04fSmrg					storePixel);
305a966c04fSmrg#endif
306a966c04fSmrg	if (ErrorStatus != XpmSuccess)
307a966c04fSmrg	    RETURN(ErrorStatus);
308a966c04fSmrg    }
309a966c04fSmrg
310a966c04fSmrg    /*
311a966c04fSmrg     * get rgb values and a string of char, and possibly a name for each
312a966c04fSmrg     * color
313a966c04fSmrg     */
314a966c04fSmrg    if (pmap.ncolors >= UINT_MAX / sizeof(XpmColor))
315a966c04fSmrg	RETURN(XpmNoMemory);
316a966c04fSmrg    colorTable = (XpmColor *) XpmCalloc(pmap.ncolors, sizeof(XpmColor));
317a966c04fSmrg    if (!colorTable)
318a966c04fSmrg	RETURN(XpmNoMemory);
319a966c04fSmrg
320a966c04fSmrg    /* compute the minimal cpp */
321a966c04fSmrg    for (cppm = 1, c = MAXPRINTABLE; pmap.ncolors > c; cppm++)
322a966c04fSmrg	c *= MAXPRINTABLE;
323a966c04fSmrg    if (cpp < cppm)
324a966c04fSmrg	cpp = cppm;
325a966c04fSmrg
326a966c04fSmrg    if (pmap.mask_pixel) {
327a966c04fSmrg	ErrorStatus = ScanTransparentColor(colorTable, cpp, attributes);
328a966c04fSmrg	if (ErrorStatus != XpmSuccess)
329a966c04fSmrg	    RETURN(ErrorStatus);
330a966c04fSmrg    }
331a966c04fSmrg
332a966c04fSmrg    ErrorStatus = ScanOtherColors(display, colorTable, pmap.ncolors,
333a966c04fSmrg				  pmap.pixels, pmap.mask_pixel, cpp,
334a966c04fSmrg				  attributes);
335a966c04fSmrg    if (ErrorStatus != XpmSuccess)
336a966c04fSmrg	RETURN(ErrorStatus);
337a966c04fSmrg
338a966c04fSmrg    /*
33919569120Smrg     * store found information in the XpmImage structure
340a966c04fSmrg     */
341a966c04fSmrg    xpmimage->width = width;
342a966c04fSmrg    xpmimage->height = height;
343a966c04fSmrg    xpmimage->cpp = cpp;
344a966c04fSmrg    xpmimage->ncolors = pmap.ncolors;
345a966c04fSmrg    xpmimage->colorTable = colorTable;
346a966c04fSmrg    xpmimage->data = pmap.pixelindex;
347a966c04fSmrg
348a966c04fSmrg    XpmFree(pmap.pixels);
349a966c04fSmrg    return (XpmSuccess);
350a966c04fSmrg
351a966c04fSmrg/* exit point in case of error, free only locally allocated variables */
352a966c04fSmrgerror:
353a966c04fSmrg    if (pmap.pixelindex)
354a966c04fSmrg	XpmFree(pmap.pixelindex);
355a966c04fSmrg    if (pmap.pixels)
356a966c04fSmrg	XpmFree(pmap.pixels);
357a966c04fSmrg    if (colorTable)
358a966c04fSmrg	xpmFreeColorTable(colorTable, pmap.ncolors);
359a966c04fSmrg
360a966c04fSmrg    return (ErrorStatus);
361a966c04fSmrg}
362a966c04fSmrg
363a966c04fSmrgstatic int
3642e2dd055SmrgScanTransparentColor(
3652e2dd055Smrg    XpmColor		*color,
3662e2dd055Smrg    unsigned int	 cpp,
3672e2dd055Smrg    XpmAttributes	*attributes)
368a966c04fSmrg{
369a966c04fSmrg    char *s;
370a966c04fSmrg    unsigned int a, b, c;
371a966c04fSmrg
372a966c04fSmrg    /* first get a character string */
373a966c04fSmrg    a = 0;
374a966c04fSmrg    if (cpp >= UINT_MAX - 1)
375a966c04fSmrg	return (XpmNoMemory);
376a966c04fSmrg    if (!(s = color->string = (char *) XpmMalloc(cpp + 1)))
377a966c04fSmrg	return (XpmNoMemory);
378a966c04fSmrg    *s++ = printable[c = a % MAXPRINTABLE];
379a966c04fSmrg    for (b = 1; b < cpp; b++, s++)
380a966c04fSmrg	*s = printable[c = ((a - c) / MAXPRINTABLE) % MAXPRINTABLE];
381a966c04fSmrg    *s = '\0';
382a966c04fSmrg
38319569120Smrg    /* then retrieve related info from the attributes if any */
384a966c04fSmrg    if (attributes && (attributes->valuemask & XpmColorTable
385a966c04fSmrg/* 3.2 backward compatibility code */
386a966c04fSmrg		       || attributes->valuemask & XpmInfos)
387a966c04fSmrg/* end 3.2 bc */
388a966c04fSmrg	&& attributes->mask_pixel != XpmUndefPixel) {
389a966c04fSmrg
390a966c04fSmrg	unsigned int key;
391a966c04fSmrg	char **defaults = (char **) color;
392a966c04fSmrg	char **mask_defaults;
393a966c04fSmrg
394a966c04fSmrg/* 3.2 backward compatibility code */
395a966c04fSmrg	if (attributes->valuemask & XpmColorTable)
396a966c04fSmrg/* end 3.2 bc */
397a966c04fSmrg	    mask_defaults = (char **) (
398a966c04fSmrg		attributes->colorTable + attributes->mask_pixel);
399a966c04fSmrg/* 3.2 backward compatibility code */
400a966c04fSmrg	else
401a966c04fSmrg	    mask_defaults = (char **)
402a966c04fSmrg		((XpmColor **) attributes->colorTable)[attributes->mask_pixel];
403a966c04fSmrg/* end 3.2 bc */
404a966c04fSmrg	for (key = 1; key <= NKEYS; key++) {
405a966c04fSmrg	    if ((s = mask_defaults[key])) {
406a966c04fSmrg		defaults[key] = (char *) xpmstrdup(s);
407a966c04fSmrg		if (!defaults[key])
408a966c04fSmrg		    return (XpmNoMemory);
409a966c04fSmrg	    }
410a966c04fSmrg	}
411a966c04fSmrg    } else {
412a966c04fSmrg	color->c_color = (char *) xpmstrdup(TRANSPARENT_COLOR);
413a966c04fSmrg	if (!color->c_color)
414a966c04fSmrg	    return (XpmNoMemory);
415a966c04fSmrg    }
416a966c04fSmrg    return (XpmSuccess);
417a966c04fSmrg}
418a966c04fSmrg
419a966c04fSmrgstatic int
4202e2dd055SmrgScanOtherColors(
4212e2dd055Smrg    Display		*display,
4222e2dd055Smrg    XpmColor		*colors,
4232e2dd055Smrg    unsigned int	 ncolors,
4242e2dd055Smrg    Pixel		*pixels,
4252e2dd055Smrg    unsigned int	 mask,
4262e2dd055Smrg    unsigned int	 cpp,
4272e2dd055Smrg    XpmAttributes	*attributes)
428a966c04fSmrg{
429a966c04fSmrg    /* variables stored in the XpmAttributes structure */
430a966c04fSmrg    Colormap colormap;
431a966c04fSmrg    char *rgb_fname;
432a966c04fSmrg
433a966c04fSmrg#ifndef FOR_MSW
434a966c04fSmrg    xpmRgbName rgbn[MAX_RGBNAMES];
435a966c04fSmrg#else
43697cf2ee2Smrg    xpmRgbName *rgbn = NULL;
43797cf2ee2Smrg#endif
438a966c04fSmrg    int rgbn_max = 0;
439a966c04fSmrg    unsigned int i, j, c, i2;
440a966c04fSmrg    XpmColor *color;
441a966c04fSmrg    XColor *xcolors = NULL, *xcolor;
442a966c04fSmrg    char *colorname, *s;
443a966c04fSmrg    XpmColor *colorTable = NULL, **oldColorTable = NULL;
444a966c04fSmrg    unsigned int ancolors = 0;
445a966c04fSmrg    Pixel *apixels = NULL;
446a966c04fSmrg    unsigned int mask_pixel = 0;
447a966c04fSmrg    Bool found;
448a966c04fSmrg
449a966c04fSmrg    /* retrieve information from the XpmAttributes */
450a966c04fSmrg    if (attributes && (attributes->valuemask & XpmColormap))
451a966c04fSmrg	colormap = attributes->colormap;
452a966c04fSmrg    else
453a966c04fSmrg	colormap = XDefaultColormap(display, XDefaultScreen(display));
454a966c04fSmrg    if (attributes && (attributes->valuemask & XpmRgbFilename))
455a966c04fSmrg	rgb_fname = attributes->rgb_fname;
456a966c04fSmrg    else
457a966c04fSmrg	rgb_fname = NULL;
458a966c04fSmrg
459a966c04fSmrg    /* start from the right element */
460a966c04fSmrg    if (mask) {
461a966c04fSmrg	colors++;
462a966c04fSmrg	ncolors--;
463a966c04fSmrg	pixels++;
464a966c04fSmrg    }
465a966c04fSmrg
466a966c04fSmrg    /* first get character strings and rgb values */
467a966c04fSmrg    if (ncolors >= UINT_MAX / sizeof(XColor) || cpp >= UINT_MAX - 1)
468a966c04fSmrg	return (XpmNoMemory);
469a966c04fSmrg    xcolors = (XColor *) XpmMalloc(sizeof(XColor) * ncolors);
470a966c04fSmrg    if (!xcolors)
471a966c04fSmrg	return (XpmNoMemory);
472a966c04fSmrg
473a966c04fSmrg    for (i = 0, i2 = mask, color = colors, xcolor = xcolors;
474a966c04fSmrg	 i < ncolors; i++, i2++, color++, xcolor++, pixels++) {
475a966c04fSmrg
476a966c04fSmrg	if (!(s = color->string = (char *) XpmMalloc(cpp + 1))) {
477a966c04fSmrg	    XpmFree(xcolors);
478a966c04fSmrg	    return (XpmNoMemory);
479a966c04fSmrg	}
480a966c04fSmrg	*s++ = printable[c = i2 % MAXPRINTABLE];
481a966c04fSmrg	for (j = 1; j < cpp; j++, s++)
482a966c04fSmrg	    *s = printable[c = ((i2 - c) / MAXPRINTABLE) % MAXPRINTABLE];
483a966c04fSmrg	*s = '\0';
484a966c04fSmrg
485a966c04fSmrg	xcolor->pixel = *pixels;
486a966c04fSmrg    }
487a966c04fSmrg    XQueryColors(display, colormap, xcolors, ncolors);
488a966c04fSmrg
489a966c04fSmrg#ifndef FOR_MSW
490a966c04fSmrg    /* read the rgb file if any was specified */
491a966c04fSmrg    if (rgb_fname)
492a966c04fSmrg	rgbn_max = xpmReadRgbNames(attributes->rgb_fname, rgbn);
493a966c04fSmrg#else
494a966c04fSmrg    /* FOR_MSW: rgb names and values are hardcoded in rgbtab.h */
495a966c04fSmrg    rgbn_max = xpmReadRgbNames(NULL, NULL);
496a966c04fSmrg#endif
497a966c04fSmrg
498a966c04fSmrg    if (attributes && attributes->valuemask & XpmColorTable) {
499a966c04fSmrg	colorTable = attributes->colorTable;
500a966c04fSmrg	ancolors = attributes->ncolors;
501a966c04fSmrg	apixels = attributes->pixels;
502a966c04fSmrg	mask_pixel = attributes->mask_pixel;
503a966c04fSmrg    }
504a966c04fSmrg/* 3.2 backward compatibility code */
505a966c04fSmrg    else if (attributes && attributes->valuemask & XpmInfos) {
506a966c04fSmrg	oldColorTable = (XpmColor **) attributes->colorTable;
507a966c04fSmrg	ancolors = attributes->ncolors;
508a966c04fSmrg	apixels = attributes->pixels;
509a966c04fSmrg	mask_pixel = attributes->mask_pixel;
510a966c04fSmrg    }
511a966c04fSmrg/* end 3.2 bc */
512a966c04fSmrg
513a966c04fSmrg    for (i = 0, color = colors, xcolor = xcolors; i < ncolors;
514a966c04fSmrg						  i++, color++, xcolor++) {
515a966c04fSmrg
516a966c04fSmrg	/* look for related info from the attributes if any */
517a966c04fSmrg	found = False;
518a966c04fSmrg	if (ancolors) {
519a966c04fSmrg	    unsigned int offset = 0;
520a966c04fSmrg
521a966c04fSmrg	    for (j = 0; j < ancolors; j++) {
522a966c04fSmrg		if (j == mask_pixel) {
523a966c04fSmrg		    offset = 1;
524a966c04fSmrg		    continue;
525a966c04fSmrg		}
526a966c04fSmrg		if (apixels[j - offset] == xcolor->pixel)
527a966c04fSmrg		    break;
528a966c04fSmrg	    }
529a966c04fSmrg	    if (j != ancolors) {
530a966c04fSmrg		unsigned int key;
531a966c04fSmrg		char **defaults = (char **) color;
532a966c04fSmrg		char **adefaults;
533a966c04fSmrg
534a966c04fSmrg/* 3.2 backward compatibility code */
535a966c04fSmrg		if (oldColorTable)
536a966c04fSmrg		    adefaults = (char **) oldColorTable[j];
537a966c04fSmrg		else
538a966c04fSmrg/* end 3.2 bc */
539a966c04fSmrg		    adefaults = (char **) (colorTable + j);
540a966c04fSmrg
541a966c04fSmrg		found = True;
542a966c04fSmrg		for (key = 1; key <= NKEYS; key++) {
543a966c04fSmrg		    if ((s = adefaults[key]))
544a966c04fSmrg			defaults[key] = (char *) xpmstrdup(s);
545a966c04fSmrg		}
546a966c04fSmrg	    }
547a966c04fSmrg	}
548a966c04fSmrg	if (!found) {
549a966c04fSmrg	    /* if nothing found look for a color name */
550a966c04fSmrg	    colorname = NULL;
551a966c04fSmrg	    if (rgbn_max)
552a966c04fSmrg		colorname = xpmGetRgbName(rgbn, rgbn_max, xcolor->red,
553a966c04fSmrg					  xcolor->green, xcolor->blue);
554a966c04fSmrg	    if (colorname)
555a966c04fSmrg		color->c_color = (char *) xpmstrdup(colorname);
556a966c04fSmrg	    else {
557a966c04fSmrg		/* at last store the rgb value */
558a966c04fSmrg		char buf[BUFSIZ];
559a966c04fSmrg#ifndef FOR_MSW
560a966c04fSmrg		sprintf(buf, "#%04X%04X%04X",
561a966c04fSmrg			xcolor->red, xcolor->green, xcolor->blue);
56297cf2ee2Smrg#else
563a966c04fSmrg		sprintf(buf, "#%02x%02x%02x",
564a966c04fSmrg			xcolor->red, xcolor->green, xcolor->blue);
56597cf2ee2Smrg#endif
566a966c04fSmrg		color->c_color = (char *) xpmstrdup(buf);
567a966c04fSmrg	    }
568a966c04fSmrg	    if (!color->c_color) {
569a966c04fSmrg		XpmFree(xcolors);
570a966c04fSmrg		xpmFreeRgbNames(rgbn, rgbn_max);
571a966c04fSmrg		return (XpmNoMemory);
572a966c04fSmrg	    }
573a966c04fSmrg	}
574a966c04fSmrg    }
575a966c04fSmrg
576a966c04fSmrg    XpmFree(xcolors);
577a966c04fSmrg    xpmFreeRgbNames(rgbn, rgbn_max);
578a966c04fSmrg    return (XpmSuccess);
579a966c04fSmrg}
580a966c04fSmrg
581a966c04fSmrg#ifndef FOR_MSW
582a966c04fSmrg# ifndef AMIGA
583a966c04fSmrg/*
584a966c04fSmrg * The functions below are written from X11R5 MIT's code (XImUtil.c)
585a966c04fSmrg *
586a966c04fSmrg * The idea is to have faster functions than the standard XGetPixel function
587a966c04fSmrg * to scan the image data. Indeed we can speed up things by suppressing tests
588a966c04fSmrg * performed for each pixel. We do exactly the same tests but at the image
589a966c04fSmrg * level.
590a966c04fSmrg */
591a966c04fSmrg
59297cf2ee2Smrgstatic unsigned long const low_bits_table[] = {
593a966c04fSmrg    0x00000000, 0x00000001, 0x00000003, 0x00000007,
594a966c04fSmrg    0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
595a966c04fSmrg    0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
596a966c04fSmrg    0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
597a966c04fSmrg    0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
598a966c04fSmrg    0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
599a966c04fSmrg    0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
600a966c04fSmrg    0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
601a966c04fSmrg    0xffffffff
602a966c04fSmrg};
603a966c04fSmrg
604a966c04fSmrg/*
605a966c04fSmrg * Default method to scan pixels of an image data structure.
606a966c04fSmrg * The algorithm used is:
607a966c04fSmrg *
608a966c04fSmrg *	copy the source bitmap_unit or Zpixel into temp
609a966c04fSmrg *	normalize temp if needed
610a966c04fSmrg *	extract the pixel bits into return value
611a966c04fSmrg *
612a966c04fSmrg */
613a966c04fSmrg
614a966c04fSmrgstatic int
6152e2dd055SmrgGetImagePixels(
6162e2dd055Smrg    XImage		*image,
6172e2dd055Smrg    unsigned int	 width,
6182e2dd055Smrg    unsigned int	 height,
6192e2dd055Smrg    PixelsMap		*pmap)
620a966c04fSmrg{
621a966c04fSmrg    char *src;
622a966c04fSmrg    char *dst;
623a966c04fSmrg    unsigned int *iptr;
624a966c04fSmrg    char *data;
625a966c04fSmrg    unsigned int x, y;
626a966c04fSmrg    int bits, depth, ibu, ibpp, offset, i;
627a966c04fSmrg    unsigned long lbt;
628a966c04fSmrg    Pixel pixel, px;
629a966c04fSmrg
630a966c04fSmrg    data = image->data;
631a966c04fSmrg    iptr = pmap->pixelindex;
632a966c04fSmrg    depth = image->depth;
633a966c04fSmrg    lbt = low_bits_table[depth];
634a966c04fSmrg    ibpp = image->bits_per_pixel;
635a966c04fSmrg    offset = image->xoffset;
636a966c04fSmrg
637a966c04fSmrg    if (image->bitmap_unit < 0)
638a966c04fSmrg	    return (XpmNoMemory);
639a966c04fSmrg
640a966c04fSmrg    if ((image->bits_per_pixel | image->depth) == 1) {
641a966c04fSmrg	ibu = image->bitmap_unit;
642a966c04fSmrg	for (y = 0; y < height; y++)
643a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
644a966c04fSmrg		src = &data[XYINDEX(x, y, image)];
645a966c04fSmrg		dst = (char *) &pixel;
646a966c04fSmrg		pixel = 0;
647a966c04fSmrg		for (i = ibu >> 3; --i >= 0;)
648a966c04fSmrg		    *dst++ = *src++;
649a966c04fSmrg		XYNORMALIZE(&pixel, image);
650a966c04fSmrg		bits = (x + offset) % ibu;
651a966c04fSmrg		pixel = ((((char *) &pixel)[bits >> 3]) >> (bits & 7)) & 1;
652a966c04fSmrg		if (ibpp != depth)
653a966c04fSmrg		    pixel &= lbt;
654a966c04fSmrg		if (storePixel(pixel, pmap, iptr))
655a966c04fSmrg		    return (XpmNoMemory);
656a966c04fSmrg	    }
657a966c04fSmrg    } else if (image->format == XYPixmap) {
658a966c04fSmrg	int nbytes, bpl, j;
659a966c04fSmrg	long plane = 0;
660a966c04fSmrg	ibu = image->bitmap_unit;
661a966c04fSmrg	nbytes = ibu >> 3;
662a966c04fSmrg	bpl = image->bytes_per_line;
663a966c04fSmrg	for (y = 0; y < height; y++)
664a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
665a966c04fSmrg		pixel = 0;
666a966c04fSmrg		plane = 0;
667a966c04fSmrg		for (i = depth; --i >= 0;) {
668a966c04fSmrg		    src = &data[XYINDEX(x, y, image) + plane];
669a966c04fSmrg		    dst = (char *) &px;
670a966c04fSmrg		    px = 0;
671a966c04fSmrg		    for (j = nbytes; --j >= 0;)
672a966c04fSmrg			*dst++ = *src++;
673a966c04fSmrg		    XYNORMALIZE(&px, image);
674a966c04fSmrg		    bits = (x + offset) % ibu;
675a966c04fSmrg		    pixel = (pixel << 1) |
676a966c04fSmrg			    (((((char *) &px)[bits >> 3]) >> (bits & 7)) & 1);
677a966c04fSmrg		    plane = plane + (bpl * height);
678a966c04fSmrg		}
679a966c04fSmrg		if (ibpp != depth)
680a966c04fSmrg		    pixel &= lbt;
681a966c04fSmrg		if (storePixel(pixel, pmap, iptr))
682a966c04fSmrg		    return (XpmNoMemory);
683a966c04fSmrg	    }
684a966c04fSmrg    } else if (image->format == ZPixmap) {
685a966c04fSmrg	for (y = 0; y < height; y++)
686a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
687a966c04fSmrg		src = &data[ZINDEX(x, y, image)];
688a966c04fSmrg		dst = (char *) &px;
689a966c04fSmrg		px = 0;
690a966c04fSmrg		for (i = (ibpp + 7) >> 3; --i >= 0;)
691a966c04fSmrg		    *dst++ = *src++;
692a966c04fSmrg		ZNORMALIZE(&px, image);
693a966c04fSmrg		pixel = 0;
694a966c04fSmrg		for (i = sizeof(unsigned long); --i >= 0;)
695a966c04fSmrg		    pixel = (pixel << 8) | ((unsigned char *) &px)[i];
696a966c04fSmrg		if (ibpp == 4) {
697a966c04fSmrg		    if (x & 1)
698a966c04fSmrg			pixel >>= 4;
699a966c04fSmrg		    else
700a966c04fSmrg			pixel &= 0xf;
701a966c04fSmrg		}
702a966c04fSmrg		if (ibpp != depth)
703a966c04fSmrg		    pixel &= lbt;
704a966c04fSmrg		if (storePixel(pixel, pmap, iptr))
705a966c04fSmrg		    return (XpmNoMemory);
706a966c04fSmrg	    }
707a966c04fSmrg    } else
708a966c04fSmrg	return (XpmColorError); /* actually a bad image */
709a966c04fSmrg    return (XpmSuccess);
710a966c04fSmrg}
711a966c04fSmrg
712a966c04fSmrg/*
713a966c04fSmrg * scan pixels of a 32-bits Z image data structure
714a966c04fSmrg */
715a966c04fSmrg
716a966c04fSmrg#if !defined(WORD64) && !defined(LONG64)
717a966c04fSmrgstatic unsigned long byteorderpixel = MSBFirst << 24;
718a966c04fSmrg#endif
719a966c04fSmrg
720a966c04fSmrgstatic int
7212e2dd055SmrgGetImagePixels32(
7222e2dd055Smrg    XImage		 *image,
7232e2dd055Smrg    unsigned int	 width,
7242e2dd055Smrg    unsigned int	 height,
7252e2dd055Smrg    PixelsMap		*pmap)
726a966c04fSmrg{
727a966c04fSmrg    unsigned char *addr;
728a966c04fSmrg    unsigned char *data;
729a966c04fSmrg    unsigned int *iptr;
730a966c04fSmrg    unsigned int x, y;
731a966c04fSmrg    unsigned long lbt;
732a966c04fSmrg    Pixel pixel;
733a966c04fSmrg    int depth;
734a966c04fSmrg
735a966c04fSmrg    data = (unsigned char *) image->data;
736a966c04fSmrg    iptr = pmap->pixelindex;
737a966c04fSmrg    depth = image->depth;
738a966c04fSmrg    lbt = low_bits_table[depth];
739a966c04fSmrg#if !defined(WORD64) && !defined(LONG64)
740a966c04fSmrg    if (*((char *) &byteorderpixel) == image->byte_order) {
741a966c04fSmrg	for (y = 0; y < height; y++)
742a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
743a966c04fSmrg		addr = &data[ZINDEX32(x, y, image)];
744a966c04fSmrg		pixel = *((unsigned long *) addr);
745a966c04fSmrg		if (depth != 32)
746a966c04fSmrg		    pixel &= lbt;
747a966c04fSmrg		if (storePixel(pixel, pmap, iptr))
748a966c04fSmrg		    return (XpmNoMemory);
749a966c04fSmrg	    }
750a966c04fSmrg    } else
751a966c04fSmrg#endif
752a966c04fSmrg    if (image->byte_order == MSBFirst)
753a966c04fSmrg	for (y = 0; y < height; y++)
754a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
755a966c04fSmrg		addr = &data[ZINDEX32(x, y, image)];
756a966c04fSmrg		pixel = ((unsigned long) addr[0] << 24 |
757a966c04fSmrg			 (unsigned long) addr[1] << 16 |
758a966c04fSmrg			 (unsigned long) addr[2] << 8 |
759a966c04fSmrg			 addr[3]);
760a966c04fSmrg		if (depth != 32)
761a966c04fSmrg		    pixel &= lbt;
762a966c04fSmrg		if (storePixel(pixel, pmap, iptr))
763a966c04fSmrg		    return (XpmNoMemory);
764a966c04fSmrg	    }
765a966c04fSmrg    else
766a966c04fSmrg	for (y = 0; y < height; y++)
767a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
768a966c04fSmrg		addr = &data[ZINDEX32(x, y, image)];
769a966c04fSmrg		pixel = (addr[0] |
770a966c04fSmrg			 (unsigned long) addr[1] << 8 |
771a966c04fSmrg			 (unsigned long) addr[2] << 16 |
772a966c04fSmrg			 (unsigned long) addr[3] << 24);
773a966c04fSmrg		if (depth != 32)
774a966c04fSmrg		    pixel &= lbt;
775a966c04fSmrg		if (storePixel(pixel, pmap, iptr))
776a966c04fSmrg		    return (XpmNoMemory);
777a966c04fSmrg	    }
778a966c04fSmrg    return (XpmSuccess);
779a966c04fSmrg}
780a966c04fSmrg
781a966c04fSmrg/*
782a966c04fSmrg * scan pixels of a 16-bits Z image data structure
783a966c04fSmrg */
784a966c04fSmrg
785a966c04fSmrgstatic int
7862e2dd055SmrgGetImagePixels16(
7872e2dd055Smrg    XImage		*image,
7882e2dd055Smrg    unsigned int	 width,
7892e2dd055Smrg    unsigned int	 height,
7902e2dd055Smrg    PixelsMap		*pmap)
791a966c04fSmrg{
792a966c04fSmrg    unsigned char *addr;
793a966c04fSmrg    unsigned char *data;
794a966c04fSmrg    unsigned int *iptr;
795a966c04fSmrg    unsigned int x, y;
796a966c04fSmrg    unsigned long lbt;
797a966c04fSmrg    Pixel pixel;
798a966c04fSmrg    int depth;
799a966c04fSmrg
800a966c04fSmrg    data = (unsigned char *) image->data;
801a966c04fSmrg    iptr = pmap->pixelindex;
802a966c04fSmrg    depth = image->depth;
803a966c04fSmrg    lbt = low_bits_table[depth];
804a966c04fSmrg    if (image->byte_order == MSBFirst)
805a966c04fSmrg	for (y = 0; y < height; y++)
806a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
807a966c04fSmrg		addr = &data[ZINDEX16(x, y, image)];
808a966c04fSmrg		pixel = addr[0] << 8 | addr[1];
809a966c04fSmrg		if (depth != 16)
810a966c04fSmrg		    pixel &= lbt;
811a966c04fSmrg		if (storePixel(pixel, pmap, iptr))
812a966c04fSmrg		    return (XpmNoMemory);
813a966c04fSmrg	    }
814a966c04fSmrg    else
815a966c04fSmrg	for (y = 0; y < height; y++)
816a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
817a966c04fSmrg		addr = &data[ZINDEX16(x, y, image)];
818a966c04fSmrg		pixel = addr[0] | addr[1] << 8;
819a966c04fSmrg		if (depth != 16)
820a966c04fSmrg		    pixel &= lbt;
821a966c04fSmrg		if (storePixel(pixel, pmap, iptr))
822a966c04fSmrg		    return (XpmNoMemory);
823a966c04fSmrg	    }
824a966c04fSmrg    return (XpmSuccess);
825a966c04fSmrg}
826a966c04fSmrg
827a966c04fSmrg/*
828a966c04fSmrg * scan pixels of a 8-bits Z image data structure
829a966c04fSmrg */
830a966c04fSmrg
831a966c04fSmrgstatic int
8322e2dd055SmrgGetImagePixels8(
8332e2dd055Smrg    XImage		*image,
8342e2dd055Smrg    unsigned int	 width,
8352e2dd055Smrg    unsigned int	 height,
8362e2dd055Smrg    PixelsMap		*pmap)
837a966c04fSmrg{
838a966c04fSmrg    unsigned int *iptr;
839a966c04fSmrg    unsigned char *data;
840a966c04fSmrg    unsigned int x, y;
841a966c04fSmrg    unsigned long lbt;
842a966c04fSmrg    Pixel pixel;
843a966c04fSmrg    int depth;
844a966c04fSmrg
845a966c04fSmrg    data = (unsigned char *) image->data;
846a966c04fSmrg    iptr = pmap->pixelindex;
847a966c04fSmrg    depth = image->depth;
848a966c04fSmrg    lbt = low_bits_table[depth];
849a966c04fSmrg    for (y = 0; y < height; y++)
850a966c04fSmrg	for (x = 0; x < width; x++, iptr++) {
851a966c04fSmrg	    pixel = data[ZINDEX8(x, y, image)];
852a966c04fSmrg	    if (depth != 8)
853a966c04fSmrg		pixel &= lbt;
854a966c04fSmrg	    if (storePixel(pixel, pmap, iptr))
855a966c04fSmrg		return (XpmNoMemory);
856a966c04fSmrg	}
857a966c04fSmrg    return (XpmSuccess);
858a966c04fSmrg}
859a966c04fSmrg
860a966c04fSmrg/*
861a966c04fSmrg * scan pixels of a 1-bit depth Z image data structure
862a966c04fSmrg */
863a966c04fSmrg
864a966c04fSmrgstatic int
8652e2dd055SmrgGetImagePixels1(
8662e2dd055Smrg    XImage		*image,
8672e2dd055Smrg    unsigned int	 width,
8682e2dd055Smrg    unsigned int	 height,
8692e2dd055Smrg    PixelsMap		 *pmap,
8702e2dd055Smrg    storeFuncPtr	 storeFunc)
871a966c04fSmrg{
872a966c04fSmrg    unsigned int *iptr;
873a966c04fSmrg    unsigned int x, y;
874a966c04fSmrg    char *data;
875a966c04fSmrg    Pixel pixel;
876a966c04fSmrg    int xoff, yoff, offset, bpl;
877a966c04fSmrg
878a966c04fSmrg    data = image->data;
879a966c04fSmrg    iptr = pmap->pixelindex;
880a966c04fSmrg    offset = image->xoffset;
881a966c04fSmrg    bpl = image->bytes_per_line;
882a966c04fSmrg
883a966c04fSmrg    if (image->bitmap_bit_order == MSBFirst)
884a966c04fSmrg	for (y = 0; y < height; y++)
885a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
886a966c04fSmrg		xoff = x + offset;
887a966c04fSmrg		yoff = y * bpl + (xoff >> 3);
888a966c04fSmrg		xoff &= 7;
889a966c04fSmrg		pixel = (data[yoff] & (0x80 >> xoff)) ? 1 : 0;
890a966c04fSmrg		if ((*storeFunc) (pixel, pmap, iptr))
891a966c04fSmrg		    return (XpmNoMemory);
892a966c04fSmrg	    }
893a966c04fSmrg    else
894a966c04fSmrg	for (y = 0; y < height; y++)
895a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
896a966c04fSmrg		xoff = x + offset;
897a966c04fSmrg		yoff = y * bpl + (xoff >> 3);
898a966c04fSmrg		xoff &= 7;
899a966c04fSmrg		pixel = (data[yoff] & (1 << xoff)) ? 1 : 0;
900a966c04fSmrg		if ((*storeFunc) (pixel, pmap, iptr))
901a966c04fSmrg		    return (XpmNoMemory);
902a966c04fSmrg	    }
903a966c04fSmrg    return (XpmSuccess);
904a966c04fSmrg}
905a966c04fSmrg
906a966c04fSmrg# else /* AMIGA */
907a966c04fSmrg
908a966c04fSmrg#define CLEAN_UP(status) \
909a966c04fSmrgdo {\
910a966c04fSmrg    if (pixels) XpmFree (pixels);\
911a966c04fSmrg    if (tmp_img) FreeXImage (tmp_img);\
912a966c04fSmrg    return (status);\
913a966c04fSmrg} while(0)
914a966c04fSmrg
915a966c04fSmrgstatic int
916a966c04fSmrgAGetImagePixels (
917a966c04fSmrg    XImage        *image,
918a966c04fSmrg    unsigned int   width,
919a966c04fSmrg    unsigned int   height,
920a966c04fSmrg    PixelsMap     *pmap,
9212e2dd055Smrg    int          (*storeFunc) (Pixel, PixelsMap *, unsigned int *))
922a966c04fSmrg{
923a966c04fSmrg    unsigned int   *iptr;
924a966c04fSmrg    unsigned int    x, y;
925a966c04fSmrg    unsigned char  *pixels;
926a966c04fSmrg    XImage         *tmp_img;
92797cf2ee2Smrg
928a966c04fSmrg    pixels = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*pixels));
929a966c04fSmrg    if (pixels == NULL)
930a966c04fSmrg	return XpmNoMemory;
93197cf2ee2Smrg
932a966c04fSmrg    tmp_img = AllocXImage ((((width+15)>>4)<<4), 1, image->rp->BitMap->Depth);
933a966c04fSmrg    if (tmp_img == NULL)
934a966c04fSmrg	CLEAN_UP (XpmNoMemory);
93597cf2ee2Smrg
936a966c04fSmrg    iptr = pmap->pixelindex;
937a966c04fSmrg    for (y = 0; y < height; ++y)
938a966c04fSmrg    {
939a966c04fSmrg	ReadPixelLine8 (image->rp, 0, y, width, pixels, tmp_img->rp);
940a966c04fSmrg	for (x = 0; x < width; ++x, ++iptr)
941a966c04fSmrg	{
942a966c04fSmrg	    if ((*storeFunc) (pixels[x], pmap, iptr))
943a966c04fSmrg		CLEAN_UP (XpmNoMemory);
944a966c04fSmrg	}
945a966c04fSmrg    }
94697cf2ee2Smrg
947a966c04fSmrg    CLEAN_UP (XpmSuccess);
948a966c04fSmrg}
949a966c04fSmrg
950a966c04fSmrg#undef CLEAN_UP
951a966c04fSmrg
952a966c04fSmrg# endif/* AMIGA */
953a966c04fSmrg#else  /* ndef FOR_MSW */
954a966c04fSmrgstatic int
9552e2dd055SmrgMSWGetImagePixels(
9562e2dd055Smrg    Display	 *display,
9572e2dd055Smrg    XImage	 *image,
9582e2dd055Smrg    unsigned int  width,
9592e2dd055Smrg    unsigned int  height,
9602e2dd055Smrg    PixelsMap	 *pmap,
9612e2dd055Smrg    int		(*storeFunc) (Pixel, PixelsMap*, unsigned int *))
962a966c04fSmrg{
963a966c04fSmrg    unsigned int *iptr;
964a966c04fSmrg    unsigned int x, y;
965a966c04fSmrg    Pixel pixel;
966a966c04fSmrg
967a966c04fSmrg    iptr = pmap->pixelindex;
968a966c04fSmrg
969a966c04fSmrg    SelectObject(*display, image->bitmap);
970a966c04fSmrg    for (y = 0; y < height; y++) {
971a966c04fSmrg	for (x = 0; x < width; x++, iptr++) {
972a966c04fSmrg	    pixel = GetPixel(*display, x, y);
973a966c04fSmrg	    if ((*storeFunc) (pixel, pmap, iptr))
974a966c04fSmrg		return (XpmNoMemory);
975a966c04fSmrg	}
976a966c04fSmrg    }
977a966c04fSmrg    return (XpmSuccess);
978a966c04fSmrg}
979a966c04fSmrg
980a966c04fSmrg#endif
981a966c04fSmrg
982a966c04fSmrg#ifndef FOR_MSW
983a966c04fSmrg# ifndef AMIGA
984a966c04fSmrgint
9852e2dd055SmrgXpmCreateXpmImageFromPixmap(
9862e2dd055Smrg    Display		*display,
9872e2dd055Smrg    Pixmap		 pixmap,
9882e2dd055Smrg    Pixmap		 shapemask,
9892e2dd055Smrg    XpmImage		*xpmimage,
9902e2dd055Smrg    XpmAttributes	*attributes)
991a966c04fSmrg{
992a966c04fSmrg    XImage *ximage = NULL;
993a966c04fSmrg    XImage *shapeimage = NULL;
994a966c04fSmrg    unsigned int width = 0;
995a966c04fSmrg    unsigned int height = 0;
996a966c04fSmrg    int ErrorStatus;
997a966c04fSmrg
998a966c04fSmrg    /* get geometry */
999a966c04fSmrg    if (attributes && attributes->valuemask & XpmSize) {
1000a966c04fSmrg	width = attributes->width;
1001a966c04fSmrg	height = attributes->height;
1002a966c04fSmrg    }
1003a966c04fSmrg    /* get the ximages */
1004a966c04fSmrg    if (pixmap)
1005a966c04fSmrg	xpmCreateImageFromPixmap(display, pixmap, &ximage, &width, &height);
1006a966c04fSmrg    if (shapemask)
1007a966c04fSmrg	xpmCreateImageFromPixmap(display, shapemask, &shapeimage,
1008a966c04fSmrg				 &width, &height);
1009a966c04fSmrg
1010a966c04fSmrg    /* create the related XpmImage */
1011a966c04fSmrg    ErrorStatus = XpmCreateXpmImageFromImage(display, ximage, shapeimage,
1012a966c04fSmrg					     xpmimage, attributes);
1013a966c04fSmrg
1014a966c04fSmrg    /* destroy the ximages */
1015a966c04fSmrg    if (ximage)
1016a966c04fSmrg	XDestroyImage(ximage);
1017a966c04fSmrg    if (shapeimage)
1018a966c04fSmrg	XDestroyImage(shapeimage);
1019a966c04fSmrg
1020a966c04fSmrg    return (ErrorStatus);
1021a966c04fSmrg}
1022a966c04fSmrg
1023a966c04fSmrg# endif/* not AMIGA */
1024a966c04fSmrg#endif /* ndef FOR_MSW */
1025