]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1989-94 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 | #include "xpm34p.h" | |
41 | ||
42 | #define MAXPRINTABLE 92 /* number of printable ascii chars | |
43 | * minus \ and " for string compat | |
44 | * and ? to avoid ANSI trigraphs. */ | |
45 | ||
46 | static char *printable = | |
47 | " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\ | |
48 | ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; | |
49 | ||
50 | /* | |
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 | |
54 | */ | |
55 | ||
56 | ||
57 | typedef struct { | |
58 | Pixel *pixels; | |
59 | unsigned int *pixelindex; | |
60 | unsigned int size; | |
61 | unsigned int ncolors; | |
62 | unsigned int mask_pixel; /* whether there is or not */ | |
63 | } PixelsMap; | |
64 | ||
65 | LFUNC(storePixel, int, (Pixel pixel, PixelsMap *pmap, | |
66 | unsigned int *index_return)); | |
67 | ||
68 | LFUNC(storeMaskPixel, int, (Pixel pixel, PixelsMap *pmap, | |
69 | unsigned int *index_return)); | |
70 | ||
71 | #ifndef FOR_MSW | |
72 | LFUNC(GetImagePixels, int, (XImage *image, unsigned int width, | |
73 | unsigned int height, PixelsMap *pmap)); | |
74 | ||
75 | LFUNC(GetImagePixels32, int, (XImage *image, unsigned int width, | |
76 | unsigned int height, PixelsMap *pmap)); | |
77 | ||
78 | LFUNC(GetImagePixels16, int, (XImage *image, unsigned int width, | |
79 | unsigned int height, PixelsMap *pmap)); | |
80 | ||
81 | LFUNC(GetImagePixels8, int, (XImage *image, unsigned int width, | |
82 | unsigned int height, PixelsMap *pmap)); | |
83 | ||
84 | LFUNC(GetImagePixels1, int, (XImage *image, unsigned int width, | |
85 | unsigned int height, PixelsMap *pmap, | |
86 | int (*storeFunc) (Pixel,PixelsMap*, | |
87 | unsigned int*))); | |
88 | ||
89 | /* | |
90 | int (*storeFunc) ())); | |
91 | */ | |
92 | ||
93 | #else /* ndef FOR_MSW */ | |
94 | LFUNC(MSWGetImagePixels, int, (Display *d, XImage *image, unsigned int width, | |
95 | unsigned int height, PixelsMap *pmap)); | |
96 | #endif | |
97 | LFUNC(ScanTransparentColor, int, (XpmColor *color, unsigned int cpp, | |
98 | XpmAttributes *attributes)); | |
99 | ||
100 | LFUNC(ScanOtherColors, int, (Display *display, XpmColor *colors, int ncolors, | |
101 | Pixel *pixels, unsigned int mask, | |
102 | unsigned int cpp, XpmAttributes *attributes)); | |
103 | ||
104 | /* | |
105 | * This function stores the given pixel in the given arrays which are grown | |
106 | * if not large enough. | |
107 | */ | |
108 | static int | |
109 | storePixel(Pixel pixel, PixelsMap *pmap, unsigned int *index_return) | |
110 | { | |
111 | unsigned int i; | |
112 | Pixel *p; | |
113 | unsigned int ncolors; | |
114 | ||
115 | if (*index_return) { /* this is a transparent pixel! */ | |
116 | *index_return = 0; | |
117 | return 0; | |
118 | } | |
119 | ncolors = pmap->ncolors; | |
120 | p = pmap->pixels + pmap->mask_pixel; | |
121 | for (i = pmap->mask_pixel; i < ncolors; i++, p++) | |
122 | if (*p == pixel) | |
123 | break; | |
124 | if (i == ncolors) { | |
125 | if (ncolors >= pmap->size) { | |
126 | pmap->size *= 2; | |
127 | p = (Pixel *) XpmRealloc(pmap->pixels, sizeof(Pixel) * pmap->size); | |
128 | if (!p) | |
129 | return (1); | |
130 | pmap->pixels = p; | |
131 | ||
132 | } | |
133 | (pmap->pixels)[ncolors] = pixel; | |
134 | pmap->ncolors++; | |
135 | } | |
136 | *index_return = i; | |
137 | return 0; | |
138 | } | |
139 | ||
140 | static int | |
141 | storeMaskPixel(Pixel pixel, PixelsMap *pmap, unsigned int *index_return) | |
142 | { | |
143 | if (!pixel) { | |
144 | if (!pmap->ncolors) { | |
145 | pmap->ncolors = 1; | |
146 | (pmap->pixels)[0] = 0; | |
147 | pmap->mask_pixel = 1; | |
148 | } | |
149 | *index_return = 1; | |
150 | } else | |
151 | *index_return = 0; | |
152 | return 0; | |
153 | } | |
154 | ||
155 | /* function call in case of error, frees only locally allocated variables */ | |
156 | #undef RETURN | |
157 | #define RETURN(status) \ | |
158 | { \ | |
159 | if (pmap.pixelindex) XpmFree(pmap.pixelindex); \ | |
160 | if (pmap.pixels) XpmFree(pmap.pixels); \ | |
161 | if (colorTable) xpmFreeColorTable(colorTable, pmap.ncolors); \ | |
162 | return(status); \ | |
163 | } | |
164 | ||
165 | /* | |
166 | * This function scans the given image and stores the found informations in | |
167 | * the given XpmImage structure. | |
168 | */ | |
169 | int | |
170 | XpmCreateXpmImageFromImage(Display *display, XImage *image, XImage *shapeimage, | |
171 | XpmImage *xpmimage, XpmAttributes *attributes) | |
172 | { | |
173 | /* variables stored in the XpmAttributes structure */ | |
174 | unsigned int cpp; | |
175 | ||
176 | /* variables to return */ | |
177 | PixelsMap pmap; | |
178 | XpmColor *colorTable = NULL; | |
179 | int ErrorStatus; | |
180 | ||
181 | /* calculation variables */ | |
182 | unsigned int width = 0; | |
183 | unsigned int height = 0; | |
184 | unsigned int cppm; /* minimum chars per pixel */ | |
185 | unsigned int c; | |
186 | unsigned int offset; | |
187 | ||
188 | /* initialize pmap */ | |
189 | pmap.pixels = NULL; | |
190 | pmap.pixelindex = NULL; | |
191 | pmap.size = 256; /* should be enough most of the time */ | |
192 | pmap.ncolors = 0; | |
193 | pmap.mask_pixel = 0; | |
194 | ||
195 | /* | |
196 | * get geometry | |
197 | */ | |
198 | if (image) { | |
199 | width = image->width; | |
200 | height = image->height; | |
201 | } else if (shapeimage) { | |
202 | width = shapeimage->width; | |
203 | height = shapeimage->height; | |
204 | } | |
205 | ||
206 | /* | |
207 | * retrieve information from the XpmAttributes | |
208 | */ | |
209 | if (attributes && (attributes->valuemask & XpmCharsPerPixel | |
210 | /* 3.2 backward compatibility code */ | |
211 | || attributes->valuemask & XpmInfos)) | |
212 | /* end 3.2 bc */ | |
213 | cpp = attributes->cpp; | |
214 | else | |
215 | cpp = 0; | |
216 | ||
217 | pmap.pixelindex = | |
218 | (unsigned int *) XpmCalloc(width * height, sizeof(unsigned int)); | |
219 | if (!pmap.pixelindex) | |
220 | RETURN(XpmNoMemory); | |
221 | ||
222 | pmap.pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * pmap.size); | |
223 | if (!pmap.pixels) | |
224 | RETURN(XpmNoMemory); | |
225 | ||
226 | /* | |
227 | * scan shape mask if any | |
228 | */ | |
229 | if (shapeimage) { | |
230 | #ifndef FOR_MSW | |
231 | ErrorStatus = GetImagePixels1(shapeimage, width, height, &pmap, | |
232 | storeMaskPixel); | |
233 | #else | |
234 | ErrorStatus = MSWGetImagePixels(display, shapeimage, width, height, | |
235 | &pmap); | |
236 | #endif | |
237 | if (ErrorStatus != XpmSuccess) | |
238 | RETURN(ErrorStatus); | |
239 | } | |
240 | ||
241 | /* | |
242 | * scan the image data | |
243 | * | |
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. | |
246 | * | |
247 | */ | |
248 | ||
249 | if (image) { | |
250 | #ifndef FOR_MSW | |
251 | if (image->depth == 1) | |
252 | ErrorStatus = GetImagePixels1(image, width, height, &pmap, | |
253 | storePixel); | |
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); | |
260 | else | |
261 | ErrorStatus = GetImagePixels(image, width, height, &pmap); | |
262 | #else /* FOR_MSW */ | |
263 | ErrorStatus = MSWGetImagePixels(display, image, width, height, &pmap); | |
264 | #endif | |
265 | if (ErrorStatus != XpmSuccess) | |
266 | RETURN(ErrorStatus); | |
267 | } | |
268 | ||
269 | /* | |
270 | * get rgb values and a string of char, and possibly a name for each | |
271 | * color | |
272 | */ | |
273 | ||
274 | colorTable = (XpmColor *) XpmCalloc(pmap.ncolors, sizeof(XpmColor)); | |
275 | if (!colorTable) | |
276 | RETURN(XpmNoMemory); | |
277 | ||
278 | /* compute the minimal cpp */ | |
279 | for (cppm = 1, c = MAXPRINTABLE; pmap.ncolors > c; cppm++) | |
280 | c *= MAXPRINTABLE; | |
281 | if (cpp < cppm) | |
282 | cpp = cppm; | |
283 | ||
284 | if (pmap.mask_pixel) { | |
285 | ErrorStatus = ScanTransparentColor(colorTable, cpp, attributes); | |
286 | if (ErrorStatus != XpmSuccess) | |
287 | RETURN(ErrorStatus); | |
288 | offset = 1; | |
289 | } else | |
290 | offset = 0; | |
291 | ||
292 | ErrorStatus = ScanOtherColors(display, colorTable + offset, | |
293 | pmap.ncolors - offset, pmap.pixels + offset, | |
294 | pmap.mask_pixel, cpp, attributes); | |
295 | if (ErrorStatus != XpmSuccess) | |
296 | RETURN(ErrorStatus); | |
297 | ||
298 | /* | |
299 | * store found informations in the XpmImage structure | |
300 | */ | |
301 | xpmimage->width = width; | |
302 | xpmimage->height = height; | |
303 | xpmimage->cpp = cpp; | |
304 | xpmimage->ncolors = pmap.ncolors; | |
305 | xpmimage->colorTable = colorTable; | |
306 | xpmimage->data = pmap.pixelindex; | |
307 | ||
308 | XpmFree(pmap.pixels); | |
309 | return (XpmSuccess); | |
310 | } | |
311 | ||
312 | static int | |
313 | ScanTransparentColor(XpmColor *color, unsigned int cpp, XpmAttributes *attributes) | |
314 | { | |
315 | char *s; | |
316 | unsigned int a, b, c; | |
317 | ||
318 | /* first get a character string */ | |
319 | a = 0; | |
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]; | |
325 | *s = '\0'; | |
326 | ||
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 || | |
331 | /* end 3.2 bc */ | |
332 | attributes->valuemask & XpmColorTable)) { | |
333 | ||
334 | unsigned int key; | |
335 | char **defaults = (char **) color; | |
336 | char **mask_defaults; | |
337 | ||
338 | /* 3.2 backward compatibility code */ | |
339 | if (attributes->valuemask & XpmInfos) | |
340 | mask_defaults = (char **) | |
341 | ((XpmColor **) attributes->colorTable)[attributes->mask_pixel]; | |
342 | else | |
343 | /* end 3.2 bc */ | |
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); | |
349 | if (!defaults[key]) | |
350 | return (XpmNoMemory); | |
351 | } | |
352 | } | |
353 | } else { | |
354 | color->c_color = (char *) strdup(TRANSPARENT_COLOR); | |
355 | if (!color->c_color) | |
356 | return (XpmNoMemory); | |
357 | } | |
358 | return (XpmSuccess); | |
359 | } | |
360 | ||
361 | static int | |
362 | ScanOtherColors(Display *display, XpmColor *colors, int ncolors, Pixel *pixels, | |
363 | unsigned int mask, unsigned int cpp, XpmAttributes *attributes) | |
364 | { | |
365 | /* variables stored in the XpmAttributes structure */ | |
366 | Colormap colormap; | |
367 | char *rgb_fname; | |
368 | ||
369 | #ifndef FOR_MSW | |
370 | xpmRgbName rgbn[MAX_RGBNAMES]; | |
371 | #else | |
372 | xpmRgbName *rgbn = NULL; | |
373 | #endif | |
374 | int rgbn_max = 0; | |
375 | unsigned int i, j, c, i2; | |
376 | XpmColor *color; | |
377 | XColor *xcolors = NULL, *xcolor; | |
378 | char *colorname, *s; | |
379 | XpmColor *colorTable, **oldColorTable = NULL; | |
380 | unsigned int ancolors = 0; | |
381 | Pixel *apixels; | |
382 | unsigned int mask_pixel; | |
383 | int found; | |
384 | ||
385 | /* retrieve information from the XpmAttributes */ | |
386 | if (attributes && (attributes->valuemask & XpmColormap)) | |
387 | colormap = attributes->colormap; | |
388 | else | |
389 | colormap = XDefaultColormap(display, XDefaultScreen(display)); | |
390 | if (attributes && (attributes->valuemask & XpmRgbFilename)) | |
391 | rgb_fname = attributes->rgb_fname; | |
392 | else | |
393 | rgb_fname = NULL; | |
394 | ||
395 | /* first get character strings and rgb values */ | |
396 | xcolors = (XColor *) XpmMalloc(sizeof(XColor) * ncolors); | |
397 | if (!xcolors) | |
398 | return (XpmNoMemory); | |
399 | ||
400 | for (i = 0, i2 = (mask ? i + 1 : i), color = colors, xcolor = xcolors; | |
401 | i < ncolors; i++, i2++, color++, xcolor++, pixels++) { | |
402 | ||
403 | if (!(s = color->string = (char *) XpmMalloc(cpp + 1))) { | |
404 | XpmFree(xcolors); | |
405 | return (XpmNoMemory); | |
406 | } | |
407 | *s++ = printable[c = i2 % MAXPRINTABLE]; | |
408 | for (j = 1; j < cpp; j++, s++) | |
409 | *s = printable[c = ((i2 - c) / MAXPRINTABLE) % MAXPRINTABLE]; | |
410 | *s = '\0'; | |
411 | ||
412 | xcolor->pixel = *pixels; | |
413 | } | |
414 | #ifdef wx_msw | |
415 | XQueryColors(display, (Colormap *)colormap, xcolors, ncolors); | |
416 | #else | |
417 | XQueryColors(display, (Colormap)colormap, xcolors, ncolors); | |
418 | #endif | |
419 | ||
420 | #ifndef FOR_MSW | |
421 | /* read the rgb file if any was specified */ | |
422 | if (rgb_fname) | |
423 | rgbn_max = xpmReadRgbNames(attributes->rgb_fname, rgbn); | |
424 | #else | |
425 | /* FOR_MSW: rgb names and values are hardcoded in rgbtab.h */ | |
426 | rgbn_max = xpmReadRgbNames(NULL, NULL); | |
427 | #endif | |
428 | ||
429 | if (attributes && attributes->valuemask & XpmColorTable) { | |
430 | colorTable = attributes->colorTable; | |
431 | ancolors = attributes->ncolors; | |
432 | apixels = attributes->pixels; | |
433 | mask_pixel = attributes->mask_pixel; | |
434 | } | |
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; | |
441 | } | |
442 | /* end 3.2 bc */ | |
443 | ||
444 | for (i = 0, color = colors, xcolor = xcolors; i < ncolors; | |
445 | i++, color++, xcolor++) { | |
446 | ||
447 | /* look for related info from the attributes if any */ | |
448 | found = False; | |
449 | if (ancolors) { | |
450 | unsigned int offset = 0; | |
451 | ||
452 | for (j = 0; j < ancolors; j++) { | |
453 | if (j == mask_pixel) { | |
454 | offset = 1; | |
455 | continue; | |
456 | } | |
457 | if (apixels[j - offset] == xcolor->pixel) | |
458 | break; | |
459 | } | |
460 | if (j != ancolors) { | |
461 | unsigned int key; | |
462 | char **defaults = (char **) color; | |
463 | char **adefaults; | |
464 | ||
465 | /* 3.2 backward compatibility code */ | |
466 | if (oldColorTable) | |
467 | adefaults = (char **) oldColorTable[j]; | |
468 | else | |
469 | /* end 3.2 bc */ | |
470 | adefaults = (char **) (colorTable + j); | |
471 | ||
472 | found = True; | |
473 | for (key = 1; key <= NKEYS; key++) { | |
474 | if (s = adefaults[key]) | |
475 | defaults[key] = (char *) strdup(s); | |
476 | } | |
477 | } | |
478 | } | |
479 | if (!found) { | |
480 | /* if nothing found look for a color name */ | |
481 | colorname = NULL; | |
482 | if (rgbn_max) | |
483 | colorname = xpmGetRgbName(rgbn, rgbn_max, xcolor->red, | |
484 | xcolor->green, xcolor->blue); | |
485 | if (colorname) | |
486 | color->c_color = (char *) strdup(colorname); | |
487 | else { | |
488 | /* at last store the rgb value */ | |
489 | char buf[BUFSIZ]; | |
490 | #ifndef FOR_MSW | |
491 | sprintf(buf, "#%04X%04X%04X", | |
492 | xcolor->red, xcolor->green, xcolor->blue); | |
493 | #else | |
494 | sprintf(buf, "#%02x%02x%02x", | |
495 | xcolor->red, xcolor->green, xcolor->blue); | |
496 | #endif | |
497 | color->c_color = (char *) strdup(buf); | |
498 | } | |
499 | if (!color->c_color) { | |
500 | XpmFree(xcolors); | |
501 | xpmFreeRgbNames(rgbn, rgbn_max); | |
502 | return (XpmNoMemory); | |
503 | } | |
504 | } | |
505 | } | |
506 | ||
507 | XpmFree(xcolors); | |
508 | xpmFreeRgbNames(rgbn, rgbn_max); | |
509 | return (XpmSuccess); | |
510 | } | |
511 | ||
512 | #ifndef FOR_MSW | |
513 | /* | |
514 | * The functions below are written from X11R5 MIT's code (XImUtil.c) | |
515 | * | |
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. | |
520 | */ | |
521 | ||
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, | |
531 | 0xffffffff | |
532 | }; | |
533 | ||
534 | /* | |
535 | * Default method to scan pixels of a Z image data structure. | |
536 | * The algorithm used is: | |
537 | * | |
538 | * copy the source bitmap_unit or Zpixel into temp | |
539 | * normalize temp if needed | |
540 | * extract the pixel bits into return value | |
541 | * | |
542 | */ | |
543 | ||
544 | static int | |
545 | GetImagePixels(XImage *image, unsigned int width, unsigned int height, PixelsMap *pmap) | |
546 | { | |
547 | char *src; | |
548 | char *dst; | |
549 | unsigned int *iptr; | |
550 | char *data; | |
551 | int x, y, i; | |
552 | int bits, depth, ibu, ibpp; | |
553 | unsigned long lbt; | |
554 | Pixel pixel, px; | |
555 | ||
556 | data = image->data; | |
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; | |
567 | pixel = 0; | |
568 | for (i = ibu >> 3; --i >= 0;) | |
569 | *dst++ = *src++; | |
570 | XYNORMALIZE(&pixel, image); | |
571 | bits = x % ibu; | |
572 | pixel = ((((char *) &pixel)[bits >> 3]) >> (bits & 7)) & 1; | |
573 | if (ibpp != depth) | |
574 | pixel &= lbt; | |
575 | if (storePixel(pixel, pmap, iptr)) | |
576 | return (XpmNoMemory); | |
577 | } | |
578 | } else { | |
579 | for (y = 0; y < height; y++) | |
580 | for (x = 0; x < width; x++, iptr++) { | |
581 | src = &data[ZINDEX(x, y, image)]; | |
582 | dst = (char *) &px; | |
583 | px = 0; | |
584 | for (i = (ibpp + 7) >> 3; --i >= 0;) | |
585 | *dst++ = *src++; | |
586 | ZNORMALIZE(&px, image); | |
587 | pixel = 0; | |
588 | for (i = sizeof(unsigned long); --i >= 0;) | |
589 | pixel = (pixel << 8) | ((unsigned char *) &px)[i]; | |
590 | if (ibpp == 4) { | |
591 | if (x & 1) | |
592 | pixel >>= 4; | |
593 | else | |
594 | pixel &= 0xf; | |
595 | } | |
596 | if (ibpp != depth) | |
597 | pixel &= lbt; | |
598 | if (storePixel(pixel, pmap, iptr)) | |
599 | return (XpmNoMemory); | |
600 | } | |
601 | } | |
602 | return (XpmSuccess); | |
603 | } | |
604 | ||
605 | /* | |
606 | * scan pixels of a 32-bits Z image data structure | |
607 | */ | |
608 | ||
609 | #ifndef WORD64 | |
610 | static unsigned long byteorderpixel = MSBFirst << 24; | |
611 | ||
612 | #endif | |
613 | ||
614 | static int | |
615 | GetImagePixels32(XImage *image, unsigned int width, unsigned int height, PixelsMap *pmap) | |
616 | { | |
617 | unsigned char *addr; | |
618 | unsigned char *data; | |
619 | unsigned int *iptr; | |
620 | int x, y; | |
621 | unsigned long lbt; | |
622 | Pixel pixel; | |
623 | int depth; | |
624 | ||
625 | data = (unsigned char *) image->data; | |
626 | iptr = pmap->pixelindex; | |
627 | depth = image->depth; | |
628 | lbt = low_bits_table[depth]; | |
629 | #ifndef WORD64 | |
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); | |
635 | if (depth != 32) | |
636 | pixel &= lbt; | |
637 | if (storePixel(pixel, pmap, iptr)) | |
638 | return (XpmNoMemory); | |
639 | } | |
640 | } else | |
641 | #endif | |
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 | | |
649 | addr[4]); | |
650 | if (depth != 32) | |
651 | pixel &= lbt; | |
652 | if (storePixel(pixel, pmap, iptr)) | |
653 | return (XpmNoMemory); | |
654 | } | |
655 | else | |
656 | for (y = 0; y < height; y++) | |
657 | for (x = 0; x < width; x++, iptr++) { | |
658 | addr = &data[ZINDEX32(x, y, image)]; | |
659 | pixel = (addr[0] | | |
660 | (unsigned long) addr[1] << 8 | | |
661 | (unsigned long) addr[2] << 16 | | |
662 | (unsigned long) addr[3] << 24); | |
663 | if (depth != 32) | |
664 | pixel &= lbt; | |
665 | if (storePixel(pixel, pmap, iptr)) | |
666 | return (XpmNoMemory); | |
667 | } | |
668 | return (XpmSuccess); | |
669 | } | |
670 | ||
671 | /* | |
672 | * scan pixels of a 16-bits Z image data structure | |
673 | */ | |
674 | ||
675 | static int | |
676 | GetImagePixels16(XImage *image, unsigned int width, unsigned int height, PixelsMap *pmap) | |
677 | { | |
678 | unsigned char *addr; | |
679 | unsigned char *data; | |
680 | unsigned int *iptr; | |
681 | int x, y; | |
682 | unsigned long lbt; | |
683 | Pixel pixel; | |
684 | int depth; | |
685 | ||
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]; | |
695 | if (depth != 16) | |
696 | pixel &= lbt; | |
697 | if (storePixel(pixel, pmap, iptr)) | |
698 | return (XpmNoMemory); | |
699 | } | |
700 | else | |
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; | |
705 | if (depth != 16) | |
706 | pixel &= lbt; | |
707 | if (storePixel(pixel, pmap, iptr)) | |
708 | return (XpmNoMemory); | |
709 | } | |
710 | return (XpmSuccess); | |
711 | } | |
712 | ||
713 | /* | |
714 | * scan pixels of a 8-bits Z image data structure | |
715 | */ | |
716 | ||
717 | static int | |
718 | GetImagePixels8(XImage *image, unsigned int width, unsigned int height, PixelsMap *pmap) | |
719 | { | |
720 | unsigned int *iptr; | |
721 | unsigned char *data; | |
722 | int x, y; | |
723 | unsigned long lbt; | |
724 | Pixel pixel; | |
725 | int depth; | |
726 | ||
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)]; | |
734 | if (depth != 8) | |
735 | pixel &= lbt; | |
736 | if (storePixel(pixel, pmap, iptr)) | |
737 | return (XpmNoMemory); | |
738 | } | |
739 | return (XpmSuccess); | |
740 | } | |
741 | ||
742 | /* | |
743 | * scan pixels of a 1-bit depth Z image data structure | |
744 | */ | |
745 | ||
746 | static int | |
747 | GetImagePixels1(XImage *image, unsigned int width, unsigned int height, PixelsMap *pmap, | |
748 | /* | |
749 | int (*storeFunc)() | |
750 | */ | |
751 | int (*storeFunc)(Pixel,PixelsMap*,unsigned int*) | |
752 | ) | |
753 | { | |
754 | unsigned int *iptr; | |
755 | int x, y; | |
756 | char *data; | |
757 | Pixel pixel; | |
758 | ||
759 | if (image->byte_order != image->bitmap_bit_order) | |
760 | return (GetImagePixels(image, width, height, pmap)); | |
761 | else { | |
762 | data = image->data; | |
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))) | |
768 | ? 1 : 0; | |
769 | if ((*storeFunc) (pixel, pmap, iptr)) | |
770 | return (XpmNoMemory); | |
771 | } | |
772 | else | |
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))) | |
776 | ? 1 : 0; | |
777 | if ((*storeFunc) (pixel, pmap, iptr)) | |
778 | return (XpmNoMemory); | |
779 | } | |
780 | } | |
781 | return (XpmSuccess); | |
782 | } | |
783 | ||
784 | #else /* ndef FOR_MSW */ | |
785 | static int | |
786 | MSWGetImagePixels(Display *display, XImage *image, unsigned int width, unsigned int height, PixelsMap *pmap) | |
787 | { | |
788 | unsigned int *iptr; | |
789 | unsigned int x, y; | |
790 | Pixel pixel; | |
791 | ||
792 | iptr = pmap->pixelindex; | |
793 | ||
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); | |
800 | } | |
801 | } | |
802 | return (XpmSuccess); | |
803 | } | |
804 | ||
805 | #endif | |
806 | ||
807 | #ifndef FOR_MSW | |
808 | int | |
809 | XpmCreateXpmImageFromPixmap(Display *display, Pixmap pixmap, Pixmap shapemask, | |
810 | XpmImage *xpmimage, XpmAttributes *attributes) | |
811 | { | |
812 | XImage *ximage = NULL; | |
813 | XImage *shapeimage = NULL; | |
814 | unsigned int width = 0; | |
815 | unsigned int height = 0; | |
816 | int ErrorStatus; | |
817 | ||
818 | /* get geometry */ | |
819 | if (attributes && attributes->valuemask & XpmSize) { | |
820 | width = attributes->width; | |
821 | height = attributes->height; | |
822 | } | |
823 | /* get the ximages */ | |
824 | if (pixmap) | |
825 | xpmCreateImageFromPixmap(display, pixmap, &ximage, &width, &height); | |
826 | if (shapemask) | |
827 | xpmCreateImageFromPixmap(display, shapemask, &shapeimage, | |
828 | &width, &height); | |
829 | ||
830 | /* create the related XpmImage */ | |
831 | ErrorStatus = XpmCreateXpmImageFromImage(display, ximage, shapeimage, | |
832 | xpmimage, attributes); | |
833 | ||
834 | /* destroy the ximages */ | |
835 | if (ximage) | |
836 | XDestroyImage(ximage); | |
837 | if (shapeimage) | |
838 | XDestroyImage(shapeimage); | |
839 | ||
840 | return (ErrorStatus); | |
841 | } | |
842 | ||
843 | #endif /* ndef FOR_MSW */ |