]>
git.saurik.com Git - wxWidgets.git/blob - src/xpm/scan.c
2 * Copyright (C) 1989-94 GROUPE BULL
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
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.
26 /*****************************************************************************\
30 * Scanning utility for XPM file format *
32 * Developed by Arnaud Le Hors *
33 \*****************************************************************************/
36 * The code related to FOR_MSW has been added by
37 * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
42 #define MAXPRINTABLE 92 /* number of printable ascii chars
43 * minus \ and " for string compat
44 * and ? to avoid ANSI trigraphs. */
46 static char *printable
=
47 " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\
48 ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
51 * printable begin with a space, so in most case, due to my algorithm, when
52 * the number of different colors is less than MAXPRINTABLE, it will give a
53 * char follow by "nothing" (a space) in the readable xpm file
59 unsigned int *pixelindex
;
62 unsigned int mask_pixel
; /* whether there is or not */
65 LFUNC(storePixel
, int, (Pixel pixel
, PixelsMap
*pmap
,
66 unsigned int *index_return
));
68 LFUNC(storeMaskPixel
, int, (Pixel pixel
, PixelsMap
*pmap
,
69 unsigned int *index_return
));
72 LFUNC(GetImagePixels
, int, (XImage
*image
, unsigned int width
,
73 unsigned int height
, PixelsMap
*pmap
));
75 LFUNC(GetImagePixels32
, int, (XImage
*image
, unsigned int width
,
76 unsigned int height
, PixelsMap
*pmap
));
78 LFUNC(GetImagePixels16
, int, (XImage
*image
, unsigned int width
,
79 unsigned int height
, PixelsMap
*pmap
));
81 LFUNC(GetImagePixels8
, int, (XImage
*image
, unsigned int width
,
82 unsigned int height
, PixelsMap
*pmap
));
84 LFUNC(GetImagePixels1
, int, (XImage
*image
, unsigned int width
,
85 unsigned int height
, PixelsMap
*pmap
,
86 int (*storeFunc
) (Pixel
,PixelsMap
*,
90 int (*storeFunc) ()));
93 #else /* ndef FOR_MSW */
94 LFUNC(MSWGetImagePixels
, int, (Display
*d
, XImage
*image
, unsigned int width
,
95 unsigned int height
, PixelsMap
*pmap
));
97 LFUNC(ScanTransparentColor
, int, (XpmColor
*color
, unsigned int cpp
,
98 XpmAttributes
*attributes
));
100 LFUNC(ScanOtherColors
, int, (Display
*display
, XpmColor
*colors
, int ncolors
,
101 Pixel
*pixels
, unsigned int mask
,
102 unsigned int cpp
, XpmAttributes
*attributes
));
105 * This function stores the given pixel in the given arrays which are grown
106 * if not large enough.
109 storePixel(Pixel pixel
, PixelsMap
*pmap
, unsigned int *index_return
)
113 unsigned int ncolors
;
115 if (*index_return
) { /* this is a transparent pixel! */
119 ncolors
= pmap
->ncolors
;
120 p
= pmap
->pixels
+ pmap
->mask_pixel
;
121 for (i
= pmap
->mask_pixel
; i
< ncolors
; i
++, p
++)
125 if (ncolors
>= pmap
->size
) {
127 p
= (Pixel
*) XpmRealloc(pmap
->pixels
, sizeof(Pixel
) * pmap
->size
);
133 (pmap
->pixels
)[ncolors
] = pixel
;
141 storeMaskPixel(Pixel pixel
, PixelsMap
*pmap
, unsigned int *index_return
)
144 if (!pmap
->ncolors
) {
146 (pmap
->pixels
)[0] = 0;
147 pmap
->mask_pixel
= 1;
155 /* function call in case of error, frees only locally allocated variables */
157 #define RETURN(status) \
159 if (pmap.pixelindex) XpmFree(pmap.pixelindex); \
160 if (pmap.pixels) XpmFree(pmap.pixels); \
161 if (colorTable) xpmFreeColorTable(colorTable, pmap.ncolors); \
166 * This function scans the given image and stores the found informations in
167 * the given XpmImage structure.
170 XpmCreateXpmImageFromImage(Display
*display
, XImage
*image
, XImage
*shapeimage
,
171 XpmImage
*xpmimage
, XpmAttributes
*attributes
)
173 /* variables stored in the XpmAttributes structure */
176 /* variables to return */
178 XpmColor
*colorTable
= NULL
;
181 /* calculation variables */
182 unsigned int width
= 0;
183 unsigned int height
= 0;
184 unsigned int cppm
; /* minimum chars per pixel */
188 /* initialize pmap */
190 pmap
.pixelindex
= NULL
;
191 pmap
.size
= 256; /* should be enough most of the time */
199 width
= image
->width
;
200 height
= image
->height
;
201 } else if (shapeimage
) {
202 width
= shapeimage
->width
;
203 height
= shapeimage
->height
;
207 * retrieve information from the XpmAttributes
209 if (attributes
&& (attributes
->valuemask
& XpmCharsPerPixel
210 /* 3.2 backward compatibility code */
211 || attributes
->valuemask
& XpmInfos
))
213 cpp
= attributes
->cpp
;
218 (unsigned int *) XpmCalloc(width
* height
, sizeof(unsigned int));
219 if (!pmap
.pixelindex
)
222 pmap
.pixels
= (Pixel
*) XpmMalloc(sizeof(Pixel
) * pmap
.size
);
227 * scan shape mask if any
231 ErrorStatus
= GetImagePixels1(shapeimage
, width
, height
, &pmap
,
234 ErrorStatus
= MSWGetImagePixels(display
, shapeimage
, width
, height
,
237 if (ErrorStatus
!= XpmSuccess
)
242 * scan the image data
244 * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use optimized
245 * functions, otherwise use slower but sure general one.
251 if (image
->depth
== 1)
252 ErrorStatus
= GetImagePixels1(image
, width
, height
, &pmap
,
254 else if (image
->bits_per_pixel
== 8)
255 ErrorStatus
= GetImagePixels8(image
, width
, height
, &pmap
);
256 else if (image
->bits_per_pixel
== 16)
257 ErrorStatus
= GetImagePixels16(image
, width
, height
, &pmap
);
258 else if (image
->bits_per_pixel
== 32)
259 ErrorStatus
= GetImagePixels32(image
, width
, height
, &pmap
);
261 ErrorStatus
= GetImagePixels(image
, width
, height
, &pmap
);
263 ErrorStatus
= MSWGetImagePixels(display
, image
, width
, height
, &pmap
);
265 if (ErrorStatus
!= XpmSuccess
)
270 * get rgb values and a string of char, and possibly a name for each
274 colorTable
= (XpmColor
*) XpmCalloc(pmap
.ncolors
, sizeof(XpmColor
));
278 /* compute the minimal cpp */
279 for (cppm
= 1, c
= MAXPRINTABLE
; pmap
.ncolors
> c
; cppm
++)
284 if (pmap
.mask_pixel
) {
285 ErrorStatus
= ScanTransparentColor(colorTable
, cpp
, attributes
);
286 if (ErrorStatus
!= XpmSuccess
)
292 ErrorStatus
= ScanOtherColors(display
, colorTable
+ offset
,
293 pmap
.ncolors
- offset
, pmap
.pixels
+ offset
,
294 pmap
.mask_pixel
, cpp
, attributes
);
295 if (ErrorStatus
!= XpmSuccess
)
299 * store found informations in the XpmImage structure
301 xpmimage
->width
= width
;
302 xpmimage
->height
= height
;
304 xpmimage
->ncolors
= pmap
.ncolors
;
305 xpmimage
->colorTable
= colorTable
;
306 xpmimage
->data
= pmap
.pixelindex
;
308 XpmFree(pmap
.pixels
);
313 ScanTransparentColor(XpmColor
*color
, unsigned int cpp
, XpmAttributes
*attributes
)
316 unsigned int a
, b
, c
;
318 /* first get a character string */
320 if (!(s
= color
->string
= (char *) XpmMalloc(cpp
+ 1)))
321 return (XpmNoMemory
);
322 *s
++ = printable
[c
= a
% MAXPRINTABLE
];
323 for (b
= 1; b
< cpp
; b
++, s
++)
324 *s
= printable
[c
= ((a
- c
) / MAXPRINTABLE
) % MAXPRINTABLE
];
327 /* then retreive related info from the attributes if any */
328 if (attributes
&& attributes
->mask_pixel
!= XpmUndefPixel
&& (
329 /* 3.2 backward compatibility code */
330 attributes
->valuemask
& XpmInfos
||
332 attributes
->valuemask
& XpmColorTable
)) {
335 char **defaults
= (char **) color
;
336 char **mask_defaults
;
338 /* 3.2 backward compatibility code */
339 if (attributes
->valuemask
& XpmInfos
)
340 mask_defaults
= (char **)
341 ((XpmColor
**) attributes
->colorTable
)[attributes
->mask_pixel
];
344 mask_defaults
= (char **) (
345 attributes
->colorTable
+ attributes
->mask_pixel
);
346 for (key
= 1; key
<= NKEYS
; key
++) {
347 if (s
= mask_defaults
[key
]) {
348 defaults
[key
] = (char *) strdup(s
);
350 return (XpmNoMemory
);
354 color
->c_color
= (char *) strdup(TRANSPARENT_COLOR
);
356 return (XpmNoMemory
);
362 ScanOtherColors(Display
*display
, XpmColor
*colors
, int ncolors
, Pixel
*pixels
,
363 unsigned int mask
, unsigned int cpp
, XpmAttributes
*attributes
)
365 /* variables stored in the XpmAttributes structure */
370 xpmRgbName rgbn
[MAX_RGBNAMES
];
372 xpmRgbName
*rgbn
= NULL
;
375 unsigned int i
, j
, c
, i2
;
377 XColor
*xcolors
= NULL
, *xcolor
;
379 XpmColor
*colorTable
, **oldColorTable
= NULL
;
380 unsigned int ancolors
= 0;
382 unsigned int mask_pixel
;
385 /* retrieve information from the XpmAttributes */
386 if (attributes
&& (attributes
->valuemask
& XpmColormap
))
387 colormap
= attributes
->colormap
;
389 colormap
= XDefaultColormap(display
, XDefaultScreen(display
));
390 if (attributes
&& (attributes
->valuemask
& XpmRgbFilename
))
391 rgb_fname
= attributes
->rgb_fname
;
395 /* first get character strings and rgb values */
396 xcolors
= (XColor
*) XpmMalloc(sizeof(XColor
) * ncolors
);
398 return (XpmNoMemory
);
400 for (i
= 0, i2
= (mask
? i
+ 1 : i
), color
= colors
, xcolor
= xcolors
;
401 i
< ncolors
; i
++, i2
++, color
++, xcolor
++, pixels
++) {
403 if (!(s
= color
->string
= (char *) XpmMalloc(cpp
+ 1))) {
405 return (XpmNoMemory
);
407 *s
++ = printable
[c
= i2
% MAXPRINTABLE
];
408 for (j
= 1; j
< cpp
; j
++, s
++)
409 *s
= printable
[c
= ((i2
- c
) / MAXPRINTABLE
) % MAXPRINTABLE
];
412 xcolor
->pixel
= *pixels
;
415 XQueryColors(display
, (Colormap
*)colormap
, xcolors
, ncolors
);
417 XQueryColors(display
, (Colormap
)colormap
, xcolors
, ncolors
);
421 /* read the rgb file if any was specified */
423 rgbn_max
= xpmReadRgbNames(attributes
->rgb_fname
, rgbn
);
425 /* FOR_MSW: rgb names and values are hardcoded in rgbtab.h */
426 rgbn_max
= xpmReadRgbNames(NULL
, NULL
);
429 if (attributes
&& attributes
->valuemask
& XpmColorTable
) {
430 colorTable
= attributes
->colorTable
;
431 ancolors
= attributes
->ncolors
;
432 apixels
= attributes
->pixels
;
433 mask_pixel
= attributes
->mask_pixel
;
435 /* 3.2 backward compatibility code */
436 else if (attributes
&& attributes
->valuemask
& XpmInfos
) {
437 oldColorTable
= (XpmColor
**) attributes
->colorTable
;
438 ancolors
= attributes
->ncolors
;
439 apixels
= attributes
->pixels
;
440 mask_pixel
= attributes
->mask_pixel
;
444 for (i
= 0, color
= colors
, xcolor
= xcolors
; i
< ncolors
;
445 i
++, color
++, xcolor
++) {
447 /* look for related info from the attributes if any */
450 unsigned int offset
= 0;
452 for (j
= 0; j
< ancolors
; j
++) {
453 if (j
== mask_pixel
) {
457 if (apixels
[j
- offset
] == xcolor
->pixel
)
462 char **defaults
= (char **) color
;
465 /* 3.2 backward compatibility code */
467 adefaults
= (char **) oldColorTable
[j
];
470 adefaults
= (char **) (colorTable
+ j
);
473 for (key
= 1; key
<= NKEYS
; key
++) {
474 if (s
= adefaults
[key
])
475 defaults
[key
] = (char *) strdup(s
);
480 /* if nothing found look for a color name */
483 colorname
= xpmGetRgbName(rgbn
, rgbn_max
, xcolor
->red
,
484 xcolor
->green
, xcolor
->blue
);
486 color
->c_color
= (char *) strdup(colorname
);
488 /* at last store the rgb value */
491 sprintf(buf
, "#%04X%04X%04X",
492 xcolor
->red
, xcolor
->green
, xcolor
->blue
);
494 sprintf(buf
, "#%02x%02x%02x",
495 xcolor
->red
, xcolor
->green
, xcolor
->blue
);
497 color
->c_color
= (char *) strdup(buf
);
499 if (!color
->c_color
) {
501 xpmFreeRgbNames(rgbn
, rgbn_max
);
502 return (XpmNoMemory
);
508 xpmFreeRgbNames(rgbn
, rgbn_max
);
514 * The functions below are written from X11R5 MIT's code (XImUtil.c)
516 * The idea is to have faster functions than the standard XGetPixel function
517 * to scan the image data. Indeed we can speed up things by suppressing tests
518 * performed for each pixel. We do exactly the same tests but at the image
519 * level. Assuming that we use only ZPixmap images.
522 static unsigned long Const low_bits_table
[] = {
523 0x00000000, 0x00000001, 0x00000003, 0x00000007,
524 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
525 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
526 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
527 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
528 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
529 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
530 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
535 * Default method to scan pixels of a Z image data structure.
536 * The algorithm used is:
538 * copy the source bitmap_unit or Zpixel into temp
539 * normalize temp if needed
540 * extract the pixel bits into return value
545 GetImagePixels(XImage
*image
, unsigned int width
, unsigned int height
, PixelsMap
*pmap
)
552 int bits
, depth
, ibu
, ibpp
;
557 iptr
= pmap
->pixelindex
;
558 depth
= image
->depth
;
559 lbt
= low_bits_table
[depth
];
560 ibpp
= image
->bits_per_pixel
;
561 if (image
->depth
== 1) {
562 ibu
= image
->bitmap_unit
;
563 for (y
= 0; y
< height
; y
++)
564 for (x
= 0; x
< width
; x
++, iptr
++) {
565 src
= &data
[XYINDEX(x
, y
, image
)];
566 dst
= (char *) &pixel
;
568 for (i
= ibu
>> 3; --i
>= 0;)
570 XYNORMALIZE(&pixel
, image
);
572 pixel
= ((((char *) &pixel
)[bits
>> 3]) >> (bits
& 7)) & 1;
575 if (storePixel(pixel
, pmap
, iptr
))
576 return (XpmNoMemory
);
579 for (y
= 0; y
< height
; y
++)
580 for (x
= 0; x
< width
; x
++, iptr
++) {
581 src
= &data
[ZINDEX(x
, y
, image
)];
584 for (i
= (ibpp
+ 7) >> 3; --i
>= 0;)
586 ZNORMALIZE(&px
, image
);
588 for (i
= sizeof(unsigned long); --i
>= 0;)
589 pixel
= (pixel
<< 8) | ((unsigned char *) &px
)[i
];
598 if (storePixel(pixel
, pmap
, iptr
))
599 return (XpmNoMemory
);
606 * scan pixels of a 32-bits Z image data structure
610 static unsigned long byteorderpixel
= MSBFirst
<< 24;
615 GetImagePixels32(XImage
*image
, unsigned int width
, unsigned int height
, PixelsMap
*pmap
)
625 data
= (unsigned char *) image
->data
;
626 iptr
= pmap
->pixelindex
;
627 depth
= image
->depth
;
628 lbt
= low_bits_table
[depth
];
630 if (*((char *) &byteorderpixel
) == image
->byte_order
) {
631 for (y
= 0; y
< height
; y
++)
632 for (x
= 0; x
< width
; x
++, iptr
++) {
633 addr
= &data
[ZINDEX32(x
, y
, image
)];
634 pixel
= *((unsigned long *) addr
);
637 if (storePixel(pixel
, pmap
, iptr
))
638 return (XpmNoMemory
);
642 if (image
->byte_order
== MSBFirst
)
643 for (y
= 0; y
< height
; y
++)
644 for (x
= 0; x
< width
; x
++, iptr
++) {
645 addr
= &data
[ZINDEX32(x
, y
, image
)];
646 pixel
= ((unsigned long) addr
[0] << 24 |
647 (unsigned long) addr
[1] << 16 |
648 (unsigned long) addr
[2] << 8 |
652 if (storePixel(pixel
, pmap
, iptr
))
653 return (XpmNoMemory
);
656 for (y
= 0; y
< height
; y
++)
657 for (x
= 0; x
< width
; x
++, iptr
++) {
658 addr
= &data
[ZINDEX32(x
, y
, image
)];
660 (unsigned long) addr
[1] << 8 |
661 (unsigned long) addr
[2] << 16 |
662 (unsigned long) addr
[3] << 24);
665 if (storePixel(pixel
, pmap
, iptr
))
666 return (XpmNoMemory
);
672 * scan pixels of a 16-bits Z image data structure
676 GetImagePixels16(XImage
*image
, unsigned int width
, unsigned int height
, PixelsMap
*pmap
)
686 data
= (unsigned char *) image
->data
;
687 iptr
= pmap
->pixelindex
;
688 depth
= image
->depth
;
689 lbt
= low_bits_table
[depth
];
690 if (image
->byte_order
== MSBFirst
)
691 for (y
= 0; y
< height
; y
++)
692 for (x
= 0; x
< width
; x
++, iptr
++) {
693 addr
= &data
[ZINDEX16(x
, y
, image
)];
694 pixel
= addr
[0] << 8 | addr
[1];
697 if (storePixel(pixel
, pmap
, iptr
))
698 return (XpmNoMemory
);
701 for (y
= 0; y
< height
; y
++)
702 for (x
= 0; x
< width
; x
++, iptr
++) {
703 addr
= &data
[ZINDEX16(x
, y
, image
)];
704 pixel
= addr
[0] | addr
[1] << 8;
707 if (storePixel(pixel
, pmap
, iptr
))
708 return (XpmNoMemory
);
714 * scan pixels of a 8-bits Z image data structure
718 GetImagePixels8(XImage
*image
, unsigned int width
, unsigned int height
, PixelsMap
*pmap
)
727 data
= (unsigned char *) image
->data
;
728 iptr
= pmap
->pixelindex
;
729 depth
= image
->depth
;
730 lbt
= low_bits_table
[depth
];
731 for (y
= 0; y
< height
; y
++)
732 for (x
= 0; x
< width
; x
++, iptr
++) {
733 pixel
= data
[ZINDEX8(x
, y
, image
)];
736 if (storePixel(pixel
, pmap
, iptr
))
737 return (XpmNoMemory
);
743 * scan pixels of a 1-bit depth Z image data structure
747 GetImagePixels1(XImage
*image
, unsigned int width
, unsigned int height
, PixelsMap
*pmap
,
751 int (*storeFunc
)(Pixel
,PixelsMap
*,unsigned int*)
759 if (image
->byte_order
!= image
->bitmap_bit_order
)
760 return (GetImagePixels(image
, width
, height
, pmap
));
763 iptr
= pmap
->pixelindex
;
764 if (image
->bitmap_bit_order
== MSBFirst
)
765 for (y
= 0; y
< height
; y
++)
766 for (x
= 0; x
< width
; x
++, iptr
++) {
767 pixel
= (data
[ZINDEX1(x
, y
, image
)] & (0x80 >> (x
& 7)))
769 if ((*storeFunc
) (pixel
, pmap
, iptr
))
770 return (XpmNoMemory
);
773 for (y
= 0; y
< height
; y
++)
774 for (x
= 0; x
< width
; x
++, iptr
++) {
775 pixel
= (data
[ZINDEX1(x
, y
, image
)] & (1 << (x
& 7)))
777 if ((*storeFunc
) (pixel
, pmap
, iptr
))
778 return (XpmNoMemory
);
784 #else /* ndef FOR_MSW */
786 MSWGetImagePixels(Display
*display
, XImage
*image
, unsigned int width
, unsigned int height
, PixelsMap
*pmap
)
792 iptr
= pmap
->pixelindex
;
794 for (y
= 0; y
< height
; y
++) {
795 for (x
= 0; x
< width
; x
++, iptr
++) {
796 /* bitmap must be selected !!! ??? */
797 pixel
= GetPixel(*display
, x
, y
);
798 if (storePixel(pixel
, pmap
, iptr
))
799 return (XpmNoMemory
);
809 XpmCreateXpmImageFromPixmap(Display
*display
, Pixmap pixmap
, Pixmap shapemask
,
810 XpmImage
*xpmimage
, XpmAttributes
*attributes
)
812 XImage
*ximage
= NULL
;
813 XImage
*shapeimage
= NULL
;
814 unsigned int width
= 0;
815 unsigned int height
= 0;
819 if (attributes
&& attributes
->valuemask
& XpmSize
) {
820 width
= attributes
->width
;
821 height
= attributes
->height
;
823 /* get the ximages */
825 xpmCreateImageFromPixmap(display
, pixmap
, &ximage
, &width
, &height
);
827 xpmCreateImageFromPixmap(display
, shapemask
, &shapeimage
,
830 /* create the related XpmImage */
831 ErrorStatus
= XpmCreateXpmImageFromImage(display
, ximage
, shapeimage
,
832 xpmimage
, attributes
);
834 /* destroy the ximages */
836 XDestroyImage(ximage
);
838 XDestroyImage(shapeimage
);
840 return (ErrorStatus
);
843 #endif /* ndef FOR_MSW */