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., 51 Franklin St, Fifth Floor, Boston,
24 * 1. Using Grayscale visual with Dithering crashes wmaker
25 * 2. Ghost dock/appicon is wrong in Pseudocolor, Staticgray, Grayscale
30 #include <X11/Xutil.h>
41 extern Pixmap
R_CreateXImageMappedPixmap(RContext
* context
, RXImage
* ximage
);
44 #define NFREE(n) if (n) free(n)
46 #define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
48 typedef struct RConversionTable
{
49 unsigned short table
[256];
52 struct RConversionTable
*next
;
55 typedef struct RStdConversionTable
{
56 unsigned int table
[256];
61 struct RStdConversionTable
*next
;
62 } RStdConversionTable
;
64 static RConversionTable
*conversionTable
= NULL
;
65 static RStdConversionTable
*stdConversionTable
= NULL
;
67 static void release_conversion_table(void)
69 RConversionTable
*tmp
= conversionTable
;
72 RConversionTable
*tmp_to_delete
= tmp
;
77 conversionTable
= NULL
;
80 static void release_std_conversion_table(void)
82 RStdConversionTable
*tmp
= stdConversionTable
;
85 RStdConversionTable
*tmp_to_delete
= tmp
;
90 stdConversionTable
= NULL
;
93 void r_destroy_conversion_tables(void)
95 release_conversion_table();
96 release_std_conversion_table();
99 static unsigned short *computeTable(unsigned short mask
)
101 RConversionTable
*tmp
= conversionTable
;
105 if (tmp
->index
== mask
)
113 tmp
= (RConversionTable
*) malloc(sizeof(RConversionTable
));
117 for (i
= 0; i
< 256; i
++)
118 tmp
->table
[i
] = (i
* mask
+ 0x7f) / 0xff;
121 tmp
->next
= conversionTable
;
122 conversionTable
= tmp
;
126 static unsigned int *computeStdTable(unsigned int mult
, unsigned int max
)
128 RStdConversionTable
*tmp
= stdConversionTable
;
132 if (tmp
->mult
== mult
&& tmp
->max
== max
)
140 tmp
= (RStdConversionTable
*) malloc(sizeof(RStdConversionTable
));
144 for (i
= 0; i
< 256; i
++) {
145 tmp
->table
[i
] = (i
* max
) / 0xff * mult
;
150 tmp
->next
= stdConversionTable
;
151 stdConversionTable
= tmp
;
156 /***************************************************************************/
159 convertTrueColor_generic(RXImage
* ximg
, RImage
* image
,
160 signed char *err
, signed char *nerr
,
161 const unsigned short *rtable
,
162 const unsigned short *gtable
,
163 const unsigned short *btable
,
164 const int dr
, const int dg
, const int db
,
165 const unsigned short roffs
, const unsigned short goffs
, const unsigned short boffs
)
171 unsigned char *ptr
= image
->data
;
172 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
174 /* convert and dither the image to XImage */
175 for (y
= 0; y
< image
->height
; y
++) {
179 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
182 pixel
= *ptr
+ err
[x
];
185 else if (pixel
> 0xff)
189 rer
= pixel
- r
* dr
;
192 pixel
= *(ptr
+ 1) + err
[x
+ 1];
195 else if (pixel
> 0xff)
199 ger
= pixel
- g
* dg
;
202 pixel
= *(ptr
+ 2) + err
[x
+ 2];
205 else if (pixel
> 0xff)
209 ber
= pixel
- b
* db
;
211 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
212 XPutPixel(ximg
->image
, x
, y
, pixel
);
214 /* distribute error */
220 err
[x
+ 1 + 3 * 1] += g
;
221 err
[x
+ 2 + 3 * 1] += b
;
227 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
228 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
229 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
231 /* skip to next line */
237 /* redither the 1st line to distribute error better */
243 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
246 pixel
= *ptr
+ err
[x
];
249 else if (pixel
> 0xff)
253 rer
= pixel
- r
* dr
;
256 pixel
= *(ptr
+ 1) + err
[x
+ 1];
259 else if (pixel
> 0xff)
263 ger
= pixel
- g
* dg
;
266 pixel
= *(ptr
+ 2) + err
[x
+ 2];
269 else if (pixel
> 0xff)
273 ber
= pixel
- b
* db
;
275 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
276 XPutPixel(ximg
->image
, x
, y
, pixel
);
278 /* distribute error */
284 err
[x
+ 1 + 3 * 1] += g
;
285 err
[x
+ 2 + 3 * 1] += b
;
291 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
292 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
293 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
297 static RXImage
*image2TrueColor(RContext
* ctx
, RImage
* image
)
300 unsigned short rmask
, gmask
, bmask
;
301 unsigned short roffs
, goffs
, boffs
;
302 unsigned short *rtable
, *gtable
, *btable
;
303 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
305 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
310 roffs
= ctx
->red_offset
;
311 goffs
= ctx
->green_offset
;
312 boffs
= ctx
->blue_offset
;
314 rmask
= ctx
->visual
->red_mask
>> roffs
;
315 gmask
= ctx
->visual
->green_mask
>> goffs
;
316 bmask
= ctx
->visual
->blue_mask
>> boffs
;
318 rtable
= computeTable(rmask
);
319 gtable
= computeTable(gmask
);
320 btable
= computeTable(bmask
);
322 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
323 RErrorCode
= RERR_NOMEMORY
;
324 RDestroyXImage(ctx
, ximg
);
328 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
332 unsigned char *ptr
= image
->data
;
336 fputs("true color match\n", stderr
);
338 if (rmask
== 0xff && gmask
== 0xff && bmask
== 0xff) {
339 for (y
= 0; y
< image
->height
; y
++) {
340 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
342 pixel
= (*(ptr
) << roffs
) | (*(ptr
+ 1) << goffs
) | (*(ptr
+ 2) << boffs
);
343 XPutPixel(ximg
->image
, x
, y
, pixel
);
347 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
348 for (x
= 0; x
< image
->width
; x
++, ofs
+= channels
- 3) {
350 r
= rtable
[ptr
[ofs
++]];
351 g
= gtable
[ptr
[ofs
++]];
352 b
= btable
[ptr
[ofs
++]];
353 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
354 XPutPixel(ximg
->image
, x
, y
, pixel
);
360 const int dr
= 0xff / rmask
;
361 const int dg
= 0xff / gmask
;
362 const int db
= 0xff / bmask
;
365 fputs("true color dither\n", stderr
);
371 int ch
= (HAS_ALPHA(image
) ? 4 : 3);
373 err
= malloc(ch
* (image
->width
+ 2));
374 nerr
= malloc(ch
* (image
->width
+ 2));
378 RErrorCode
= RERR_NOMEMORY
;
379 RDestroyXImage(ctx
, ximg
);
383 memset(err
, 0, ch
* (image
->width
+ 2));
384 memset(nerr
, 0, ch
* (image
->width
+ 2));
386 convertTrueColor_generic(ximg
, image
, err
, nerr
,
387 rtable
, gtable
, btable
, dr
, dg
, db
, roffs
, goffs
, boffs
);
397 /***************************************************************************/
400 convertPseudoColor_to_8(RXImage
* ximg
, RImage
* image
,
401 signed char *err
, signed char *nerr
,
402 const unsigned short *rtable
,
403 const unsigned short *gtable
,
404 const unsigned short *btable
,
405 const int dr
, const int dg
, const int db
, unsigned long *pixels
, int cpc
)
411 unsigned char *ptr
= image
->data
;
412 unsigned char *optr
= (unsigned char *)ximg
->image
->data
;
413 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
414 int cpcpc
= cpc
* cpc
;
416 /* convert and dither the image to XImage */
417 for (y
= 0; y
< image
->height
; y
++) {
421 for (x
= 0; x
< image
->width
* 3; x
+= 3, ptr
+= channels
) {
424 pixel
= *ptr
+ err
[x
];
427 else if (pixel
> 0xff)
431 rer
= pixel
- r
* dr
;
434 pixel
= *(ptr
+ 1) + err
[x
+ 1];
437 else if (pixel
> 0xff)
441 ger
= pixel
- g
* dg
;
444 pixel
= *(ptr
+ 2) + err
[x
+ 2];
447 else if (pixel
> 0xff)
451 ber
= pixel
- b
* db
;
453 *optr
++ = pixels
[r
* cpcpc
+ g
* cpc
+ b
];
455 /* distribute error */
462 err
[x
+ 1 + 3 * 1] += g
;
463 err
[x
+ 2 + 3 * 1] += b
;
469 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
470 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
471 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
473 /* skip to next line */
478 optr
+= ximg
->image
->bytes_per_line
- image
->width
;
482 static RXImage
*image2PseudoColor(RContext
* ctx
, RImage
* image
)
485 register int x
, y
, r
, g
, b
;
488 const int cpc
= ctx
->attribs
->colors_per_channel
;
489 const unsigned short rmask
= cpc
- 1; /* different sizes could be used */
490 const unsigned short gmask
= rmask
; /* for r,g,b */
491 const unsigned short bmask
= rmask
;
492 unsigned short *rtable
, *gtable
, *btable
;
493 const int cpccpc
= cpc
* cpc
;
494 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
496 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
503 /* Tables are same at the moment because rmask==gmask==bmask. */
504 rtable
= computeTable(rmask
);
505 gtable
= computeTable(gmask
);
506 btable
= computeTable(bmask
);
508 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
509 RErrorCode
= RERR_NOMEMORY
;
510 RDestroyXImage(ctx
, ximg
);
514 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
517 fprintf(stderr
, "pseudo color match with %d colors per channel\n", cpc
);
519 for (y
= 0; y
< image
->height
; y
++) {
520 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
- 3) {
525 pixel
= r
* cpccpc
+ g
* cpc
+ b
;
526 /*data[ofs] = ctx->colors[pixel].pixel; */
527 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[pixel
].pixel
);
534 const int dr
= 0xff / rmask
;
535 const int dg
= 0xff / gmask
;
536 const int db
= 0xff / bmask
;
539 fprintf(stderr
, "pseudo color dithering with %d colors per channel\n", cpc
);
541 err
= malloc(4 * (image
->width
+ 3));
542 nerr
= malloc(4 * (image
->width
+ 3));
546 RErrorCode
= RERR_NOMEMORY
;
547 RDestroyXImage(ctx
, ximg
);
550 memset(err
, 0, 4 * (image
->width
+ 3));
551 memset(nerr
, 0, 4 * (image
->width
+ 3));
553 convertPseudoColor_to_8(ximg
, image
, err
+ 4, nerr
+ 4,
554 rtable
, gtable
, btable
, dr
, dg
, db
, ctx
->pixels
, cpc
);
564 * For standard colormap
566 static RXImage
*image2StandardPseudoColor(RContext
* ctx
, RImage
* image
)
569 register int x
, y
, r
, g
, b
;
573 unsigned int *rtable
, *gtable
, *btable
;
574 unsigned int base_pixel
= ctx
->std_rgb_map
->base_pixel
;
575 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
577 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
584 data
= (unsigned char *)ximg
->image
->data
;
586 rtable
= computeStdTable(ctx
->std_rgb_map
->red_mult
, ctx
->std_rgb_map
->red_max
);
588 gtable
= computeStdTable(ctx
->std_rgb_map
->green_mult
, ctx
->std_rgb_map
->green_max
);
590 btable
= computeStdTable(ctx
->std_rgb_map
->blue_mult
, ctx
->std_rgb_map
->blue_max
);
592 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
593 RErrorCode
= RERR_NOMEMORY
;
594 RDestroyXImage(ctx
, ximg
);
598 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
599 for (y
= 0; y
< image
->height
; y
++) {
600 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
602 pixel
= (rtable
[*ptr
] + gtable
[*(ptr
+ 1)]
603 + btable
[*(ptr
+ 2)] + base_pixel
) & 0xffffffff;
605 XPutPixel(ximg
->image
, x
, y
, pixel
);
610 signed short *err
, *nerr
;
616 fprintf(stderr
, "pseudo color dithering with %d colors per channel\n",
617 ctx
->attribs
->colors_per_channel
);
619 err
= (short *)malloc(3 * (image
->width
+ 2) * sizeof(short));
620 nerr
= (short *)malloc(3 * (image
->width
+ 2) * sizeof(short));
624 RErrorCode
= RERR_NOMEMORY
;
625 RDestroyXImage(ctx
, ximg
);
628 for (x
= 0, x1
= 0; x
< image
->width
* 3; x1
+= channels
- 3) {
629 err
[x
++] = ptr
[x1
++];
630 err
[x
++] = ptr
[x1
++];
631 err
[x
++] = ptr
[x1
++];
633 err
[x
] = err
[x
+ 1] = err
[x
+ 2] = 0;
634 /* convert and dither the image to XImage */
635 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
636 if (y
< image
->height
- 1) {
638 for (x
= 0, x1
= (y
+ 1) * image
->width
* channels
;
639 x
< image
->width
* 3; x1
+= channels
- 3) {
640 nerr
[x
++] = ptr
[x1
++];
641 nerr
[x
++] = ptr
[x1
++];
642 nerr
[x
++] = ptr
[x1
++];
646 nerr
[x
++] = ptr
[x1
++];
647 nerr
[x
++] = ptr
[x1
++];
648 nerr
[x
++] = ptr
[x1
++];
650 for (x
= 0; x
< image
->width
* 3; x
+= 3, ofs
++) {
656 if (err
[x
+ 1] > 0xff)
658 else if (err
[x
+ 1] < 0)
660 if (err
[x
+ 2] > 0xff)
662 else if (err
[x
+ 2] < 0)
666 g
= gtable
[err
[x
+ 1]];
667 b
= btable
[err
[x
+ 2]];
671 data
[ofs
] = base_pixel
+ pixel
;
674 rer
= err
[x
] - (ctx
->colors
[pixel
].red
>> 8);
675 ger
= err
[x
+ 1] - (ctx
->colors
[pixel
].green
>> 8);
676 ber
= err
[x
+ 2] - (ctx
->colors
[pixel
].blue
>> 8);
678 /* distribute error */
679 err
[x
+ 3 * 1] += (rer
* 7) / 16;
680 err
[x
+ 1 + 3 * 1] += (ger
* 7) / 16;
681 err
[x
+ 2 + 3 * 1] += (ber
* 7) / 16;
683 nerr
[x
] += (rer
* 5) / 16;
684 nerr
[x
+ 1] += (ger
* 5) / 16;
685 nerr
[x
+ 2] += (ber
* 5) / 16;
688 nerr
[x
- 3 * 1] += (rer
* 3) / 16;
689 nerr
[x
- 3 * 1 + 1] += (ger
* 3) / 16;
690 nerr
[x
- 3 * 1 + 2] += (ber
* 3) / 16;
693 nerr
[x
+ 3 * 1] += rer
/ 16;
694 nerr
[x
+ 1 + 3 * 1] += ger
/ 16;
695 nerr
[x
+ 2 + 3 * 1] += ber
/ 16;
697 /* skip to next line */
702 ofs
+= ximg
->image
->bytes_per_line
- image
->width
;
707 ximg
->image
->data
= (char *)data
;
712 static RXImage
*image2GrayScale(RContext
* ctx
, RImage
* image
)
715 register int x
, y
, g
;
717 const int cpc
= ctx
->attribs
->colors_per_channel
;
718 unsigned short gmask
;
719 unsigned short *table
;
721 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
723 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
730 data
= (unsigned char *)ximg
->image
->data
;
732 if (ctx
->vclass
== StaticGray
)
733 gmask
= (1 << ctx
->depth
) - 1; /* use all grays */
735 gmask
= cpc
* cpc
* cpc
- 1;
737 table
= computeTable(gmask
);
740 RErrorCode
= RERR_NOMEMORY
;
741 RDestroyXImage(ctx
, ximg
);
745 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
748 fprintf(stderr
, "grayscale match with %d colors per channel\n", cpc
);
750 for (y
= 0; y
< image
->height
; y
++) {
751 for (x
= 0; x
< image
->width
; x
++) {
753 g
= table
[(*ptr
* 30 + *(ptr
+ 1) * 59 + *(ptr
+ 2) * 11) / 100];
755 /*data[ofs] = ctx->colors[g].pixel; */
756 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
765 const int dg
= 0xff / gmask
;
768 fprintf(stderr
, "grayscale dither with %d colors per channel\n", cpc
);
770 gerr
= (short *)malloc((image
->width
+ 2) * sizeof(short));
771 ngerr
= (short *)malloc((image
->width
+ 2) * sizeof(short));
772 if (!gerr
|| !ngerr
) {
775 RErrorCode
= RERR_NOMEMORY
;
776 RDestroyXImage(ctx
, ximg
);
779 for (x
= 0, y
= 0; x
< image
->width
; x
++, y
+= channels
) {
780 gerr
[x
] = (ptr
[y
] * 30 + ptr
[y
+ 1] * 59 + ptr
[y
+ 2] * 11) / 100;
783 /* convert and dither the image to XImage */
784 for (y
= 0; y
< image
->height
; y
++) {
785 if (y
< image
->height
- 1) {
787 for (x
= 0, x1
= (y
+ 1) * image
->width
* channels
; x
< image
->width
;
788 x
++, x1
+= channels
) {
789 ngerr
[x
] = (ptr
[x1
] * 30 + ptr
[x1
+ 1] * 59 + ptr
[x1
+ 2] * 11) / 100;
793 ngerr
[x
] = (ptr
[x1
] * 30 + ptr
[x1
+ 1] * 59 + ptr
[x1
+ 2] * 11) / 100;
795 for (x
= 0; x
< image
->width
; x
++) {
799 else if (gerr
[x
] < 0)
804 /*data[ofs] = ctx->colors[g].pixel; */
805 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
807 ger
= gerr
[x
] - g
* dg
;
809 /* distribute error */
816 ngerr
[x
+ 1] += ger
- 2 * g
;
818 /* skip to next line */
826 ximg
->image
->data
= (char *)data
;
831 static RXImage
*image2Bitmap(RContext
* ctx
, RImage
* image
, int threshold
)
834 unsigned char *alpha
;
837 ximg
= RCreateXImage(ctx
, 1, image
->width
, image
->height
);
841 alpha
= image
->data
+ 3;
843 for (y
= 0; y
< image
->height
; y
++) {
844 for (x
= 0; x
< image
->width
; x
++) {
845 XPutPixel(ximg
->image
, x
, y
, (*alpha
<= threshold
? 0 : 1));
853 int RConvertImage(RContext
* context
, RImage
* image
, Pixmap
* pixmap
)
855 RXImage
*ximg
= NULL
;
860 assert(context
!= NULL
);
861 assert(image
!= NULL
);
862 assert(pixmap
!= NULL
);
864 switch (context
->vclass
) {
866 ximg
= image2TrueColor(context
, image
);
871 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
)
872 ximg
= image2StandardPseudoColor(context
, image
);
874 ximg
= image2PseudoColor(context
, image
);
879 ximg
= image2GrayScale(context
, image
);
887 *pixmap
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
, image
->height
, context
->depth
);
890 if (context
->flags
.use_shared_pixmap
&& ximg
->is_shared
)
891 tmp
= R_CreateXImageMappedPixmap(context
, ximg
);
896 * We have to copy the shm Pixmap into a normal Pixmap because
897 * otherwise, we would have to control when Pixmaps are freed so
898 * that we can detach their shm segments. This is a problem if the
899 * program crash, leaving stale shared memory segments in the
900 * system (lots of them). But with some work, we can optimize
901 * things and remove this XCopyArea. This will require
902 * explicitly freeing all pixmaps when exiting or restarting
905 XCopyArea(context
->dpy
, tmp
, *pixmap
, context
->copy_gc
, 0, 0, image
->width
, image
->height
, 0, 0);
906 XFreePixmap(context
->dpy
, tmp
);
908 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
910 #else /* !USE_XSHM */
911 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
912 #endif /* !USE_XSHM */
914 RDestroyXImage(context
, ximg
);
919 /* make the gc permanent (create with context creation).
920 * GC creation is very expensive. altering its properties is not. -Dan
922 int RConvertImageMask(RContext
* context
, RImage
* image
, Pixmap
* pixmap
, Pixmap
* mask
, int threshold
)
926 RXImage
*ximg
= NULL
;
928 assert(context
!= NULL
);
929 assert(image
!= NULL
);
930 assert(pixmap
!= NULL
);
931 assert(mask
!= NULL
);
933 if (!RConvertImage(context
, image
, pixmap
))
936 if (image
->format
== RRGBFormat
) {
941 ximg
= image2Bitmap(context
, image
, threshold
);
946 *mask
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
, image
->height
, 1);
947 gcv
.foreground
= context
->black
;
948 gcv
.background
= context
->white
;
949 gcv
.graphics_exposures
= False
;
950 gc
= XCreateGC(context
->dpy
, *mask
, GCForeground
| GCBackground
| GCGraphicsExposures
, &gcv
);
951 RPutXImage(context
, *mask
, gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
952 RDestroyXImage(context
, ximg
);
953 XFreeGC(context
->dpy
, gc
);
958 Bool
RGetClosestXColor(RContext
* context
, const RColor
* color
, XColor
* retColor
)
960 if (context
->vclass
== TrueColor
) {
961 unsigned short rmask
, gmask
, bmask
;
962 unsigned short roffs
, goffs
, boffs
;
963 unsigned short *rtable
, *gtable
, *btable
;
965 roffs
= context
->red_offset
;
966 goffs
= context
->green_offset
;
967 boffs
= context
->blue_offset
;
969 rmask
= context
->visual
->red_mask
>> roffs
;
970 gmask
= context
->visual
->green_mask
>> goffs
;
971 bmask
= context
->visual
->blue_mask
>> boffs
;
973 rtable
= computeTable(rmask
);
974 gtable
= computeTable(gmask
);
975 btable
= computeTable(bmask
);
977 retColor
->pixel
= (rtable
[color
->red
] << roffs
) |
978 (gtable
[color
->green
] << goffs
) | (btable
[color
->blue
] << boffs
);
980 retColor
->red
= color
->red
<< 8;
981 retColor
->green
= color
->green
<< 8;
982 retColor
->blue
= color
->blue
<< 8;
983 retColor
->flags
= DoRed
| DoGreen
| DoBlue
;
985 } else if (context
->vclass
== PseudoColor
|| context
->vclass
== StaticColor
) {
987 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
) {
988 unsigned int *rtable
, *gtable
, *btable
;
990 rtable
= computeStdTable(context
->std_rgb_map
->red_mult
, context
->std_rgb_map
->red_max
);
992 gtable
= computeStdTable(context
->std_rgb_map
->green_mult
,
993 context
->std_rgb_map
->green_max
);
995 btable
= computeStdTable(context
->std_rgb_map
->blue_mult
, context
->std_rgb_map
->blue_max
);
997 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
998 RErrorCode
= RERR_NOMEMORY
;
1002 retColor
->pixel
= (rtable
[color
->red
]
1003 + gtable
[color
->green
]
1004 + btable
[color
->blue
]
1005 + context
->std_rgb_map
->base_pixel
) & 0xffffffff;
1006 retColor
->red
= color
->red
<< 8;
1007 retColor
->green
= color
->green
<< 8;
1008 retColor
->blue
= color
->blue
<< 8;
1009 retColor
->flags
= DoRed
| DoGreen
| DoBlue
;
1012 const int cpc
= context
->attribs
->colors_per_channel
;
1013 const unsigned short rmask
= cpc
- 1; /* different sizes could be used */
1014 const unsigned short gmask
= rmask
; /* for r,g,b */
1015 const unsigned short bmask
= rmask
;
1016 unsigned short *rtable
, *gtable
, *btable
;
1017 const int cpccpc
= cpc
* cpc
;
1020 rtable
= computeTable(rmask
);
1021 gtable
= computeTable(gmask
);
1022 btable
= computeTable(bmask
);
1024 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
1025 RErrorCode
= RERR_NOMEMORY
;
1028 index
= rtable
[color
->red
] * cpccpc
+ gtable
[color
->green
] * cpc
+ btable
[color
->blue
];
1029 *retColor
= context
->colors
[index
];
1032 } else if (context
->vclass
== GrayScale
|| context
->vclass
== StaticGray
) {
1034 const int cpc
= context
->attribs
->colors_per_channel
;
1035 unsigned short gmask
;
1036 unsigned short *table
;
1039 if (context
->vclass
== StaticGray
)
1040 gmask
= (1 << context
->depth
) - 1; /* use all grays */
1042 gmask
= cpc
* cpc
* cpc
- 1;
1044 table
= computeTable(gmask
);
1048 index
= table
[(color
->red
* 30 + color
->green
* 59 + color
->blue
* 11) / 100];
1050 *retColor
= context
->colors
[index
];
1052 RErrorCode
= RERR_INTERNAL
;