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