]> git.saurik.com Git - wxWidgets.git/blob - src/xpm/scan.c
Fixed transparency problem when masked area was not black
[wxWidgets.git] / src / xpm / scan.c
1 /*
2 * Copyright (C) 1989-95 GROUPE BULL
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
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"
46
47 #define MAXPRINTABLE 92 /* number of printable ascii chars
48 * minus \ and " for string compat
49 * and ? to avoid ANSI trigraphs. */
50
51 static char *printable =
52 " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\
53 ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
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
62 typedef 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
70 LFUNC(storePixel, int, (Pixel pixel, PixelsMap *pmap,
71 unsigned int *index_return));
72
73 LFUNC(storeMaskPixel, int, (Pixel pixel, PixelsMap *pmap,
74 unsigned int *index_return));
75
76 #ifndef FOR_MSW
77 # ifndef AMIGA
78 LFUNC(GetImagePixels, int, (XImage *image, unsigned int width,
79 unsigned int height, PixelsMap *pmap));
80
81 LFUNC(GetImagePixels32, int, (XImage *image, unsigned int width,
82 unsigned int height, PixelsMap *pmap));
83
84 LFUNC(GetImagePixels16, int, (XImage *image, unsigned int width,
85 unsigned int height, PixelsMap *pmap));
86
87 LFUNC(GetImagePixels8, int, (XImage *image, unsigned int width,
88 unsigned int height, PixelsMap *pmap));
89
90 LFUNC(GetImagePixels1, int, (XImage *image, unsigned int width,
91 unsigned int height, PixelsMap *pmap,
92 int (*storeFunc) ()));
93 # else /* AMIGA */
94 LFUNC(AGetImagePixels, int, (XImage *image, unsigned int width,
95 unsigned int height, PixelsMap *pmap,
96 int (*storeFunc) ()));
97 # endif/* AMIGA */
98 #else /* ndef FOR_MSW */
99 LFUNC(MSWGetImagePixels, int, (Display *d, XImage *image, unsigned int width,
100 unsigned int height, PixelsMap *pmap,
101 int (*storeFunc) ()));
102 #endif
103 LFUNC(ScanTransparentColor, int, (XpmColor *color, unsigned int cpp,
104 XpmAttributes *attributes));
105
106 LFUNC(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 */
114 static int
115 storePixel(pixel, pmap, index_return)
116 Pixel pixel;
117 PixelsMap *pmap;
118 unsigned int *index_return;
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
149 static int
150 storeMaskPixel(pixel, pmap, index_return)
151 Pixel pixel;
152 PixelsMap *pmap;
153 unsigned int *index_return;
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
167 /* function call in case of error */
168 #undef RETURN
169 #define RETURN(status) \
170 { \
171 ErrorStatus = status; \
172 goto error; \
173 }
174
175 /*
176 * This function scans the given image and stores the found informations in
177 * the given XpmImage structure.
178 */
179 int
180 XpmCreateXpmImageFromImage(display, image, shapeimage,
181 xpmimage, attributes)
182 Display *display;
183 XImage *image;
184 XImage *shapeimage;
185 XpmImage *xpmimage;
186 XpmAttributes *attributes;
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;
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
245 # ifndef AMIGA
246 ErrorStatus = GetImagePixels1(shapeimage, width, height, &pmap,
247 storeMaskPixel);
248 # else
249 ErrorStatus = AGetImagePixels(shapeimage, width, height, &pmap,
250 storeMaskPixel);
251 # endif
252 #else
253 ErrorStatus = MSWGetImagePixels(display, shapeimage, width, height,
254 &pmap, storeMaskPixel);
255 #endif
256 if (ErrorStatus != XpmSuccess)
257 RETURN(ErrorStatus);
258 }
259
260 /*
261 * scan the image data
262 *
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.
265 *
266 */
267
268 if (image) {
269 #ifndef FOR_MSW
270 # ifndef AMIGA
271 if (((image->bits_per_pixel | image->depth) == 1) &&
272 (image->byte_order == image->bitmap_bit_order))
273 ErrorStatus = GetImagePixels1(image, width, height, &pmap,
274 storePixel);
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
283 ErrorStatus = GetImagePixels(image, width, height, &pmap);
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);
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);
315 }
316
317 ErrorStatus = ScanOtherColors(display, colorTable, pmap.ncolors,
318 pmap.pixels, pmap.mask_pixel, cpp,
319 attributes);
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);
335
336 /* exit point in case of error, free only locally allocated variables */
337 error:
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);
346 }
347
348 static int
349 ScanTransparentColor(color, cpp, attributes)
350 XpmColor *color;
351 unsigned int cpp;
352 XpmAttributes *attributes;
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 */
367 if (attributes && (attributes->valuemask & XpmColorTable
368 /* 3.2 backward compatibility code */
369 || attributes->valuemask & XpmInfos)
370 /* end 3.2 bc */
371 && attributes->mask_pixel != XpmUndefPixel) {
372
373 unsigned int key;
374 char **defaults = (char **) color;
375 char **mask_defaults;
376
377 /* 3.2 backward compatibility code */
378 if (attributes->valuemask & XpmColorTable)
379 /* end 3.2 bc */
380 mask_defaults = (char **) (
381 attributes->colorTable + attributes->mask_pixel);
382 /* 3.2 backward compatibility code */
383 else
384 mask_defaults = (char **)
385 ((XpmColor **) attributes->colorTable)[attributes->mask_pixel];
386 /* end 3.2 bc */
387 for (key = 1; key <= NKEYS; key++) {
388 if (s = mask_defaults[key]) {
389 defaults[key] = (char *) xpmstrdup(s);
390 if (!defaults[key])
391 return (XpmNoMemory);
392 }
393 }
394 } else {
395 color->c_color = (char *) xpmstrdup(TRANSPARENT_COLOR);
396 if (!color->c_color)
397 return (XpmNoMemory);
398 }
399 return (XpmSuccess);
400 }
401
402 static int
403 ScanOtherColors(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;
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
419 xpmRgbName *rgbn = NULL;
420 #endif
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;
430 Bool found;
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
442 /* start from the right element */
443 if (mask) {
444 colors++;
445 ncolors--;
446 pixels++;
447 }
448
449 /* first get character strings and rgb values */
450 xcolors = (XColor *) XpmMalloc(sizeof(XColor) * ncolors);
451 if (!xcolors)
452 return (XpmNoMemory);
453
454 for (i = 0, i2 = mask, color = colors, xcolor = xcolors;
455 i < ncolors; i++, i2++, color++, xcolor++, pixels++) {
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 }
468 XQueryColors(display, colormap, xcolors, ncolors);
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
494 for (i = 0, color = colors, xcolor = xcolors; i < ncolors;
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])
525 defaults[key] = (char *) xpmstrdup(s);
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)
536 color->c_color = (char *) xpmstrdup(colorname);
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);
543 #else
544 sprintf(buf, "#%02x%02x%02x",
545 xcolor->red, xcolor->green, xcolor->blue);
546 #endif
547 color->c_color = (char *) xpmstrdup(buf);
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
563 # ifndef AMIGA
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
570 * level.
571 */
572
573 static 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 /*
586 * Default method to scan pixels of an image data structure.
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
595 static int
596 GetImagePixels(image, width, height, pmap)
597 XImage *image;
598 unsigned int width;
599 unsigned int height;
600 PixelsMap *pmap;
601 {
602 char *src;
603 char *dst;
604 unsigned int *iptr;
605 char *data;
606 int x, y, i;
607 int bits, depth, ibu, ibpp, offset;
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;
616 offset = image->xoffset;
617
618 if ((image->bits_per_pixel | image->depth) == 1) {
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);
628 bits = (x + offset) % ibu;
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 }
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) {
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 }
685 } else
686 return (XpmColorError); /* actually a bad image */
687 return (XpmSuccess);
688 }
689
690 /*
691 * scan pixels of a 32-bits Z image data structure
692 */
693
694 #if !defined(WORD64) && !defined(LONG64)
695 static unsigned long byteorderpixel = MSBFirst << 24;
696 #endif
697
698 static int
699 GetImagePixels32(image, width, height, pmap)
700 XImage *image;
701 unsigned int width;
702 unsigned int height;
703 PixelsMap *pmap;
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];
717 #if !defined(WORD64) && !defined(LONG64)
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 |
737 addr[3]);
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
763 static int
764 GetImagePixels16(image, width, height, pmap)
765 XImage *image;
766 unsigned int width;
767 unsigned int height;
768 PixelsMap *pmap;
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
809 static int
810 GetImagePixels8(image, width, height, pmap)
811 XImage *image;
812 unsigned int width;
813 unsigned int height;
814 PixelsMap *pmap;
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
842 static int
843 GetImagePixels1(image, width, height, pmap, storeFunc)
844 XImage *image;
845 unsigned int width;
846 unsigned int height;
847 PixelsMap *pmap;
848 int (*storeFunc) ();
849 {
850 unsigned int *iptr;
851 int x, y;
852 char *data;
853 Pixel pixel;
854 int xoff, yoff, offset, bpl;
855
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 }
881 return (XpmSuccess);
882 }
883
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
893 static int
894 AGetImagePixels (
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 */
931 #else /* ndef FOR_MSW */
932 static int
933 MSWGetImagePixels(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) ();
940 {
941 unsigned int *iptr;
942 unsigned int x, y;
943 Pixel pixel;
944
945 iptr = pmap->pixelindex;
946
947 SelectObject(*display, image->bitmap);
948 for (y = 0; y < height; y++) {
949 for (x = 0; x < width; x++, iptr++) {
950 pixel = GetPixel(*display, x, y);
951 if ((*storeFunc) (pixel, pmap, iptr))
952 return (XpmNoMemory);
953 }
954 }
955 return (XpmSuccess);
956 }
957
958 #endif
959
960 #ifndef FOR_MSW
961 # ifndef AMIGA
962 int
963 XpmCreateXpmImageFromPixmap(display, pixmap, shapemask,
964 xpmimage, attributes)
965 Display *display;
966 Pixmap pixmap;
967 Pixmap shapemask;
968 XpmImage *xpmimage;
969 XpmAttributes *attributes;
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
1002 # endif/* not AMIGA */
1003 #endif /* ndef FOR_MSW */