1 /* convert.c - convert RImage to Pixmap
3 * Raster graphics library
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * 1. Using Grayscale visual with Dithering crashes wmaker
24 * 2. Ghost dock/appicon is wrong in Pseudocolor, Staticgray, Grayscale
30 #include <X11/Xutil.h>
44 extern Pixmap
R_CreateXImageMappedPixmap(RContext
* context
, RXImage
* ximage
);
49 extern void x86_PseudoColor_32_to_8(unsigned char *image
,
50 unsigned char *ximage
,
51 char *err
, char *nerr
,
53 int dr
, int dg
, int db
,
54 unsigned long *pixels
,
55 int cpc
, int width
, int height
, int bytesPerPixel
, int line_offset
);
60 extern int x86_check_mmx();
62 extern void x86_mmx_TrueColor_32_to_16(unsigned char *image
,
63 unsigned short *ximage
,
64 short *err
, short *nerr
,
65 const unsigned short *rtable
,
66 const unsigned short *gtable
,
67 const unsigned short *btable
,
68 int dr
, int dg
, int db
,
71 unsigned int boffs
, int width
, int height
, int line_offset
);
73 #endif /* ASM_X86_MMX */
75 #define NFREE(n) if (n) free(n)
77 #define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
79 typedef struct RConversionTable
{
80 unsigned short table
[256];
83 struct RConversionTable
*next
;
86 typedef struct RStdConversionTable
{
87 unsigned int table
[256];
92 struct RStdConversionTable
*next
;
93 } RStdConversionTable
;
95 static RConversionTable
*conversionTable
= NULL
;
96 static RStdConversionTable
*stdConversionTable
= NULL
;
98 static unsigned short *computeTable(unsigned short mask
)
100 RConversionTable
*tmp
= conversionTable
;
104 if (tmp
->index
== mask
)
112 tmp
= (RConversionTable
*) malloc(sizeof(RConversionTable
));
116 for (i
= 0; i
< 256; i
++)
117 tmp
->table
[i
] = (i
* mask
+ 0x7f) / 0xff;
120 tmp
->next
= conversionTable
;
121 conversionTable
= tmp
;
125 static unsigned int *computeStdTable(unsigned int mult
, unsigned int max
)
127 RStdConversionTable
*tmp
= stdConversionTable
;
131 if (tmp
->mult
== mult
&& tmp
->max
== max
)
139 tmp
= (RStdConversionTable
*) malloc(sizeof(RStdConversionTable
));
143 for (i
= 0; i
< 256; i
++) {
144 tmp
->table
[i
] = (i
* max
) / 0xff * mult
;
149 tmp
->next
= stdConversionTable
;
150 stdConversionTable
= tmp
;
155 /***************************************************************************/
158 convertTrueColor_generic(RXImage
* ximg
, RImage
* image
,
159 signed char *err
, signed char *nerr
,
160 const unsigned short *rtable
,
161 const unsigned short *gtable
,
162 const unsigned short *btable
,
163 const int dr
, const int dg
, const int db
,
164 const unsigned short roffs
, const unsigned short goffs
, const unsigned short boffs
)
170 unsigned char *ptr
= image
->data
;
171 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
173 /* convert and dither the image to XImage */
174 for (y
= 0; y
< image
->height
; y
++) {
178 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
181 pixel
= *ptr
+ err
[x
];
184 else if (pixel
> 0xff)
188 rer
= pixel
- r
* dr
;
191 pixel
= *(ptr
+ 1) + err
[x
+ 1];
194 else if (pixel
> 0xff)
198 ger
= pixel
- g
* dg
;
201 pixel
= *(ptr
+ 2) + err
[x
+ 2];
204 else if (pixel
> 0xff)
208 ber
= pixel
- b
* db
;
210 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
211 XPutPixel(ximg
->image
, x
, y
, pixel
);
213 /* distribute error */
219 err
[x
+ 1 + 3 * 1] += g
;
220 err
[x
+ 2 + 3 * 1] += b
;
226 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
227 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
228 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
230 /* skip to next line */
236 /* redither the 1st line to distribute error better */
242 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
245 pixel
= *ptr
+ err
[x
];
248 else if (pixel
> 0xff)
252 rer
= pixel
- r
* dr
;
255 pixel
= *(ptr
+ 1) + err
[x
+ 1];
258 else if (pixel
> 0xff)
262 ger
= pixel
- g
* dg
;
265 pixel
= *(ptr
+ 2) + err
[x
+ 2];
268 else if (pixel
> 0xff)
272 ber
= pixel
- b
* db
;
274 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
275 XPutPixel(ximg
->image
, x
, y
, pixel
);
277 /* distribute error */
283 err
[x
+ 1 + 3 * 1] += g
;
284 err
[x
+ 2 + 3 * 1] += b
;
290 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
291 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
292 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
296 static RXImage
*image2TrueColor(RContext
* ctx
, RImage
* image
)
299 unsigned short rmask
, gmask
, bmask
;
300 unsigned short roffs
, goffs
, boffs
;
301 unsigned short *rtable
, *gtable
, *btable
;
302 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
304 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
309 roffs
= ctx
->red_offset
;
310 goffs
= ctx
->green_offset
;
311 boffs
= ctx
->blue_offset
;
313 rmask
= ctx
->visual
->red_mask
>> roffs
;
314 gmask
= ctx
->visual
->green_mask
>> goffs
;
315 bmask
= ctx
->visual
->blue_mask
>> boffs
;
317 rtable
= computeTable(rmask
);
318 gtable
= computeTable(gmask
);
319 btable
= computeTable(bmask
);
321 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
322 RErrorCode
= RERR_NOMEMORY
;
323 RDestroyXImage(ctx
, ximg
);
331 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
335 unsigned char *ptr
= image
->data
;
339 puts("true color match");
341 if (rmask
== 0xff && gmask
== 0xff && bmask
== 0xff) {
342 for (y
= 0; y
< image
->height
; y
++) {
343 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
345 pixel
= (*(ptr
) << roffs
) | (*(ptr
+ 1) << goffs
) | (*(ptr
+ 2) << boffs
);
346 XPutPixel(ximg
->image
, x
, y
, pixel
);
350 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
351 for (x
= 0; x
< image
->width
; x
++, ofs
+= channels
- 3) {
353 r
= rtable
[ptr
[ofs
++]];
354 g
= gtable
[ptr
[ofs
++]];
355 b
= btable
[ptr
[ofs
++]];
356 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
357 XPutPixel(ximg
->image
, x
, y
, pixel
);
363 const int dr
= 0xff / rmask
;
364 const int dg
= 0xff / gmask
;
365 const int db
= 0xff / bmask
;
368 puts("true color dither");
372 if (ctx
->depth
== 16 && HAS_ALPHA(image
) && x86_check_mmx()) {
376 err
= malloc(8 * (image
->width
+ 3));
377 nerr
= malloc(8 * (image
->width
+ 3));
381 RErrorCode
= RERR_NOMEMORY
;
382 RDestroyXImage(ctx
, ximg
);
385 memset(err
, 0, 8 * (image
->width
+ 3));
386 memset(nerr
, 0, 8 * (image
->width
+ 3));
388 x86_mmx_TrueColor_32_to_16(image
->data
,
389 (unsigned short *)ximg
->image
->data
,
391 rtable
, gtable
, btable
,
394 image
->width
, image
->height
,
395 ximg
->image
->bytes_per_line
- 2 * image
->width
);
400 #endif /* ASM_X86_MMX */
404 int ch
= (HAS_ALPHA(image
) ? 4 : 3);
406 err
= malloc(ch
* (image
->width
+ 2));
407 nerr
= malloc(ch
* (image
->width
+ 2));
411 RErrorCode
= RERR_NOMEMORY
;
412 RDestroyXImage(ctx
, ximg
);
416 memset(err
, 0, ch
* (image
->width
+ 2));
417 memset(nerr
, 0, ch
* (image
->width
+ 2));
419 convertTrueColor_generic(ximg
, image
, err
, nerr
,
420 rtable
, gtable
, btable
, dr
, dg
, db
, roffs
, goffs
, boffs
);
434 /***************************************************************************/
437 convertPseudoColor_to_8(RXImage
* ximg
, RImage
* image
,
438 signed char *err
, signed char *nerr
,
439 const unsigned short *rtable
,
440 const unsigned short *gtable
,
441 const unsigned short *btable
,
442 const int dr
, const int dg
, const int db
, unsigned long *pixels
, int cpc
)
448 unsigned char *ptr
= image
->data
;
449 unsigned char *optr
= (unsigned char *)ximg
->image
->data
;
450 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
451 int cpcpc
= cpc
* cpc
;
453 /* convert and dither the image to XImage */
454 for (y
= 0; y
< image
->height
; y
++) {
458 for (x
= 0; x
< image
->width
* 3; x
+= 3, ptr
+= channels
) {
461 pixel
= *ptr
+ err
[x
];
464 else if (pixel
> 0xff)
468 rer
= pixel
- r
* dr
;
471 pixel
= *(ptr
+ 1) + err
[x
+ 1];
474 else if (pixel
> 0xff)
478 ger
= pixel
- g
* dg
;
481 pixel
= *(ptr
+ 2) + err
[x
+ 2];
484 else if (pixel
> 0xff)
488 ber
= pixel
- b
* db
;
490 *optr
++ = pixels
[r
* cpcpc
+ g
* cpc
+ b
];
492 /* distribute error */
499 err
[x
+ 1 + 3 * 1] += g
;
500 err
[x
+ 2 + 3 * 1] += b
;
506 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
507 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
508 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
510 /* skip to next line */
515 optr
+= ximg
->image
->bytes_per_line
- image
->width
;
519 static RXImage
*image2PseudoColor(RContext
* ctx
, RImage
* image
)
522 register int x
, y
, r
, g
, b
;
525 const int cpc
= ctx
->attribs
->colors_per_channel
;
526 const unsigned short rmask
= cpc
- 1; /* different sizes could be used */
527 const unsigned short gmask
= rmask
; /* for r,g,b */
528 const unsigned short bmask
= rmask
;
529 unsigned short *rtable
, *gtable
, *btable
;
530 const int cpccpc
= cpc
* cpc
;
531 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
533 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
540 /* Tables are same at the moment because rmask==gmask==bmask. */
541 rtable
= computeTable(rmask
);
542 gtable
= computeTable(gmask
);
543 btable
= computeTable(bmask
);
545 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
546 RErrorCode
= RERR_NOMEMORY
;
547 RDestroyXImage(ctx
, ximg
);
551 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
554 printf("pseudo color match with %d colors per channel\n", cpc
);
556 for (y
= 0; y
< image
->height
; y
++) {
557 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
- 3) {
562 pixel
= r
* cpccpc
+ g
* cpc
+ b
;
563 /*data[ofs] = ctx->colors[pixel].pixel; */
564 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[pixel
].pixel
);
571 const int dr
= 0xff / rmask
;
572 const int dg
= 0xff / gmask
;
573 const int db
= 0xff / bmask
;
576 printf("pseudo color dithering with %d colors per channel\n", cpc
);
578 err
= malloc(4 * (image
->width
+ 3));
579 nerr
= malloc(4 * (image
->width
+ 3));
583 RErrorCode
= RERR_NOMEMORY
;
584 RDestroyXImage(ctx
, ximg
);
587 memset(err
, 0, 4 * (image
->width
+ 3));
588 memset(nerr
, 0, 4 * (image
->width
+ 3));
591 convertPseudoColor_to_8(ximg
, image
, err
+ 4, nerr
+ 4,
592 rtable
, gtable
, btable
, dr
, dg
, db
, ctx
->pixels
, cpc
);
602 * For standard colormap
604 static RXImage
*image2StandardPseudoColor(RContext
* ctx
, RImage
* image
)
607 register int x
, y
, r
, g
, b
;
611 unsigned int *rtable
, *gtable
, *btable
;
612 unsigned int base_pixel
= ctx
->std_rgb_map
->base_pixel
;
613 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
615 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
622 data
= (unsigned char *)ximg
->image
->data
;
624 rtable
= computeStdTable(ctx
->std_rgb_map
->red_mult
, ctx
->std_rgb_map
->red_max
);
626 gtable
= computeStdTable(ctx
->std_rgb_map
->green_mult
, ctx
->std_rgb_map
->green_max
);
628 btable
= computeStdTable(ctx
->std_rgb_map
->blue_mult
, ctx
->std_rgb_map
->blue_max
);
630 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
631 RErrorCode
= RERR_NOMEMORY
;
632 RDestroyXImage(ctx
, ximg
);
636 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
637 for (y
= 0; y
< image
->height
; y
++) {
638 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
640 pixel
= (rtable
[*ptr
] + gtable
[*(ptr
+ 1)]
641 + btable
[*(ptr
+ 2)] + base_pixel
) & 0xffffffff;
643 XPutPixel(ximg
->image
, x
, y
, pixel
);
648 signed short *err
, *nerr
;
654 printf("pseudo color dithering with %d colors per channel\n", ctx
->attribs
->colors_per_channel
);
656 err
= (short *)malloc(3 * (image
->width
+ 2) * sizeof(short));
657 nerr
= (short *)malloc(3 * (image
->width
+ 2) * sizeof(short));
661 RErrorCode
= RERR_NOMEMORY
;
662 RDestroyXImage(ctx
, ximg
);
665 for (x
= 0, x1
= 0; x
< image
->width
* 3; x1
+= channels
- 3) {
666 err
[x
++] = ptr
[x1
++];
667 err
[x
++] = ptr
[x1
++];
668 err
[x
++] = ptr
[x1
++];
670 err
[x
] = err
[x
+ 1] = err
[x
+ 2] = 0;
671 /* convert and dither the image to XImage */
672 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
673 if (y
< image
->height
- 1) {
675 for (x
= 0, x1
= (y
+ 1) * image
->width
* channels
;
676 x
< image
->width
* 3; x1
+= channels
- 3) {
677 nerr
[x
++] = ptr
[x1
++];
678 nerr
[x
++] = ptr
[x1
++];
679 nerr
[x
++] = ptr
[x1
++];
683 nerr
[x
++] = ptr
[x1
++];
684 nerr
[x
++] = ptr
[x1
++];
685 nerr
[x
++] = ptr
[x1
++];
687 for (x
= 0; x
< image
->width
* 3; x
+= 3, ofs
++) {
693 if (err
[x
+ 1] > 0xff)
695 else if (err
[x
+ 1] < 0)
697 if (err
[x
+ 2] > 0xff)
699 else if (err
[x
+ 2] < 0)
703 g
= gtable
[err
[x
+ 1]];
704 b
= btable
[err
[x
+ 2]];
708 data
[ofs
] = base_pixel
+ pixel
;
711 rer
= err
[x
] - (ctx
->colors
[pixel
].red
>> 8);
712 ger
= err
[x
+ 1] - (ctx
->colors
[pixel
].green
>> 8);
713 ber
= err
[x
+ 2] - (ctx
->colors
[pixel
].blue
>> 8);
715 /* distribute error */
716 err
[x
+ 3 * 1] += (rer
* 7) / 16;
717 err
[x
+ 1 + 3 * 1] += (ger
* 7) / 16;
718 err
[x
+ 2 + 3 * 1] += (ber
* 7) / 16;
720 nerr
[x
] += (rer
* 5) / 16;
721 nerr
[x
+ 1] += (ger
* 5) / 16;
722 nerr
[x
+ 2] += (ber
* 5) / 16;
725 nerr
[x
- 3 * 1] += (rer
* 3) / 16;
726 nerr
[x
- 3 * 1 + 1] += (ger
* 3) / 16;
727 nerr
[x
- 3 * 1 + 2] += (ber
* 3) / 16;
730 nerr
[x
+ 3 * 1] += rer
/ 16;
731 nerr
[x
+ 1 + 3 * 1] += ger
/ 16;
732 nerr
[x
+ 2 + 3 * 1] += ber
/ 16;
734 /* skip to next line */
739 ofs
+= ximg
->image
->bytes_per_line
- image
->width
;
744 ximg
->image
->data
= (char *)data
;
749 static RXImage
*image2GrayScale(RContext
* ctx
, RImage
* image
)
752 register int x
, y
, g
;
754 const int cpc
= ctx
->attribs
->colors_per_channel
;
755 unsigned short gmask
;
756 unsigned short *table
;
758 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
760 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
767 data
= (unsigned char *)ximg
->image
->data
;
769 if (ctx
->vclass
== StaticGray
)
770 gmask
= (1 << ctx
->depth
) - 1; /* use all grays */
772 gmask
= cpc
* cpc
* cpc
- 1;
774 table
= computeTable(gmask
);
777 RErrorCode
= RERR_NOMEMORY
;
778 RDestroyXImage(ctx
, ximg
);
782 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
785 printf("grayscale match with %d colors per channel\n", cpc
);
787 for (y
= 0; y
< image
->height
; y
++) {
788 for (x
= 0; x
< image
->width
; x
++) {
790 g
= table
[(*ptr
* 30 + *(ptr
+ 1) * 59 + *(ptr
+ 2) * 11) / 100];
792 /*data[ofs] = ctx->colors[g].pixel; */
793 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
802 const int dg
= 0xff / gmask
;
805 printf("grayscale dither with %d colors per channel\n", cpc
);
807 gerr
= (short *)malloc((image
->width
+ 2) * sizeof(short));
808 ngerr
= (short *)malloc((image
->width
+ 2) * sizeof(short));
809 if (!gerr
|| !ngerr
) {
812 RErrorCode
= RERR_NOMEMORY
;
813 RDestroyXImage(ctx
, ximg
);
816 for (x
= 0, y
= 0; x
< image
->width
; x
++, y
+= channels
) {
817 gerr
[x
] = (ptr
[y
] * 30 + ptr
[y
+ 1] * 59 + ptr
[y
+ 2] * 11) / 100;
820 /* convert and dither the image to XImage */
821 for (y
= 0; y
< image
->height
; y
++) {
822 if (y
< image
->height
- 1) {
824 for (x
= 0, x1
= (y
+ 1) * image
->width
* channels
; x
< image
->width
;
825 x
++, x1
+= channels
) {
826 ngerr
[x
] = (ptr
[x1
] * 30 + ptr
[x1
+ 1] * 59 + ptr
[x1
+ 2] * 11) / 100;
830 ngerr
[x
] = (ptr
[x1
] * 30 + ptr
[x1
+ 1] * 59 + ptr
[x1
+ 2] * 11) / 100;
832 for (x
= 0; x
< image
->width
; x
++) {
836 else if (gerr
[x
] < 0)
841 /*data[ofs] = ctx->colors[g].pixel; */
842 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
844 ger
= gerr
[x
] - g
* dg
;
846 /* distribute error */
853 ngerr
[x
+ 1] += ger
- 2 * g
;
855 /* skip to next line */
863 ximg
->image
->data
= (char *)data
;
868 static RXImage
*image2Bitmap(RContext
* ctx
, RImage
* image
, int threshold
)
871 unsigned char *alpha
;
874 ximg
= RCreateXImage(ctx
, 1, image
->width
, image
->height
);
878 alpha
= image
->data
+ 3;
880 for (y
= 0; y
< image
->height
; y
++) {
881 for (x
= 0; x
< image
->width
; x
++) {
882 XPutPixel(ximg
->image
, x
, y
, (*alpha
<= threshold
? 0 : 1));
890 int RConvertImage(RContext
* context
, RImage
* image
, Pixmap
* pixmap
)
892 RXImage
*ximg
= NULL
;
897 assert(context
!= NULL
);
898 assert(image
!= NULL
);
899 assert(pixmap
!= NULL
);
901 switch (context
->vclass
) {
906 ximg
= image2TrueColor(context
, image
);
917 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
)
918 ximg
= image2StandardPseudoColor(context
, image
);
920 ximg
= image2PseudoColor(context
, image
);
928 ximg
= image2GrayScale(context
, image
);
936 *pixmap
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
, image
->height
, context
->depth
);
939 if (context
->flags
.use_shared_pixmap
&& ximg
->is_shared
)
940 tmp
= R_CreateXImageMappedPixmap(context
, ximg
);
945 * We have to copy the shm Pixmap into a normal Pixmap because
946 * otherwise, we would have to control when Pixmaps are freed so
947 * that we can detach their shm segments. This is a problem if the
948 * program crash, leaving stale shared memory segments in the
949 * system (lots of them). But with some work, we can optimize
950 * things and remove this XCopyArea. This will require
951 * explicitly freeing all pixmaps when exiting or restarting
954 XCopyArea(context
->dpy
, tmp
, *pixmap
, context
->copy_gc
, 0, 0, image
->width
, image
->height
, 0, 0);
955 XFreePixmap(context
->dpy
, tmp
);
957 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
960 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
963 RDestroyXImage(context
, ximg
);
968 /* make the gc permanent (create with context creation).
969 * GC creation is very expensive. altering its properties is not. -Dan
971 int RConvertImageMask(RContext
* context
, RImage
* image
, Pixmap
* pixmap
, Pixmap
* mask
, int threshold
)
975 RXImage
*ximg
= NULL
;
977 assert(context
!= NULL
);
978 assert(image
!= NULL
);
979 assert(pixmap
!= NULL
);
980 assert(mask
!= NULL
);
982 if (!RConvertImage(context
, image
, pixmap
))
985 if (image
->format
== RRGBFormat
) {
990 ximg
= image2Bitmap(context
, image
, threshold
);
995 *mask
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
, image
->height
, 1);
996 gcv
.foreground
= context
->black
;
997 gcv
.background
= context
->white
;
998 gcv
.graphics_exposures
= False
;
999 gc
= XCreateGC(context
->dpy
, *mask
, GCForeground
| GCBackground
| GCGraphicsExposures
, &gcv
);
1000 RPutXImage(context
, *mask
, gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
1001 RDestroyXImage(context
, ximg
);
1002 XFreeGC(context
->dpy
, gc
);
1007 Bool
RGetClosestXColor(RContext
* context
, RColor
* color
, XColor
* retColor
)
1009 if (context
->vclass
== TrueColor
) {
1010 unsigned short rmask
, gmask
, bmask
;
1011 unsigned short roffs
, goffs
, boffs
;
1012 unsigned short *rtable
, *gtable
, *btable
;
1014 roffs
= context
->red_offset
;
1015 goffs
= context
->green_offset
;
1016 boffs
= context
->blue_offset
;
1018 rmask
= context
->visual
->red_mask
>> roffs
;
1019 gmask
= context
->visual
->green_mask
>> goffs
;
1020 bmask
= context
->visual
->blue_mask
>> boffs
;
1022 rtable
= computeTable(rmask
);
1023 gtable
= computeTable(gmask
);
1024 btable
= computeTable(bmask
);
1026 retColor
->pixel
= (rtable
[color
->red
] << roffs
) |
1027 (gtable
[color
->green
] << goffs
) | (btable
[color
->blue
] << boffs
);
1029 retColor
->red
= color
->red
<< 8;
1030 retColor
->green
= color
->green
<< 8;
1031 retColor
->blue
= color
->blue
<< 8;
1032 retColor
->flags
= DoRed
| DoGreen
| DoBlue
;
1034 } else if (context
->vclass
== PseudoColor
|| context
->vclass
== StaticColor
) {
1036 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
) {
1037 unsigned int *rtable
, *gtable
, *btable
;
1039 rtable
= computeStdTable(context
->std_rgb_map
->red_mult
, context
->std_rgb_map
->red_max
);
1041 gtable
= computeStdTable(context
->std_rgb_map
->green_mult
,
1042 context
->std_rgb_map
->green_max
);
1044 btable
= computeStdTable(context
->std_rgb_map
->blue_mult
, context
->std_rgb_map
->blue_max
);
1046 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
1047 RErrorCode
= RERR_NOMEMORY
;
1051 retColor
->pixel
= (rtable
[color
->red
]
1052 + gtable
[color
->green
]
1053 + btable
[color
->blue
]
1054 + context
->std_rgb_map
->base_pixel
) & 0xffffffff;
1055 retColor
->red
= color
->red
<< 8;
1056 retColor
->green
= color
->green
<< 8;
1057 retColor
->blue
= color
->blue
<< 8;
1058 retColor
->flags
= DoRed
| DoGreen
| DoBlue
;
1061 const int cpc
= context
->attribs
->colors_per_channel
;
1062 const unsigned short rmask
= cpc
- 1; /* different sizes could be used */
1063 const unsigned short gmask
= rmask
; /* for r,g,b */
1064 const unsigned short bmask
= rmask
;
1065 unsigned short *rtable
, *gtable
, *btable
;
1066 const int cpccpc
= cpc
* cpc
;
1069 rtable
= computeTable(rmask
);
1070 gtable
= computeTable(gmask
);
1071 btable
= computeTable(bmask
);
1073 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
1074 RErrorCode
= RERR_NOMEMORY
;
1077 index
= rtable
[color
->red
] * cpccpc
+ gtable
[color
->green
] * cpc
+ btable
[color
->blue
];
1078 *retColor
= context
->colors
[index
];
1081 } else if (context
->vclass
== GrayScale
|| context
->vclass
== StaticGray
) {
1083 const int cpc
= context
->attribs
->colors_per_channel
;
1084 unsigned short gmask
;
1085 unsigned short *table
;
1088 if (context
->vclass
== StaticGray
)
1089 gmask
= (1 << context
->depth
) - 1; /* use all grays */
1091 gmask
= cpc
* cpc
* cpc
- 1;
1093 table
= computeTable(gmask
);
1097 index
= table
[(color
->red
* 30 + color
->green
* 59 + color
->blue
* 11) / 100];
1099 *retColor
= context
->colors
[index
];
1101 RErrorCode
= RERR_INTERNAL
;