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>
42 #define NFREE(n) if (n) free(n)
44 #define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
46 typedef struct RConversionTable
{
47 unsigned short table
[256];
50 struct RConversionTable
*next
;
53 typedef struct RStdConversionTable
{
54 unsigned int table
[256];
59 struct RStdConversionTable
*next
;
60 } RStdConversionTable
;
62 static RConversionTable
*conversionTable
= NULL
;
63 static RStdConversionTable
*stdConversionTable
= NULL
;
65 static void release_conversion_table(void)
67 RConversionTable
*tmp
= conversionTable
;
70 RConversionTable
*tmp_to_delete
= tmp
;
75 conversionTable
= NULL
;
78 static void release_std_conversion_table(void)
80 RStdConversionTable
*tmp
= stdConversionTable
;
83 RStdConversionTable
*tmp_to_delete
= tmp
;
88 stdConversionTable
= NULL
;
91 void r_destroy_conversion_tables(void)
93 release_conversion_table();
94 release_std_conversion_table();
97 static unsigned short *computeTable(unsigned short mask
)
99 RConversionTable
*tmp
= conversionTable
;
103 if (tmp
->index
== mask
)
111 tmp
= (RConversionTable
*) malloc(sizeof(RConversionTable
));
115 for (i
= 0; i
< 256; i
++)
116 tmp
->table
[i
] = (i
* mask
+ 0x7f) / 0xff;
119 tmp
->next
= conversionTable
;
120 conversionTable
= tmp
;
124 static unsigned int *computeStdTable(unsigned int mult
, unsigned int max
)
126 RStdConversionTable
*tmp
= stdConversionTable
;
130 if (tmp
->mult
== mult
&& tmp
->max
== max
)
138 tmp
= (RStdConversionTable
*) malloc(sizeof(RStdConversionTable
));
142 for (i
= 0; i
< 256; i
++) {
143 tmp
->table
[i
] = (i
* max
) / 0xff * mult
;
148 tmp
->next
= stdConversionTable
;
149 stdConversionTable
= tmp
;
154 /***************************************************************************/
157 convertTrueColor_generic(RXImage
* ximg
, RImage
* image
,
158 signed char *err
, signed char *nerr
,
159 const unsigned short *rtable
,
160 const unsigned short *gtable
,
161 const unsigned short *btable
,
162 const int dr
, const int dg
, const int db
,
163 const unsigned short roffs
, const unsigned short goffs
, const unsigned short boffs
)
169 unsigned char *ptr
= image
->data
;
170 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
172 /* convert and dither the image to XImage */
173 for (y
= 0; y
< image
->height
; y
++) {
177 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
180 pixel
= *ptr
+ err
[x
];
183 else if (pixel
> 0xff)
187 rer
= pixel
- r
* dr
;
190 pixel
= *(ptr
+ 1) + err
[x
+ 1];
193 else if (pixel
> 0xff)
197 ger
= pixel
- g
* dg
;
200 pixel
= *(ptr
+ 2) + err
[x
+ 2];
203 else if (pixel
> 0xff)
207 ber
= pixel
- b
* db
;
209 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
210 XPutPixel(ximg
->image
, x
, y
, pixel
);
212 /* distribute error */
218 err
[x
+ 1 + 3 * 1] += g
;
219 err
[x
+ 2 + 3 * 1] += b
;
225 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
226 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
227 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
229 /* skip to next line */
235 /* redither the 1st line to distribute error better */
241 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
244 pixel
= *ptr
+ err
[x
];
247 else if (pixel
> 0xff)
251 rer
= pixel
- r
* dr
;
254 pixel
= *(ptr
+ 1) + err
[x
+ 1];
257 else if (pixel
> 0xff)
261 ger
= pixel
- g
* dg
;
264 pixel
= *(ptr
+ 2) + err
[x
+ 2];
267 else if (pixel
> 0xff)
271 ber
= pixel
- b
* db
;
273 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
274 XPutPixel(ximg
->image
, x
, y
, pixel
);
276 /* distribute error */
282 err
[x
+ 1 + 3 * 1] += g
;
283 err
[x
+ 2 + 3 * 1] += b
;
289 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
290 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
291 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
295 static RXImage
*image2TrueColor(RContext
* ctx
, RImage
* image
)
298 unsigned short rmask
, gmask
, bmask
;
299 unsigned short roffs
, goffs
, boffs
;
300 unsigned short *rtable
, *gtable
, *btable
;
301 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
303 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
308 roffs
= ctx
->red_offset
;
309 goffs
= ctx
->green_offset
;
310 boffs
= ctx
->blue_offset
;
312 rmask
= ctx
->visual
->red_mask
>> roffs
;
313 gmask
= ctx
->visual
->green_mask
>> goffs
;
314 bmask
= ctx
->visual
->blue_mask
>> boffs
;
316 rtable
= computeTable(rmask
);
317 gtable
= computeTable(gmask
);
318 btable
= computeTable(bmask
);
320 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
321 RErrorCode
= RERR_NOMEMORY
;
322 RDestroyXImage(ctx
, ximg
);
326 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
328 unsigned long r
, g
, b
;
331 unsigned char *ptr
= image
->data
;
335 fputs("true color match\n", stderr
);
337 if (rmask
== 0xff && gmask
== 0xff && bmask
== 0xff) {
338 for (y
= 0; y
< image
->height
; y
++) {
339 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
344 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
345 XPutPixel(ximg
->image
, x
, y
, pixel
);
349 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
350 for (x
= 0; x
< image
->width
; x
++, ofs
+= channels
- 3) {
352 r
= rtable
[ptr
[ofs
++]];
353 g
= gtable
[ptr
[ofs
++]];
354 b
= btable
[ptr
[ofs
++]];
355 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
356 XPutPixel(ximg
->image
, x
, y
, pixel
);
362 const int dr
= 0xff / rmask
;
363 const int dg
= 0xff / gmask
;
364 const int db
= 0xff / bmask
;
367 fputs("true color dither\n", stderr
);
373 int ch
= (HAS_ALPHA(image
) ? 4 : 3);
375 err
= malloc(ch
* (image
->width
+ 2));
376 nerr
= malloc(ch
* (image
->width
+ 2));
380 RErrorCode
= RERR_NOMEMORY
;
381 RDestroyXImage(ctx
, ximg
);
385 memset(err
, 0, ch
* (image
->width
+ 2));
386 memset(nerr
, 0, ch
* (image
->width
+ 2));
388 convertTrueColor_generic(ximg
, image
, err
, nerr
,
389 rtable
, gtable
, btable
, dr
, dg
, db
, roffs
, goffs
, boffs
);
399 /***************************************************************************/
402 convertPseudoColor_to_8(RXImage
* ximg
, RImage
* image
,
403 signed char *err
, signed char *nerr
,
404 const unsigned short *rtable
,
405 const unsigned short *gtable
,
406 const unsigned short *btable
,
407 const int dr
, const int dg
, const int db
, unsigned long *pixels
, int cpc
)
413 unsigned char *ptr
= image
->data
;
414 unsigned char *optr
= (unsigned char *)ximg
->image
->data
;
415 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
416 int cpcpc
= cpc
* cpc
;
418 /* convert and dither the image to XImage */
419 for (y
= 0; y
< image
->height
; y
++) {
423 for (x
= 0; x
< image
->width
* 3; x
+= 3, ptr
+= channels
) {
426 pixel
= *ptr
+ err
[x
];
429 else if (pixel
> 0xff)
433 rer
= pixel
- r
* dr
;
436 pixel
= *(ptr
+ 1) + err
[x
+ 1];
439 else if (pixel
> 0xff)
443 ger
= pixel
- g
* dg
;
446 pixel
= *(ptr
+ 2) + err
[x
+ 2];
449 else if (pixel
> 0xff)
453 ber
= pixel
- b
* db
;
455 *optr
++ = pixels
[r
* cpcpc
+ g
* cpc
+ b
];
457 /* distribute error */
464 err
[x
+ 1 + 3 * 1] += g
;
465 err
[x
+ 2 + 3 * 1] += b
;
471 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
472 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
473 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
475 /* skip to next line */
480 optr
+= ximg
->image
->bytes_per_line
- image
->width
;
484 static RXImage
*image2PseudoColor(RContext
* ctx
, RImage
* image
)
487 register int x
, y
, r
, g
, b
;
490 const int cpc
= ctx
->attribs
->colors_per_channel
;
491 const unsigned short rmask
= cpc
- 1; /* different sizes could be used */
492 const unsigned short gmask
= rmask
; /* for r,g,b */
493 const unsigned short bmask
= rmask
;
494 unsigned short *rtable
, *gtable
, *btable
;
495 const int cpccpc
= cpc
* cpc
;
496 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
498 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
505 /* Tables are same at the moment because rmask==gmask==bmask. */
506 rtable
= computeTable(rmask
);
507 gtable
= computeTable(gmask
);
508 btable
= computeTable(bmask
);
510 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
511 RErrorCode
= RERR_NOMEMORY
;
512 RDestroyXImage(ctx
, ximg
);
516 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
519 fprintf(stderr
, "pseudo color match with %d colors per channel\n", cpc
);
521 for (y
= 0; y
< image
->height
; y
++) {
522 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
- 3) {
527 pixel
= r
* cpccpc
+ g
* cpc
+ b
;
528 /*data[ofs] = ctx->colors[pixel].pixel; */
529 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[pixel
].pixel
);
536 const int dr
= 0xff / rmask
;
537 const int dg
= 0xff / gmask
;
538 const int db
= 0xff / bmask
;
541 fprintf(stderr
, "pseudo color dithering with %d colors per channel\n", cpc
);
543 err
= malloc(4 * (image
->width
+ 3));
544 nerr
= malloc(4 * (image
->width
+ 3));
548 RErrorCode
= RERR_NOMEMORY
;
549 RDestroyXImage(ctx
, ximg
);
552 memset(err
, 0, 4 * (image
->width
+ 3));
553 memset(nerr
, 0, 4 * (image
->width
+ 3));
555 convertPseudoColor_to_8(ximg
, image
, err
+ 4, nerr
+ 4,
556 rtable
, gtable
, btable
, dr
, dg
, db
, ctx
->pixels
, cpc
);
566 * For standard colormap
568 static RXImage
*image2StandardPseudoColor(RContext
* ctx
, RImage
* image
)
571 register int x
, y
, r
, g
, b
;
575 unsigned int *rtable
, *gtable
, *btable
;
576 unsigned int base_pixel
= ctx
->std_rgb_map
->base_pixel
;
577 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
579 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
586 data
= (unsigned char *)ximg
->image
->data
;
588 rtable
= computeStdTable(ctx
->std_rgb_map
->red_mult
, ctx
->std_rgb_map
->red_max
);
590 gtable
= computeStdTable(ctx
->std_rgb_map
->green_mult
, ctx
->std_rgb_map
->green_max
);
592 btable
= computeStdTable(ctx
->std_rgb_map
->blue_mult
, ctx
->std_rgb_map
->blue_max
);
594 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
595 RErrorCode
= RERR_NOMEMORY
;
596 RDestroyXImage(ctx
, ximg
);
600 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
601 for (y
= 0; y
< image
->height
; y
++) {
602 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
604 pixel
= (rtable
[*ptr
] + gtable
[*(ptr
+ 1)]
605 + btable
[*(ptr
+ 2)] + base_pixel
) & 0xffffffff;
607 XPutPixel(ximg
->image
, x
, y
, pixel
);
612 signed short *err
, *nerr
;
618 fprintf(stderr
, "pseudo color dithering with %d colors per channel\n",
619 ctx
->attribs
->colors_per_channel
);
621 err
= (short *)malloc(3 * (image
->width
+ 2) * sizeof(short));
622 nerr
= (short *)malloc(3 * (image
->width
+ 2) * sizeof(short));
626 RErrorCode
= RERR_NOMEMORY
;
627 RDestroyXImage(ctx
, ximg
);
631 memset(err
, 0, 3 * (image
->width
+ 2) * sizeof(short));
632 memset(nerr
, 0, 3 * (image
->width
+ 2) * sizeof(short));
634 for (x
= 0, x1
= 0; x
< image
->width
* 3; x1
+= channels
- 3) {
635 err
[x
++] = ptr
[x1
++];
636 err
[x
++] = ptr
[x1
++];
637 err
[x
++] = ptr
[x1
++];
639 err
[x
] = err
[x
+ 1] = err
[x
+ 2] = 0;
640 /* convert and dither the image to XImage */
641 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
642 if (y
< image
->height
- 1) {
644 for (x
= 0, x1
= (y
+ 1) * image
->width
* channels
;
645 x
< image
->width
* 3; x1
+= channels
- 3) {
646 nerr
[x
++] = ptr
[x1
++];
647 nerr
[x
++] = ptr
[x1
++];
648 nerr
[x
++] = ptr
[x1
++];
652 nerr
[x
++] = ptr
[x1
++];
653 nerr
[x
++] = ptr
[x1
++];
654 nerr
[x
++] = ptr
[x1
++];
656 for (x
= 0; x
< image
->width
* 3; x
+= 3, ofs
++) {
662 if (err
[x
+ 1] > 0xff)
664 else if (err
[x
+ 1] < 0)
666 if (err
[x
+ 2] > 0xff)
668 else if (err
[x
+ 2] < 0)
672 g
= gtable
[err
[x
+ 1]];
673 b
= btable
[err
[x
+ 2]];
677 data
[ofs
] = base_pixel
+ pixel
;
680 rer
= err
[x
] - (ctx
->colors
[pixel
].red
>> 8);
681 ger
= err
[x
+ 1] - (ctx
->colors
[pixel
].green
>> 8);
682 ber
= err
[x
+ 2] - (ctx
->colors
[pixel
].blue
>> 8);
684 /* distribute error */
685 err
[x
+ 3 * 1] += (rer
* 7) / 16;
686 err
[x
+ 1 + 3 * 1] += (ger
* 7) / 16;
687 err
[x
+ 2 + 3 * 1] += (ber
* 7) / 16;
689 nerr
[x
] += (rer
* 5) / 16;
690 nerr
[x
+ 1] += (ger
* 5) / 16;
691 nerr
[x
+ 2] += (ber
* 5) / 16;
694 nerr
[x
- 3 * 1] += (rer
* 3) / 16;
695 nerr
[x
- 3 * 1 + 1] += (ger
* 3) / 16;
696 nerr
[x
- 3 * 1 + 2] += (ber
* 3) / 16;
699 nerr
[x
+ 3 * 1] += rer
/ 16;
700 nerr
[x
+ 1 + 3 * 1] += ger
/ 16;
701 nerr
[x
+ 2 + 3 * 1] += ber
/ 16;
703 /* skip to next line */
708 ofs
+= ximg
->image
->bytes_per_line
- image
->width
;
713 ximg
->image
->data
= (char *)data
;
718 static RXImage
*image2GrayScale(RContext
* ctx
, RImage
* image
)
721 register int x
, y
, g
;
723 const int cpc
= ctx
->attribs
->colors_per_channel
;
724 unsigned short gmask
;
725 unsigned short *table
;
727 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
729 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
736 data
= (unsigned char *)ximg
->image
->data
;
738 if (ctx
->vclass
== StaticGray
)
739 gmask
= (1 << ctx
->depth
) - 1; /* use all grays */
741 gmask
= cpc
* cpc
* cpc
- 1;
743 table
= computeTable(gmask
);
746 RErrorCode
= RERR_NOMEMORY
;
747 RDestroyXImage(ctx
, ximg
);
751 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
754 fprintf(stderr
, "grayscale match with %d colors per channel\n", cpc
);
756 for (y
= 0; y
< image
->height
; y
++) {
757 for (x
= 0; x
< image
->width
; x
++) {
759 g
= table
[(*ptr
* 30 + *(ptr
+ 1) * 59 + *(ptr
+ 2) * 11) / 100];
761 /*data[ofs] = ctx->colors[g].pixel; */
762 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
771 const int dg
= 0xff / gmask
;
774 fprintf(stderr
, "grayscale dither with %d colors per channel\n", cpc
);
776 gerr
= (short *)malloc((image
->width
+ 2) * sizeof(short));
777 ngerr
= (short *)malloc((image
->width
+ 2) * sizeof(short));
778 if (!gerr
|| !ngerr
) {
781 RErrorCode
= RERR_NOMEMORY
;
782 RDestroyXImage(ctx
, ximg
);
786 memset(gerr
, 0, (image
->width
+ 2) * sizeof(short));
787 memset(ngerr
, 0, (image
->width
+ 2) * sizeof(short));
789 for (x
= 0, y
= 0; x
< image
->width
; x
++, y
+= channels
) {
790 gerr
[x
] = (ptr
[y
] * 30 + ptr
[y
+ 1] * 59 + ptr
[y
+ 2] * 11) / 100;
793 /* convert and dither the image to XImage */
794 for (y
= 0; y
< image
->height
; y
++) {
795 if (y
< image
->height
- 1) {
797 for (x
= 0, x1
= (y
+ 1) * image
->width
* channels
; x
< image
->width
;
798 x
++, x1
+= channels
) {
799 ngerr
[x
] = (ptr
[x1
] * 30 + ptr
[x1
+ 1] * 59 + ptr
[x1
+ 2] * 11) / 100;
803 ngerr
[x
] = (ptr
[x1
] * 30 + ptr
[x1
+ 1] * 59 + ptr
[x1
+ 2] * 11) / 100;
805 for (x
= 0; x
< image
->width
; x
++) {
809 else if (gerr
[x
] < 0)
814 /*data[ofs] = ctx->colors[g].pixel; */
815 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
817 ger
= gerr
[x
] - g
* dg
;
819 /* distribute error */
826 ngerr
[x
+ 1] += ger
- 2 * g
;
828 /* skip to next line */
836 ximg
->image
->data
= (char *)data
;
841 static RXImage
*image2Bitmap(RContext
* ctx
, RImage
* image
, int threshold
)
844 unsigned char *alpha
;
847 ximg
= RCreateXImage(ctx
, 1, image
->width
, image
->height
);
851 alpha
= image
->data
+ 3;
853 for (y
= 0; y
< image
->height
; y
++) {
854 for (x
= 0; x
< image
->width
; x
++) {
855 XPutPixel(ximg
->image
, x
, y
, (*alpha
<= threshold
? 0 : 1));
863 int RConvertImage(RContext
* context
, RImage
* image
, Pixmap
* pixmap
)
865 RXImage
*ximg
= NULL
;
870 assert(context
!= NULL
);
871 assert(image
!= NULL
);
872 assert(pixmap
!= NULL
);
874 switch (context
->vclass
) {
876 ximg
= image2TrueColor(context
, image
);
881 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
)
882 ximg
= image2StandardPseudoColor(context
, image
);
884 ximg
= image2PseudoColor(context
, image
);
889 ximg
= image2GrayScale(context
, image
);
897 *pixmap
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
, image
->height
, context
->depth
);
900 if (context
->flags
.use_shared_pixmap
&& ximg
->is_shared
)
901 tmp
= R_CreateXImageMappedPixmap(context
, ximg
);
906 * We have to copy the shm Pixmap into a normal Pixmap because
907 * otherwise, we would have to control when Pixmaps are freed so
908 * that we can detach their shm segments. This is a problem if the
909 * program crash, leaving stale shared memory segments in the
910 * system (lots of them). But with some work, we can optimize
911 * things and remove this XCopyArea. This will require
912 * explicitly freeing all pixmaps when exiting or restarting
915 XCopyArea(context
->dpy
, tmp
, *pixmap
, context
->copy_gc
, 0, 0, image
->width
, image
->height
, 0, 0);
916 XFreePixmap(context
->dpy
, tmp
);
918 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
920 #else /* !USE_XSHM */
921 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
922 #endif /* !USE_XSHM */
924 RDestroyXImage(context
, ximg
);
929 /* make the gc permanent (create with context creation).
930 * GC creation is very expensive. altering its properties is not. -Dan
932 int RConvertImageMask(RContext
* context
, RImage
* image
, Pixmap
* pixmap
, Pixmap
* mask
, int threshold
)
936 RXImage
*ximg
= NULL
;
938 assert(context
!= NULL
);
939 assert(image
!= NULL
);
940 assert(pixmap
!= NULL
);
941 assert(mask
!= NULL
);
943 if (!RConvertImage(context
, image
, pixmap
))
946 if (image
->format
== RRGBFormat
) {
951 ximg
= image2Bitmap(context
, image
, threshold
);
956 *mask
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
, image
->height
, 1);
957 gcv
.foreground
= context
->black
;
958 gcv
.background
= context
->white
;
959 gcv
.graphics_exposures
= False
;
960 gc
= XCreateGC(context
->dpy
, *mask
, GCForeground
| GCBackground
| GCGraphicsExposures
, &gcv
);
961 RPutXImage(context
, *mask
, gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
962 RDestroyXImage(context
, ximg
);
963 XFreeGC(context
->dpy
, gc
);
968 Bool
RGetClosestXColor(RContext
* context
, const RColor
* color
, XColor
* retColor
)
970 if (context
->vclass
== TrueColor
) {
971 unsigned short rmask
, gmask
, bmask
;
972 unsigned short roffs
, goffs
, boffs
;
973 unsigned short *rtable
, *gtable
, *btable
;
975 roffs
= context
->red_offset
;
976 goffs
= context
->green_offset
;
977 boffs
= context
->blue_offset
;
979 rmask
= context
->visual
->red_mask
>> roffs
;
980 gmask
= context
->visual
->green_mask
>> goffs
;
981 bmask
= context
->visual
->blue_mask
>> boffs
;
983 rtable
= computeTable(rmask
);
984 gtable
= computeTable(gmask
);
985 btable
= computeTable(bmask
);
987 retColor
->pixel
= (((unsigned long) rtable
[color
->red
]) << roffs
)
988 | (((unsigned long) gtable
[color
->green
]) << goffs
)
989 | (((unsigned long) btable
[color
->blue
]) << boffs
);
991 retColor
->red
= color
->red
<< 8;
992 retColor
->green
= color
->green
<< 8;
993 retColor
->blue
= color
->blue
<< 8;
994 retColor
->flags
= DoRed
| DoGreen
| DoBlue
;
996 } else if (context
->vclass
== PseudoColor
|| context
->vclass
== StaticColor
) {
998 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
) {
999 unsigned int *rtable
, *gtable
, *btable
;
1001 rtable
= computeStdTable(context
->std_rgb_map
->red_mult
, context
->std_rgb_map
->red_max
);
1003 gtable
= computeStdTable(context
->std_rgb_map
->green_mult
,
1004 context
->std_rgb_map
->green_max
);
1006 btable
= computeStdTable(context
->std_rgb_map
->blue_mult
, context
->std_rgb_map
->blue_max
);
1008 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
1009 RErrorCode
= RERR_NOMEMORY
;
1013 retColor
->pixel
= (rtable
[color
->red
]
1014 + gtable
[color
->green
]
1015 + btable
[color
->blue
]
1016 + context
->std_rgb_map
->base_pixel
) & 0xffffffff;
1017 retColor
->red
= color
->red
<< 8;
1018 retColor
->green
= color
->green
<< 8;
1019 retColor
->blue
= color
->blue
<< 8;
1020 retColor
->flags
= DoRed
| DoGreen
| DoBlue
;
1023 const int cpc
= context
->attribs
->colors_per_channel
;
1024 const unsigned short rmask
= cpc
- 1; /* different sizes could be used */
1025 const unsigned short gmask
= rmask
; /* for r,g,b */
1026 const unsigned short bmask
= rmask
;
1027 unsigned short *rtable
, *gtable
, *btable
;
1028 const int cpccpc
= cpc
* cpc
;
1031 rtable
= computeTable(rmask
);
1032 gtable
= computeTable(gmask
);
1033 btable
= computeTable(bmask
);
1035 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
1036 RErrorCode
= RERR_NOMEMORY
;
1039 index
= rtable
[color
->red
] * cpccpc
+ gtable
[color
->green
] * cpc
+ btable
[color
->blue
];
1040 *retColor
= context
->colors
[index
];
1043 } else if (context
->vclass
== GrayScale
|| context
->vclass
== StaticGray
) {
1045 const int cpc
= context
->attribs
->colors_per_channel
;
1046 unsigned short gmask
;
1047 unsigned short *table
;
1050 if (context
->vclass
== StaticGray
)
1051 gmask
= (1 << context
->depth
) - 1; /* use all grays */
1053 gmask
= cpc
* cpc
* cpc
- 1;
1055 table
= computeTable(gmask
);
1059 index
= table
[(color
->red
* 30 + color
->green
* 59 + color
->blue
* 11) / 100];
1061 *retColor
= context
->colors
[index
];
1063 RErrorCode
= RERR_INTERNAL
;