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