]> git.saurik.com Git - wxWidgets.git/blob - src/xpm/scan.c
fix from Robert
[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 #ifdef __OS2__
115 /* Visual Age cannot deal with old, non-ansi, code */
116 static int storePixel(Pixel pixel, PixelsMap* pmap, unsigned int* index_return)
117 #else
118 static int
119 storePixel(pixel, pmap, index_return)
120 Pixel pixel;
121 PixelsMap *pmap;
122 unsigned int *index_return;
123 #endif
124 {
125 unsigned int i;
126 Pixel *p;
127 unsigned int ncolors;
128
129 if (*index_return) { /* this is a transparent pixel! */
130 *index_return = 0;
131 return 0;
132 }
133 ncolors = pmap->ncolors;
134 p = pmap->pixels + pmap->mask_pixel;
135 for (i = pmap->mask_pixel; i < ncolors; i++, p++)
136 if (*p == pixel)
137 break;
138 if (i == ncolors) {
139 if (ncolors >= pmap->size) {
140 pmap->size *= 2;
141 p = (Pixel *) XpmRealloc(pmap->pixels, sizeof(Pixel) * pmap->size);
142 if (!p)
143 return (1);
144 pmap->pixels = p;
145
146 }
147 (pmap->pixels)[ncolors] = pixel;
148 pmap->ncolors++;
149 }
150 *index_return = i;
151 return 0;
152 }
153
154 #ifdef __OS2__
155 /* Visual Age cannot deal with old, non-ansi, code */
156 static int storeMaskPixel(Pixel pixel, PixelsMap* pmap, unsigned int* index_return)
157 #else
158 static int
159 storeMaskPixel(pixel, pmap, index_return)
160 Pixel pixel;
161 PixelsMap *pmap;
162 unsigned int *index_return;
163 #endif
164 {
165 if (!pixel) {
166 if (!pmap->ncolors) {
167 pmap->ncolors = 1;
168 (pmap->pixels)[0] = 0;
169 pmap->mask_pixel = 1;
170 }
171 *index_return = 1;
172 } else
173 *index_return = 0;
174 return 0;
175 }
176
177 /* function call in case of error */
178 #undef RETURN
179 #define RETURN(status) \
180 { \
181 ErrorStatus = status; \
182 goto error; \
183 }
184
185 /*
186 * This function scans the given image and stores the found informations in
187 * the given XpmImage structure.
188 */
189 #ifdef __OS2__
190 /* Visual Age cannot deal with old, non-ansi, code */
191 int XpmCreateXpmImageFromImage(
192 Display* display
193 , XImage* image
194 , XImage* shapeimage
195 , XpmImage* xpmimage
196 , XpmAttributes* attributes
197 )
198 #else
199 int
200 XpmCreateXpmImageFromImage(display, image, shapeimage,
201 xpmimage, attributes)
202 Display *display;
203 XImage *image;
204 XImage *shapeimage;
205 XpmImage *xpmimage;
206 XpmAttributes *attributes;
207 #endif
208 {
209 /* variables stored in the XpmAttributes structure */
210 unsigned int cpp;
211
212 /* variables to return */
213 PixelsMap pmap;
214 XpmColor *colorTable = NULL;
215 int ErrorStatus;
216
217 /* calculation variables */
218 unsigned int width = 0;
219 unsigned int height = 0;
220 unsigned int cppm; /* minimum chars per pixel */
221 unsigned int c;
222
223 /* initialize pmap */
224 pmap.pixels = NULL;
225 pmap.pixelindex = NULL;
226 pmap.size = 256; /* should be enough most of the time */
227 pmap.ncolors = 0;
228 pmap.mask_pixel = 0;
229
230 /*
231 * get geometry
232 */
233 if (image) {
234 width = image->width;
235 height = image->height;
236 } else if (shapeimage) {
237 width = shapeimage->width;
238 height = shapeimage->height;
239 }
240
241 /*
242 * retrieve information from the XpmAttributes
243 */
244 if (attributes && (attributes->valuemask & XpmCharsPerPixel
245 /* 3.2 backward compatibility code */
246 || attributes->valuemask & XpmInfos))
247 /* end 3.2 bc */
248 cpp = attributes->cpp;
249 else
250 cpp = 0;
251
252 pmap.pixelindex =
253 (unsigned int *) XpmCalloc(width * height, sizeof(unsigned int));
254 if (!pmap.pixelindex)
255 RETURN(XpmNoMemory);
256
257 pmap.pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * pmap.size);
258 if (!pmap.pixels)
259 RETURN(XpmNoMemory);
260
261 /*
262 * scan shape mask if any
263 */
264 if (shapeimage)
265 {
266 #ifndef FOR_MSW
267 # ifndef AMIGA
268 ErrorStatus = GetImagePixels1(shapeimage, width, height, &pmap,
269 storeMaskPixel);
270 # else
271 ErrorStatus = AGetImagePixels(shapeimage, width, height, &pmap,
272 storeMaskPixel);
273 # endif /* AMIGA */
274 #else
275
276 #ifndef __OS2__
277 ErrorStatus = MSWGetImagePixels(display, shapeimage, width, height,
278 &pmap, storeMaskPixel);
279 /* calling convention all messed up OS/2 -- figure out later */
280 #endif
281
282 #endif /* ndef for FOR_MSW */
283
284 if (ErrorStatus != XpmSuccess)
285 RETURN(ErrorStatus);
286 }
287
288 /*
289 * scan the image data
290 *
291 * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use optimized
292 * functions, otherwise use slower but sure general one.
293 *
294 */
295
296 if (image)
297 {
298 #ifndef FOR_MSW
299 # ifndef AMIGA
300 if (((image->bits_per_pixel | image->depth) == 1) &&
301 (image->byte_order == image->bitmap_bit_order))
302 ErrorStatus = GetImagePixels1(image, width, height, &pmap,
303 storePixel);
304 else if (image->format == ZPixmap)
305 {
306 if (image->bits_per_pixel == 8)
307 ErrorStatus = GetImagePixels8(image, width, height, &pmap);
308 else if (image->bits_per_pixel == 16)
309 ErrorStatus = GetImagePixels16(image, width, height, &pmap);
310 else if (image->bits_per_pixel == 32)
311 ErrorStatus = GetImagePixels32(image, width, height, &pmap);
312 }
313 else
314 ErrorStatus = GetImagePixels(image, width, height, &pmap);
315 # else
316 ErrorStatus = AGetImagePixels(image, width, height, &pmap,
317 storePixel);
318 # endif /* AMIGA */
319 #else
320
321 #ifndef __VISAGECPP30__
322 ErrorStatus = MSWGetImagePixels(display, image, width, height, &pmap,
323 storePixel);
324 #endif
325
326 #endif
327
328 if (ErrorStatus != XpmSuccess)
329 RETURN(ErrorStatus);
330 }
331
332 /*
333 * get rgb values and a string of char, and possibly a name for each
334 * color
335 */
336
337 colorTable = (XpmColor *) XpmCalloc(pmap.ncolors, sizeof(XpmColor));
338 if (!colorTable)
339 RETURN(XpmNoMemory);
340
341 /* compute the minimal cpp */
342 for (cppm = 1, c = MAXPRINTABLE; pmap.ncolors > c; cppm++)
343 c *= MAXPRINTABLE;
344 if (cpp < cppm)
345 cpp = cppm;
346
347 if (pmap.mask_pixel) {
348 ErrorStatus = ScanTransparentColor(colorTable, cpp, attributes);
349 if (ErrorStatus != XpmSuccess)
350 RETURN(ErrorStatus);
351 }
352
353 ErrorStatus = ScanOtherColors(display, colorTable, pmap.ncolors,
354 pmap.pixels, pmap.mask_pixel, cpp,
355 attributes);
356 if (ErrorStatus != XpmSuccess)
357 RETURN(ErrorStatus);
358
359 /*
360 * store found informations in the XpmImage structure
361 */
362 xpmimage->width = width;
363 xpmimage->height = height;
364 xpmimage->cpp = cpp;
365 xpmimage->ncolors = pmap.ncolors;
366 xpmimage->colorTable = colorTable;
367 xpmimage->data = pmap.pixelindex;
368
369 XpmFree(pmap.pixels);
370 return (XpmSuccess);
371
372 /* exit point in case of error, free only locally allocated variables */
373 error:
374 if (pmap.pixelindex)
375 XpmFree(pmap.pixelindex);
376 if (pmap.pixels)
377 XpmFree(pmap.pixels);
378 if (colorTable)
379 xpmFreeColorTable(colorTable, pmap.ncolors);
380
381 return (ErrorStatus);
382 }
383
384 #ifdef __OS2__
385 /* Visual Age cannot deal with old, non-ansi, code */
386 static int ScanTransparentColor(XpmColor* color, unsigned int cpp, XpmAttributes* attributes)
387 #else
388 static int
389 ScanTransparentColor(color, cpp, attributes)
390 XpmColor *color;
391 unsigned int cpp;
392 XpmAttributes *attributes;
393 #endif
394 {
395 char *s;
396 unsigned int a, b, c;
397
398 /* first get a character string */
399 a = 0;
400 if (!(s = color->string = (char *) XpmMalloc(cpp + 1)))
401 return (XpmNoMemory);
402 *s++ = printable[c = a % MAXPRINTABLE];
403 for (b = 1; b < cpp; b++, s++)
404 *s = printable[c = ((a - c) / MAXPRINTABLE) % MAXPRINTABLE];
405 *s = '\0';
406
407 /* then retreive related info from the attributes if any */
408 if (attributes && (attributes->valuemask & XpmColorTable
409 /* 3.2 backward compatibility code */
410 || attributes->valuemask & XpmInfos)
411 /* end 3.2 bc */
412 && attributes->mask_pixel != XpmUndefPixel) {
413
414 unsigned int key;
415 char **defaults = (char **) color;
416 char **mask_defaults;
417
418 /* 3.2 backward compatibility code */
419 if (attributes->valuemask & XpmColorTable)
420 /* end 3.2 bc */
421 mask_defaults = (char **) (
422 attributes->colorTable + attributes->mask_pixel);
423 /* 3.2 backward compatibility code */
424 else
425 mask_defaults = (char **)
426 ((XpmColor **) attributes->colorTable)[attributes->mask_pixel];
427 /* end 3.2 bc */
428 for (key = 1; key <= NKEYS; key++) {
429 if (s = mask_defaults[key]) {
430 defaults[key] = (char *) xpmstrdup(s);
431 if (!defaults[key])
432 return (XpmNoMemory);
433 }
434 }
435 } else {
436 color->c_color = (char *) xpmstrdup(TRANSPARENT_COLOR);
437 if (!color->c_color)
438 return (XpmNoMemory);
439 }
440 return (XpmSuccess);
441 }
442
443 #ifdef __OS2__
444 /* Visual Age cannot deal with old, non-ansi, code */
445 static int ScanOtherColors(
446 Display* display
447 , XpmColor* colors
448 , int ncolors
449 , Pixel* pixels
450 , unsigned int mask
451 , unsigned int cpp
452 , XpmAttributes* attributes
453 )
454 #else
455 static int
456 ScanOtherColors(display, colors, ncolors, pixels, mask, cpp, attributes)
457 Display *display;
458 XpmColor *colors;
459 int ncolors;
460 Pixel *pixels;
461 unsigned int mask;
462 unsigned int cpp;
463 XpmAttributes *attributes;
464 #endif
465 {
466 /* variables stored in the XpmAttributes structure */
467 Colormap colormap;
468 char *rgb_fname;
469
470 #ifndef FOR_MSW
471 xpmRgbName rgbn[MAX_RGBNAMES];
472 #else
473 xpmRgbName *rgbn = NULL;
474 #endif
475 int rgbn_max = 0;
476 unsigned int i, j, c, i2;
477 XpmColor *color;
478 XColor *xcolors = NULL, *xcolor;
479 char *colorname, *s;
480 XpmColor *colorTable, **oldColorTable = NULL;
481 unsigned int ancolors = 0;
482 Pixel *apixels;
483 unsigned int mask_pixel;
484 Bool found;
485
486 /* retrieve information from the XpmAttributes */
487 if (attributes && (attributes->valuemask & XpmColormap))
488 colormap = attributes->colormap;
489 else
490 colormap = XDefaultColormap(display, XDefaultScreen(display));
491 if (attributes && (attributes->valuemask & XpmRgbFilename))
492 rgb_fname = attributes->rgb_fname;
493 else
494 rgb_fname = NULL;
495
496 /* start from the right element */
497 if (mask) {
498 colors++;
499 ncolors--;
500 pixels++;
501 }
502
503 /* first get character strings and rgb values */
504 xcolors = (XColor *) XpmMalloc(sizeof(XColor) * ncolors);
505 if (!xcolors)
506 return (XpmNoMemory);
507
508 for (i = 0, i2 = mask, color = colors, xcolor = xcolors;
509 i < (unsigned)ncolors; i++, i2++, color++, xcolor++, pixels++) {
510
511 if (!(s = color->string = (char *) XpmMalloc(cpp + 1))) {
512 XpmFree(xcolors);
513 return (XpmNoMemory);
514 }
515 *s++ = printable[c = i2 % MAXPRINTABLE];
516 for (j = 1; j < cpp; j++, s++)
517 *s = printable[c = ((i2 - c) / MAXPRINTABLE) % MAXPRINTABLE];
518 *s = '\0';
519
520 xcolor->pixel = *pixels;
521 }
522 #ifdef __OS2__
523 XQueryColors(display, &colormap, xcolors, ncolors);
524 #else
525 XQueryColors(display, colormap, xcolors, ncolors);
526 #endif
527
528 #ifndef FOR_MSW
529 /* read the rgb file if any was specified */
530 if (rgb_fname)
531 rgbn_max = xpmReadRgbNames(attributes->rgb_fname, rgbn);
532 #else
533 /* FOR_MSW: rgb names and values are hardcoded in rgbtab.h */
534 rgbn_max = xpmReadRgbNames(NULL, NULL);
535 #endif
536
537 if (attributes && attributes->valuemask & XpmColorTable) {
538 colorTable = attributes->colorTable;
539 ancolors = attributes->ncolors;
540 apixels = attributes->pixels;
541 mask_pixel = attributes->mask_pixel;
542 }
543 /* 3.2 backward compatibility code */
544 else if (attributes && attributes->valuemask & XpmInfos) {
545 oldColorTable = (XpmColor **) attributes->colorTable;
546 ancolors = attributes->ncolors;
547 apixels = attributes->pixels;
548 mask_pixel = attributes->mask_pixel;
549 }
550 /* end 3.2 bc */
551
552 for (i = 0, color = colors, xcolor = xcolors; i < (unsigned)ncolors;
553 i++, color++, xcolor++) {
554
555 /* look for related info from the attributes if any */
556 found = False;
557 if (ancolors) {
558 unsigned int offset = 0;
559
560 for (j = 0; j < ancolors; j++) {
561 if (j == mask_pixel) {
562 offset = 1;
563 continue;
564 }
565 if (apixels[j - offset] == xcolor->pixel)
566 break;
567 }
568 if (j != ancolors) {
569 unsigned int key;
570 char **defaults = (char **) color;
571 char **adefaults;
572
573 /* 3.2 backward compatibility code */
574 if (oldColorTable)
575 adefaults = (char **) oldColorTable[j];
576 else
577 /* end 3.2 bc */
578 adefaults = (char **) (colorTable + j);
579
580 found = True;
581 for (key = 1; key <= NKEYS; key++) {
582 if (s = adefaults[key])
583 defaults[key] = (char *) xpmstrdup(s);
584 }
585 }
586 }
587 if (!found) {
588 /* if nothing found look for a color name */
589 colorname = NULL;
590 if (rgbn_max)
591 colorname = xpmGetRgbName(rgbn, rgbn_max, xcolor->red,
592 xcolor->green, xcolor->blue);
593 if (colorname)
594 color->c_color = (char *) xpmstrdup(colorname);
595 else {
596 /* at last store the rgb value */
597 char buf[BUFSIZ];
598 #ifndef FOR_MSW
599 sprintf(buf, "#%04X%04X%04X",
600 xcolor->red, xcolor->green, xcolor->blue);
601 #else
602 sprintf(buf, "#%02x%02x%02x",
603 xcolor->red, xcolor->green, xcolor->blue);
604 #endif
605 color->c_color = (char *) xpmstrdup(buf);
606 }
607 if (!color->c_color) {
608 XpmFree(xcolors);
609 xpmFreeRgbNames(rgbn, rgbn_max);
610 return (XpmNoMemory);
611 }
612 }
613 }
614
615 XpmFree(xcolors);
616 xpmFreeRgbNames(rgbn, rgbn_max);
617 return (XpmSuccess);
618 }
619
620 #ifndef FOR_MSW
621 # ifndef AMIGA
622 /*
623 * The functions below are written from X11R5 MIT's code (XImUtil.c)
624 *
625 * The idea is to have faster functions than the standard XGetPixel function
626 * to scan the image data. Indeed we can speed up things by suppressing tests
627 * performed for each pixel. We do exactly the same tests but at the image
628 * level.
629 */
630
631 static unsigned long Const low_bits_table[] = {
632 0x00000000, 0x00000001, 0x00000003, 0x00000007,
633 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
634 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
635 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
636 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
637 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
638 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
639 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
640 0xffffffff
641 };
642
643 /*
644 * Default method to scan pixels of an image data structure.
645 * The algorithm used is:
646 *
647 * copy the source bitmap_unit or Zpixel into temp
648 * normalize temp if needed
649 * extract the pixel bits into return value
650 *
651 */
652
653 static int
654 GetImagePixels(image, width, height, pmap)
655 XImage *image;
656 unsigned int width;
657 unsigned int height;
658 PixelsMap *pmap;
659 {
660 char *src;
661 char *dst;
662 unsigned int *iptr;
663 char *data;
664 int x, y, i;
665 int bits, depth, ibu, ibpp, offset;
666 unsigned long lbt;
667 Pixel pixel, px;
668
669 data = image->data;
670 iptr = pmap->pixelindex;
671 depth = image->depth;
672 lbt = low_bits_table[depth];
673 ibpp = image->bits_per_pixel;
674 offset = image->xoffset;
675
676 if ((image->bits_per_pixel | image->depth) == 1) {
677 ibu = image->bitmap_unit;
678 for (y = 0; y < height; y++)
679 for (x = 0; x < width; x++, iptr++) {
680 src = &data[XYINDEX(x, y, image)];
681 dst = (char *) &pixel;
682 pixel = 0;
683 for (i = ibu >> 3; --i >= 0;)
684 *dst++ = *src++;
685 XYNORMALIZE(&pixel, image);
686 bits = (x + offset) % ibu;
687 pixel = ((((char *) &pixel)[bits >> 3]) >> (bits & 7)) & 1;
688 if (ibpp != depth)
689 pixel &= lbt;
690 if (storePixel(pixel, pmap, iptr))
691 return (XpmNoMemory);
692 }
693 } else if (image->format == XYPixmap) {
694 int nbytes, bpl, j;
695 long plane = 0;
696 ibu = image->bitmap_unit;
697 nbytes = ibu >> 3;
698 bpl = image->bytes_per_line;
699 for (y = 0; y < height; y++)
700 for (x = 0; x < width; x++, iptr++) {
701 pixel = 0;
702 plane = 0;
703 for (i = depth; --i >= 0;) {
704 src = &data[XYINDEX(x, y, image) + plane];
705 dst = (char *) &px;
706 px = 0;
707 for (j = nbytes; --j >= 0;)
708 *dst++ = *src++;
709 XYNORMALIZE(&px, image);
710 bits = (x + offset) % ibu;
711 pixel = (pixel << 1) |
712 (((((char *) &px)[bits >> 3]) >> (bits & 7)) & 1);
713 plane = plane + (bpl * height);
714 }
715 if (ibpp != depth)
716 pixel &= lbt;
717 if (storePixel(pixel, pmap, iptr))
718 return (XpmNoMemory);
719 }
720 } else if (image->format == ZPixmap) {
721 for (y = 0; y < height; y++)
722 for (x = 0; x < width; x++, iptr++) {
723 src = &data[ZINDEX(x, y, image)];
724 dst = (char *) &px;
725 px = 0;
726 for (i = (ibpp + 7) >> 3; --i >= 0;)
727 *dst++ = *src++;
728 ZNORMALIZE(&px, image);
729 pixel = 0;
730 for (i = sizeof(unsigned long); --i >= 0;)
731 pixel = (pixel << 8) | ((unsigned char *) &px)[i];
732 if (ibpp == 4) {
733 if (x & 1)
734 pixel >>= 4;
735 else
736 pixel &= 0xf;
737 }
738 if (ibpp != depth)
739 pixel &= lbt;
740 if (storePixel(pixel, pmap, iptr))
741 return (XpmNoMemory);
742 }
743 } else
744 return (XpmColorError); /* actually a bad image */
745 return (XpmSuccess);
746 }
747
748 /*
749 * scan pixels of a 32-bits Z image data structure
750 */
751
752 #if !defined(WORD64) && !defined(LONG64)
753 static unsigned long byteorderpixel = MSBFirst << 24;
754 #endif
755
756 static int
757 GetImagePixels32(image, width, height, pmap)
758 XImage *image;
759 unsigned int width;
760 unsigned int height;
761 PixelsMap *pmap;
762 {
763 unsigned char *addr;
764 unsigned char *data;
765 unsigned int *iptr;
766 int x, y;
767 unsigned long lbt;
768 Pixel pixel;
769 int depth;
770
771 data = (unsigned char *) image->data;
772 iptr = pmap->pixelindex;
773 depth = image->depth;
774 lbt = low_bits_table[depth];
775 #if !defined(WORD64) && !defined(LONG64)
776 if (*((char *) &byteorderpixel) == image->byte_order) {
777 for (y = 0; y < height; y++)
778 for (x = 0; x < width; x++, iptr++) {
779 addr = &data[ZINDEX32(x, y, image)];
780 pixel = *((unsigned long *) addr);
781 if (depth != 32)
782 pixel &= lbt;
783 if (storePixel(pixel, pmap, iptr))
784 return (XpmNoMemory);
785 }
786 } else
787 #endif
788 if (image->byte_order == MSBFirst)
789 for (y = 0; y < height; y++)
790 for (x = 0; x < width; x++, iptr++) {
791 addr = &data[ZINDEX32(x, y, image)];
792 pixel = ((unsigned long) addr[0] << 24 |
793 (unsigned long) addr[1] << 16 |
794 (unsigned long) addr[2] << 8 |
795 addr[3]);
796 if (depth != 32)
797 pixel &= lbt;
798 if (storePixel(pixel, pmap, iptr))
799 return (XpmNoMemory);
800 }
801 else
802 for (y = 0; y < height; y++)
803 for (x = 0; x < width; x++, iptr++) {
804 addr = &data[ZINDEX32(x, y, image)];
805 pixel = (addr[0] |
806 (unsigned long) addr[1] << 8 |
807 (unsigned long) addr[2] << 16 |
808 (unsigned long) addr[3] << 24);
809 if (depth != 32)
810 pixel &= lbt;
811 if (storePixel(pixel, pmap, iptr))
812 return (XpmNoMemory);
813 }
814 return (XpmSuccess);
815 }
816
817 /*
818 * scan pixels of a 16-bits Z image data structure
819 */
820
821 static int
822 GetImagePixels16(image, width, height, pmap)
823 XImage *image;
824 unsigned int width;
825 unsigned int height;
826 PixelsMap *pmap;
827 {
828 unsigned char *addr;
829 unsigned char *data;
830 unsigned int *iptr;
831 int x, y;
832 unsigned long lbt;
833 Pixel pixel;
834 int depth;
835
836 data = (unsigned char *) image->data;
837 iptr = pmap->pixelindex;
838 depth = image->depth;
839 lbt = low_bits_table[depth];
840 if (image->byte_order == MSBFirst)
841 for (y = 0; y < height; y++)
842 for (x = 0; x < width; x++, iptr++) {
843 addr = &data[ZINDEX16(x, y, image)];
844 pixel = addr[0] << 8 | addr[1];
845 if (depth != 16)
846 pixel &= lbt;
847 if (storePixel(pixel, pmap, iptr))
848 return (XpmNoMemory);
849 }
850 else
851 for (y = 0; y < height; y++)
852 for (x = 0; x < width; x++, iptr++) {
853 addr = &data[ZINDEX16(x, y, image)];
854 pixel = addr[0] | addr[1] << 8;
855 if (depth != 16)
856 pixel &= lbt;
857 if (storePixel(pixel, pmap, iptr))
858 return (XpmNoMemory);
859 }
860 return (XpmSuccess);
861 }
862
863 /*
864 * scan pixels of a 8-bits Z image data structure
865 */
866
867 static int
868 GetImagePixels8(image, width, height, pmap)
869 XImage *image;
870 unsigned int width;
871 unsigned int height;
872 PixelsMap *pmap;
873 {
874 unsigned int *iptr;
875 unsigned char *data;
876 int x, y;
877 unsigned long lbt;
878 Pixel pixel;
879 int depth;
880
881 data = (unsigned char *) image->data;
882 iptr = pmap->pixelindex;
883 depth = image->depth;
884 lbt = low_bits_table[depth];
885 for (y = 0; y < height; y++)
886 for (x = 0; x < width; x++, iptr++) {
887 pixel = data[ZINDEX8(x, y, image)];
888 if (depth != 8)
889 pixel &= lbt;
890 if (storePixel(pixel, pmap, iptr))
891 return (XpmNoMemory);
892 }
893 return (XpmSuccess);
894 }
895
896 /*
897 * scan pixels of a 1-bit depth Z image data structure
898 */
899
900 static int
901 GetImagePixels1(image, width, height, pmap, storeFunc)
902 XImage *image;
903 unsigned int width;
904 unsigned int height;
905 PixelsMap *pmap;
906 int (*storeFunc) ();
907 {
908 unsigned int *iptr;
909 int x, y;
910 char *data;
911 Pixel pixel;
912 int xoff, yoff, offset, bpl;
913
914 data = image->data;
915 iptr = pmap->pixelindex;
916 offset = image->xoffset;
917 bpl = image->bytes_per_line;
918
919 if (image->bitmap_bit_order == MSBFirst)
920 for (y = 0; y < height; y++)
921 for (x = 0; x < width; x++, iptr++) {
922 xoff = x + offset;
923 yoff = y * bpl + (xoff >> 3);
924 xoff &= 7;
925 pixel = (data[yoff] & (0x80 >> xoff)) ? 1 : 0;
926 if ((*storeFunc) (pixel, pmap, iptr))
927 return (XpmNoMemory);
928 }
929 else
930 for (y = 0; y < height; y++)
931 for (x = 0; x < width; x++, iptr++) {
932 xoff = x + offset;
933 yoff = y * bpl + (xoff >> 3);
934 xoff &= 7;
935 pixel = (data[yoff] & (1 << xoff)) ? 1 : 0;
936 if ((*storeFunc) (pixel, pmap, iptr))
937 return (XpmNoMemory);
938 }
939 return (XpmSuccess);
940 }
941
942 # else /* AMIGA */
943
944 #define CLEAN_UP(status) \
945 {\
946 if (pixels) XpmFree (pixels);\
947 if (tmp_img) FreeXImage (tmp_img);\
948 return (status);\
949 }
950
951 static int
952 AGetImagePixels (
953 XImage *image,
954 unsigned int width,
955 unsigned int height,
956 PixelsMap *pmap,
957 int (*storeFunc) ())
958 {
959 unsigned int *iptr;
960 unsigned int x, y;
961 unsigned char *pixels;
962 XImage *tmp_img;
963
964 pixels = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*pixels));
965 if (pixels == NULL)
966 return XpmNoMemory;
967
968 tmp_img = AllocXImage ((((width+15)>>4)<<4), 1, image->rp->BitMap->Depth);
969 if (tmp_img == NULL)
970 CLEAN_UP (XpmNoMemory)
971
972 iptr = pmap->pixelindex;
973 for (y = 0; y < height; ++y)
974 {
975 ReadPixelLine8 (image->rp, 0, y, width, pixels, tmp_img->rp);
976 for (x = 0; x < width; ++x, ++iptr)
977 {
978 if ((*storeFunc) (pixels[x], pmap, iptr))
979 CLEAN_UP (XpmNoMemory)
980 }
981 }
982
983 CLEAN_UP (XpmSuccess)
984 }
985
986 #undef CLEAN_UP
987
988 # endif/* AMIGA */
989 #else /* ndef FOR_MSW */
990
991 #ifdef __OS2__
992
993 #ifdef __VISAGECPP30__
994 static int MSWGetImagePixels(
995 Display* display
996 , XImage* image
997 , unsigned int width
998 , unsigned int height
999 , PixelsMap* pmap
1000 , int (*storeFunc) (Pixel, PixelsMap*, unsigned int*)
1001 )
1002 #else
1003 static int MSWGetImagePixels(
1004 Display* display
1005 , XImage* image
1006 , unsigned int width
1007 , unsigned int height
1008 , PixelsMap* pmap
1009 , int (*storeFunc) ()
1010 )
1011 #endif
1012
1013 #else
1014 static int
1015 MSWGetImagePixels(display, image, width, height, pmap, storeFunc)
1016 Display *display;
1017 XImage *image;
1018 unsigned int width;
1019 unsigned int height;
1020 PixelsMap *pmap;
1021 int (*storeFunc) ();
1022 #endif
1023 {
1024 unsigned int *iptr;
1025 unsigned int x, y;
1026 Pixel pixel;
1027 #ifdef __OS2__
1028 HAB hab;
1029 HPS hps;
1030 DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1031 SIZEL sizl = {0, 0};
1032 POINTL point;
1033 #endif
1034
1035 iptr = pmap->pixelindex;
1036
1037 #ifdef __OS2__
1038 hps = GpiCreatePS(hab, *display, &sizl, GPIA_ASSOC | PU_PELS);
1039 GpiSetBitmap(hps, image->bitmap);
1040 #else
1041 SelectObject(*display, image->bitmap);
1042 #endif
1043
1044 for (y = 0; y < height; y++) {
1045 for (x = 0; x < width; x++, iptr++) {
1046 #ifdef __OS2__
1047 point.x = x;
1048 point.y = y;
1049 pixel = GpiQueryPel(hps, &point);
1050 #else
1051 pixel = GetPixel(*display, x, y);
1052 #endif
1053
1054 if ((*storeFunc) (pixel, pmap, iptr))
1055 return (XpmNoMemory);
1056 }
1057 }
1058 return (XpmSuccess);
1059 }
1060
1061 #endif
1062
1063 #ifndef FOR_MSW
1064 # ifndef AMIGA
1065 int
1066 XpmCreateXpmImageFromPixmap(display, pixmap, shapemask,
1067 xpmimage, attributes)
1068 Display *display;
1069 Pixmap pixmap;
1070 Pixmap shapemask;
1071 XpmImage *xpmimage;
1072 XpmAttributes *attributes;
1073 {
1074 XImage *ximage = NULL;
1075 XImage *shapeimage = NULL;
1076 unsigned int width = 0;
1077 unsigned int height = 0;
1078 int ErrorStatus;
1079
1080 /* get geometry */
1081 if (attributes && attributes->valuemask & XpmSize) {
1082 width = attributes->width;
1083 height = attributes->height;
1084 }
1085 /* get the ximages */
1086 if (pixmap)
1087 xpmCreateImageFromPixmap(display, pixmap, &ximage, &width, &height);
1088 if (shapemask)
1089 xpmCreateImageFromPixmap(display, shapemask, &shapeimage,
1090 &width, &height);
1091
1092 /* create the related XpmImage */
1093 ErrorStatus = XpmCreateXpmImageFromImage(display, ximage, shapeimage,
1094 xpmimage, attributes);
1095
1096 /* destroy the ximages */
1097 if (ximage)
1098 XDestroyImage(ximage);
1099 if (shapeimage)
1100 XDestroyImage(shapeimage);
1101
1102 return (ErrorStatus);
1103 }
1104
1105 # endif/* not AMIGA */
1106 #endif /* ndef FOR_MSW */