1 /* convert.c - convert RImage to Pixmap
3 * Raster graphics library
5 * Copyright (c) 1997-2002 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
31 #include <X11/Xutil.h>
46 extern Pixmap
R_CreateXImageMappedPixmap(RContext
*context
, RXImage
*ximage
);
51 #define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
54 typedef struct RConversionTable
{
55 unsigned short table
[256];
58 struct RConversionTable
*next
;
62 typedef struct RStdConversionTable
{
63 unsigned int table
[256];
68 struct RStdConversionTable
*next
;
69 } RStdConversionTable
;
73 static RConversionTable
*conversionTable
= NULL
;
74 static RStdConversionTable
*stdConversionTable
= NULL
;
77 static unsigned short*
78 computeTable(unsigned short mask
)
80 RConversionTable
*tmp
= conversionTable
;
84 if (tmp
->index
== mask
)
92 tmp
= (RConversionTable
*)malloc(sizeof(RConversionTable
));
97 tmp
->table
[i
] = (i
*mask
+ 0x7f)/0xff;
100 tmp
->next
= conversionTable
;
101 conversionTable
= tmp
;
107 computeStdTable(unsigned int mult
, unsigned int max
)
109 RStdConversionTable
*tmp
= stdConversionTable
;
113 if (tmp
->mult
== mult
&& tmp
->max
== max
)
121 tmp
= (RStdConversionTable
*)malloc(sizeof(RStdConversionTable
));
125 for (i
=0; i
<256; i
++) {
126 tmp
->table
[i
] = (i
*max
)/0xff * mult
;
131 tmp
->next
= stdConversionTable
;
132 stdConversionTable
= tmp
;
137 /***************************************************************************/
141 convertTrueColor_generic(RXImage
*ximg
, RImage
*image
,
142 signed char *err
, signed char *nerr
,
146 const int dr
, const int dg
, const int db
,
147 const unsigned short roffs
,
148 const unsigned short goffs
,
149 const unsigned short boffs
)
155 unsigned char *ptr
= image
->data
;
156 int channels
= (image
->format
== RRGBAFormat
? 4 : 3);
158 /* convert and dither the image to XImage */
159 for (y
=0; y
<image
->height
; y
++) {
163 for (x
=0; x
<image
->width
; x
++, ptr
+=channels
) {
166 pixel
= *ptr
+ err
[x
];
167 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
173 pixel
= *(ptr
+1) + err
[x
+1];
174 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
180 pixel
= *(ptr
+2) + err
[x
+2];
181 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
187 pixel
= (r
<<roffs
) | (g
<<goffs
) | (b
<<boffs
);
188 XPutPixel(ximg
->image
, x
, y
, pixel
);
190 /* distribute error */
204 nerr
[x
+1+3*1]=ger
-2*g
;
205 nerr
[x
+2+3*1]=ber
-2*b
;
207 /* skip to next line */
213 /* redither the 1st line to distribute error better */
219 for (x
=0; x
<image
->width
; x
++, ptr
+=channels
) {
222 pixel
= *ptr
+ err
[x
];
223 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
229 pixel
= *(ptr
+1) + err
[x
+1];
230 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
236 pixel
= *(ptr
+2) + err
[x
+2];
237 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
243 pixel
= (r
<<roffs
) | (g
<<goffs
) | (b
<<boffs
);
244 XPutPixel(ximg
->image
, x
, y
, pixel
);
246 /* distribute error */
260 nerr
[x
+1+3*1]=ger
-2*g
;
261 nerr
[x
+2+3*1]=ber
-2*b
;
269 image2TrueColor(RContext
*ctx
, RImage
*image
)
272 unsigned short rmask
, gmask
, bmask
;
273 unsigned short roffs
, goffs
, boffs
;
274 unsigned short *rtable
, *gtable
, *btable
;
275 int channels
= (image
->format
== RRGBAFormat
? 4 : 3);
277 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
282 roffs
= ctx
->red_offset
;
283 goffs
= ctx
->green_offset
;
284 boffs
= ctx
->blue_offset
;
286 rmask
= ctx
->visual
->red_mask
>> roffs
;
287 gmask
= ctx
->visual
->green_mask
>> goffs
;
288 bmask
= ctx
->visual
->blue_mask
>> boffs
;
290 rtable
= computeTable(rmask
);
291 gtable
= computeTable(gmask
);
292 btable
= computeTable(bmask
);
294 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
295 RErrorCode
= RERR_NOMEMORY
;
296 RDestroyXImage(ctx
, ximg
);
305 if (ctx
->attribs
->render_mode
==RBestMatchRendering
) {
309 unsigned char *ptr
= image
->data
;
313 puts("true color match");
315 if (rmask
==0xff && gmask
==0xff && bmask
==0xff) {
316 for (y
=0; y
< image
->height
; y
++) {
317 for (x
=0; x
< image
->width
; x
++, ptr
+=channels
) {
319 pixel
= (*(ptr
)<<roffs
) | (*(ptr
+1)<<goffs
) | (*(ptr
+2)<<boffs
);
320 XPutPixel(ximg
->image
, x
, y
, pixel
);
324 for (y
=0, ofs
=0; y
< image
->height
; y
++) {
325 for (x
=0; x
< image
->width
; x
++, ofs
+=channels
-3) {
327 r
= rtable
[ptr
[ofs
++]];
328 g
= gtable
[ptr
[ofs
++]];
329 b
= btable
[ptr
[ofs
++]];
330 pixel
= (r
<<roffs
) | (g
<<goffs
) | (b
<<boffs
);
331 XPutPixel(ximg
->image
, x
, y
, pixel
);
337 const int dr
=0xff/rmask
;
338 const int dg
=0xff/gmask
;
339 const int db
=0xff/bmask
;
342 puts("true color dither");
347 int ch
= (image
->format
== RRGBAFormat
? 4 : 3);
349 err
= malloc(ch
*(image
->width
+2));
350 nerr
= malloc(ch
*(image
->width
+2));
354 RErrorCode
= RERR_NOMEMORY
;
355 RDestroyXImage(ctx
, ximg
);
359 memset(err
, 0, ch
*(image
->width
+2));
360 memset(nerr
, 0, ch
*(image
->width
+2));
362 convertTrueColor_generic(ximg
, image
, err
, nerr
,
363 rtable
, gtable
, btable
,
364 dr
, dg
, db
, roffs
, goffs
, boffs
);
379 /***************************************************************************/
382 convertPseudoColor_to_8(RXImage
*ximg
, RImage
*image
,
383 signed char *err
, signed char *nerr
,
387 const int dr
, const int dg
, const int db
,
388 unsigned long *pixels
,
395 unsigned char *ptr
= image
->data
;
396 unsigned char *optr
= ximg
->image
->data
;
397 int channels
= (image
->format
== RRGBAFormat
? 4 : 3);
400 /* convert and dither the image to XImage */
401 for (y
=0; y
<image
->height
; y
++) {
405 for (x
=0; x
<image
->width
*3; x
+=3, ptr
+=channels
) {
408 pixel
= *ptr
+ err
[x
];
409 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
415 pixel
= *(ptr
+1) + err
[x
+1];
416 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
422 pixel
= *(ptr
+2) + err
[x
+2];
423 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
428 *optr
++ = pixels
[r
*cpcpc
+ g
*cpc
+ b
];
430 /* distribute error */
445 nerr
[x
+1+3*1]=ger
-2*g
;
446 nerr
[x
+2+3*1]=ber
-2*b
;
448 /* skip to next line */
453 optr
+= ximg
->image
->bytes_per_line
- image
->width
;
460 image2PseudoColor(RContext
*ctx
, RImage
*image
)
463 register int x
, y
, r
, g
, b
;
466 const int cpc
=ctx
->attribs
->colors_per_channel
;
467 const unsigned short rmask
= cpc
-1; /* different sizes could be used */
468 const unsigned short gmask
= rmask
; /* for r,g,b */
469 const unsigned short bmask
= rmask
;
470 unsigned short *rtable
, *gtable
, *btable
;
471 const int cpccpc
= cpc
*cpc
;
472 int channels
= (image
->format
== RRGBAFormat
? 4 : 3);
474 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
481 /* Tables are same at the moment because rmask==gmask==bmask. */
482 rtable
= computeTable(rmask
);
483 gtable
= computeTable(gmask
);
484 btable
= computeTable(bmask
);
486 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
487 RErrorCode
= RERR_NOMEMORY
;
488 RDestroyXImage(ctx
, ximg
);
492 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
495 printf("pseudo color match with %d colors per channel\n", cpc
);
497 for (y
=0; y
<image
->height
; y
++) {
498 for (x
=0; x
<image
->width
; x
++, ptr
+=channels
-3) {
503 pixel
= r
*cpccpc
+ g
*cpc
+ b
;
504 /*data[ofs] = ctx->colors[pixel].pixel;*/
505 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[pixel
].pixel
);
512 const int dr
=0xff/rmask
;
513 const int dg
=0xff/gmask
;
514 const int db
=0xff/bmask
;
518 printf("pseudo color dithering with %d colors per channel\n", cpc
);
520 err
= malloc(4*(image
->width
+3));
521 nerr
= malloc(4*(image
->width
+3));
525 RErrorCode
= RERR_NOMEMORY
;
526 RDestroyXImage(ctx
, ximg
);
529 memset(err
, 0, 4*(image
->width
+3));
530 memset(nerr
, 0, 4*(image
->width
+3));
532 convertPseudoColor_to_8(ximg
, image
, err
+4, nerr
+4,
533 rtable
, gtable
, btable
,
534 dr
, dg
, db
, ctx
->pixels
, cpc
);
545 * For standard colormap
548 image2StandardPseudoColor(RContext
*ctx
, RImage
*image
)
551 register int x
, y
, r
, g
, b
;
555 unsigned int *rtable
, *gtable
, *btable
;
556 unsigned int base_pixel
= ctx
->std_rgb_map
->base_pixel
;
557 int channels
= (image
->format
== RRGBAFormat
? 4 : 3);
560 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
567 data
= (unsigned char *)ximg
->image
->data
;
570 rtable
= computeStdTable(ctx
->std_rgb_map
->red_mult
,
571 ctx
->std_rgb_map
->red_max
);
573 gtable
= computeStdTable(ctx
->std_rgb_map
->green_mult
,
574 ctx
->std_rgb_map
->green_max
);
576 btable
= computeStdTable(ctx
->std_rgb_map
->blue_mult
,
577 ctx
->std_rgb_map
->blue_max
);
579 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
580 RErrorCode
= RERR_NOMEMORY
;
581 RDestroyXImage(ctx
, ximg
);
586 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
587 for (y
=0; y
<image
->height
; y
++) {
588 for (x
=0; x
<image
->width
; x
++, ptr
+=channels
) {
590 pixel
= (rtable
[*ptr
] + gtable
[*(ptr
+1)]
591 + btable
[*(ptr
+2)] + base_pixel
) & 0xffffffff;
593 XPutPixel(ximg
->image
, x
, y
, pixel
);
598 signed short *err
, *nerr
;
604 printf("pseudo color dithering with %d colors per channel\n", cpc
);
606 err
= (short*)malloc(3*(image
->width
+2)*sizeof(short));
607 nerr
= (short*)malloc(3*(image
->width
+2)*sizeof(short));
613 RErrorCode
= RERR_NOMEMORY
;
614 RDestroyXImage(ctx
, ximg
);
617 for (x
=0, x1
=0; x
<image
->width
*3; x1
+=channels
-3) {
618 err
[x
++] = ptr
[x1
++];
619 err
[x
++] = ptr
[x1
++];
620 err
[x
++] = ptr
[x1
++];
622 err
[x
] = err
[x
+1] = err
[x
+2] = 0;
623 /* convert and dither the image to XImage */
624 for (y
=0, ofs
=0; y
<image
->height
; y
++) {
625 if (y
<image
->height
-1) {
627 for (x
=0, x1
=(y
+1)*image
->width
*channels
;
630 nerr
[x
++] = ptr
[x1
++];
631 nerr
[x
++] = ptr
[x1
++];
632 nerr
[x
++] = ptr
[x1
++];
636 nerr
[x
++] = ptr
[x1
++];
637 nerr
[x
++] = ptr
[x1
++];
638 nerr
[x
++] = ptr
[x1
++];
640 for (x
=0; x
<image
->width
*3; x
+=3, ofs
++) {
642 if (err
[x
]>0xff) err
[x
]=0xff; else if (err
[x
]<0) err
[x
]=0;
643 if (err
[x
+1]>0xff) err
[x
+1]=0xff; else if (err
[x
+1]<0) err
[x
+1]=0;
644 if (err
[x
+2]>0xff) err
[x
+2]=0xff; else if (err
[x
+2]<0) err
[x
+2]=0;
647 g
= gtable
[err
[x
+1]];
648 b
= btable
[err
[x
+2]];
652 data
[ofs
] = base_pixel
+ pixel
;
655 rer
= err
[x
] - (ctx
->colors
[pixel
].red
>>8);
656 ger
= err
[x
+1] - (ctx
->colors
[pixel
].green
>>8);
657 ber
= err
[x
+2] - (ctx
->colors
[pixel
].blue
>>8);
659 /* distribute error */
660 err
[x
+3*1]+=(rer
*7)/16;
661 err
[x
+1+3*1]+=(ger
*7)/16;
662 err
[x
+2+3*1]+=(ber
*7)/16;
665 nerr
[x
+1]+=(ger
*5)/16;
666 nerr
[x
+2]+=(ber
*5)/16;
669 nerr
[x
-3*1]+=(rer
*3)/16;
670 nerr
[x
-3*1+1]+=(ger
*3)/16;
671 nerr
[x
-3*1+2]+=(ber
*3)/16;
675 nerr
[x
+1+3*1]+=ger
/16;
676 nerr
[x
+2+3*1]+=ber
/16;
678 /* skip to next line */
683 ofs
+= ximg
->image
->bytes_per_line
- image
->width
;
688 ximg
->image
->data
= (char*)data
;
696 image2GrayScale(RContext
*ctx
, RImage
*image
)
699 register int x
, y
, g
;
701 const int cpc
=ctx
->attribs
->colors_per_channel
;
702 unsigned short gmask
;
703 unsigned short *table
;
705 int channels
= (image
->format
== RRGBAFormat
? 4 : 3);
708 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
715 data
= (unsigned char *)ximg
->image
->data
;
717 if (ctx
->vclass
== StaticGray
)
718 gmask
= (1<<ctx
->depth
) - 1; /* use all grays */
720 gmask
= cpc
*cpc
*cpc
-1;
722 table
= computeTable(gmask
);
725 RErrorCode
= RERR_NOMEMORY
;
726 RDestroyXImage(ctx
, ximg
);
730 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
733 printf("grayscale match with %d colors per channel\n", cpc
);
735 for (y
=0; y
<image
->height
; y
++) {
736 for (x
=0; x
<image
->width
; x
++) {
738 g
= table
[(*ptr
* 30 + *(ptr
+1) * 59 + *(ptr
+2) * 11)/100];
740 /*data[ofs] = ctx->colors[g].pixel;*/
741 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
750 const int dg
=0xff/gmask
;
753 printf("grayscale dither with %d colors per channel\n", cpc
);
755 gerr
= (short*)malloc((image
->width
+2)*sizeof(short));
756 ngerr
= (short*)malloc((image
->width
+2)*sizeof(short));
757 if (!gerr
|| !ngerr
) {
760 RErrorCode
= RERR_NOMEMORY
;
761 RDestroyXImage(ctx
, ximg
);
764 for (x
=0, y
=0; x
<image
->width
; x
++, y
+=channels
) {
765 gerr
[x
] = (ptr
[y
]*30 + ptr
[y
+1]*59 + ptr
[y
+2]*11)/100;
768 /* convert and dither the image to XImage */
769 for (y
=0; y
<image
->height
; y
++) {
770 if (y
<image
->height
-1) {
772 for (x
=0, x1
=(y
+1)*image
->width
*channels
; x
<image
->width
; x
++, x1
+=channels
) {
773 ngerr
[x
] = (ptr
[x1
]*30 + ptr
[x1
+1]*59 + ptr
[x1
+2]*11)/100;
777 ngerr
[x
] = (ptr
[x1
]*30 + ptr
[x1
+1]*59 + ptr
[x1
+2]*11)/100;
779 for (x
=0; x
<image
->width
; x
++) {
781 if (gerr
[x
]>0xff) gerr
[x
]=0xff; else if (gerr
[x
]<0) gerr
[x
]=0;
785 /*data[ofs] = ctx->colors[g].pixel;*/
786 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
788 ger
= gerr
[x
] - g
*dg
;
790 /* distribute error */
799 /* skip to next line */
807 ximg
->image
->data
= (char*)data
;
814 image2Bitmap(RContext
*ctx
, RImage
*image
, int threshold
)
817 unsigned char *alpha
;
820 ximg
= RCreateXImage(ctx
, 1, image
->width
, image
->height
);
824 alpha
= image
->data
+3;
826 for (y
= 0; y
< image
->height
; y
++) {
827 for (x
= 0; x
< image
->width
; x
++) {
828 XPutPixel(ximg
->image
, x
, y
, (*alpha
<= threshold
? 0 : 1));
840 hermesConvert(RContext
*context
, RImage
*image
)
847 ximage
= RCreateXImage(context
, context
->depth
,
848 image
->width
, image
->height
);
853 /* The masks look weird for images with alpha. but they work this way.
854 * wth does hermes do internally?
856 source
.bits
= (HAS_ALPHA(image
) ? 32 : 24);
857 if (ximage
->image
->byte_order
==LSBFirst
) {
862 if (source
.bits
== 32) {
863 source
.r
= 0xff000000;
864 source
.g
= 0x00ff0000;
865 source
.b
= 0x0000ff00;
872 source
.a
= 0; /* Don't care about alpha */
874 source
.has_colorkey
= 0;
876 /* This is a hack and certainly looks weird, but it works :P
877 * it assumes though that green is inbetween red and blue (the mask) */
878 if (ximage
->image
->byte_order
==LSBFirst
) {
879 dest
.r
= context
->visual
->blue_mask
;
880 dest
.g
= context
->visual
->green_mask
;
881 dest
.b
= context
->visual
->red_mask
;
883 dest
.r
= context
->visual
->red_mask
;
884 dest
.g
= context
->visual
->green_mask
;
885 dest
.b
= context
->visual
->blue_mask
;
888 dest
.bits
= ximage
->image
->bits_per_pixel
;
889 if (context
->vclass
== TrueColor
)
893 dest
.has_colorkey
= 0;
895 /*printf("source r=0x%x, g=0x%x, b=0x%x, a=0x%x, b=%d, i=%d, c=%d\n",
896 source.r, source.g, source.b, source.a,
897 source.bits, source.indexed, source.has_colorkey);
898 printf("dest r=0x%x, g=0x%x, b=0x%x, a=0x%x, b=%d, i=%d, c=%d\n",
899 dest.r, dest.g, dest.b, dest.a,
900 dest.bits, dest.indexed, dest.has_colorkey);
903 Hermes_ConverterRequest(context
->hermes_data
->converter
, &source
, &dest
);
905 Hermes_ConverterPalette(context
->hermes_data
->converter
,
906 context
->hermes_data
->palette
, 0);
908 Hermes_ConverterCopy(context
->hermes_data
->converter
,
909 image
->data
, 0, 0, image
->width
, image
->height
,
910 image
->width
* (image
->format
== RRGBFormat
? 3 : 4),
911 ximage
->image
->data
, 0, 0,
912 image
->width
, image
->height
,
913 ximage
->image
->bytes_per_line
);
917 #endif /* HAVE_HERMES */
921 RConvertImage(RContext
*context
, RImage
*image
, Pixmap
*pixmap
)
928 assert(context
!=NULL
);
930 assert(pixmap
!=NULL
);
932 switch (context
->vclass
) {
935 if (context
->attribs
->render_mode
== RBestMatchRendering
) {
936 ximg
= hermesConvert(context
, image
);
938 ximg
= image2TrueColor(context
, image
);
940 #else /* !HAVE_HERMES */
941 ximg
= image2TrueColor(context
, image
);
947 /* For StaticColor we can also use hermes, but it doesn't dither */
951 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
)
952 ximg
= image2StandardPseudoColor(context
, image
);
954 ximg
= image2PseudoColor(context
, image
);
962 ximg
= image2GrayScale(context
, image
);
971 *pixmap
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
,
972 image
->height
, context
->depth
);
975 if (context
->flags
.use_shared_pixmap
&& ximg
->is_shared
)
976 tmp
= R_CreateXImageMappedPixmap(context
, ximg
);
981 * We have to copy the shm Pixmap into a normal Pixmap because
982 * otherwise, we would have to control when Pixmaps are freed so
983 * that we can detach their shm segments. This is a problem if the
984 * program crash, leaving stale shared memory segments in the
985 * system (lots of them). But with some work, we can optimize
986 * things and remove this XCopyArea. This will require
987 * explicitly freeing all pixmaps when exiting or restarting
990 XCopyArea(context
->dpy
, tmp
, *pixmap
, context
->copy_gc
, 0, 0,
991 image
->width
, image
->height
, 0, 0);
992 XFreePixmap(context
->dpy
, tmp
);
994 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0,
995 image
->width
, image
->height
);
998 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0,
999 image
->width
, image
->height
);
1002 RDestroyXImage(context
, ximg
);
1009 RConvertImageMask(RContext
*context
, RImage
*image
, Pixmap
*pixmap
,
1010 Pixmap
*mask
, int threshold
)
1016 assert(context
!=NULL
);
1017 assert(image
!=NULL
);
1018 assert(pixmap
!=NULL
);
1021 if (!RConvertImage(context
, image
, pixmap
))
1024 if (image
->format
==RRGBFormat
) {
1029 ximg
= image2Bitmap(context
, image
, threshold
);
1034 *mask
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
,
1036 gcv
.foreground
= context
->black
;
1037 gcv
.background
= context
->white
;
1038 gcv
.graphics_exposures
= False
;
1039 gc
= XCreateGC(context
->dpy
, *mask
, GCForeground
|GCBackground
1040 |GCGraphicsExposures
, &gcv
);
1041 RPutXImage(context
, *mask
, gc
, ximg
, 0, 0, 0, 0,
1042 image
->width
, image
->height
);
1043 RDestroyXImage(context
, ximg
);
1044 XFreeGC(context
->dpy
, gc
);
1051 RGetClosestXColor(RContext
*context
, RColor
*color
, XColor
*retColor
)
1053 if (context
->vclass
== TrueColor
) {
1054 unsigned short rmask
, gmask
, bmask
;
1055 unsigned short roffs
, goffs
, boffs
;
1056 unsigned short *rtable
, *gtable
, *btable
;
1058 roffs
= context
->red_offset
;
1059 goffs
= context
->green_offset
;
1060 boffs
= context
->blue_offset
;
1062 rmask
= context
->visual
->red_mask
>> roffs
;
1063 gmask
= context
->visual
->green_mask
>> goffs
;
1064 bmask
= context
->visual
->blue_mask
>> boffs
;
1066 rtable
= computeTable(rmask
);
1067 gtable
= computeTable(gmask
);
1068 btable
= computeTable(bmask
);
1070 retColor
->pixel
= (rtable
[color
->red
]<<roffs
) |
1071 (gtable
[color
->green
]<<goffs
) | (btable
[color
->blue
]<<boffs
);
1073 retColor
->red
= color
->red
<< 8;
1074 retColor
->green
= color
->green
<< 8;
1075 retColor
->blue
= color
->blue
<< 8;
1076 retColor
->flags
= DoRed
|DoGreen
|DoBlue
;
1078 } else if (context
->vclass
== PseudoColor
1079 || context
->vclass
== StaticColor
) {
1081 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
) {
1082 unsigned int *rtable
, *gtable
, *btable
;
1084 rtable
= computeStdTable(context
->std_rgb_map
->red_mult
,
1085 context
->std_rgb_map
->red_max
);
1087 gtable
= computeStdTable(context
->std_rgb_map
->green_mult
,
1088 context
->std_rgb_map
->green_max
);
1090 btable
= computeStdTable(context
->std_rgb_map
->blue_mult
,
1091 context
->std_rgb_map
->blue_max
);
1093 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
1094 RErrorCode
= RERR_NOMEMORY
;
1098 retColor
->pixel
= (rtable
[color
->red
]
1099 + gtable
[color
->green
]
1100 + btable
[color
->blue
]
1101 + context
->std_rgb_map
->base_pixel
) & 0xffffffff;
1102 retColor
->red
= color
->red
<<8;
1103 retColor
->green
= color
->green
<<8;
1104 retColor
->blue
= color
->blue
<<8;
1105 retColor
->flags
= DoRed
|DoGreen
|DoBlue
;
1108 const int cpc
=context
->attribs
->colors_per_channel
;
1109 const unsigned short rmask
= cpc
-1; /* different sizes could be used */
1110 const unsigned short gmask
= rmask
; /* for r,g,b */
1111 const unsigned short bmask
= rmask
;
1112 unsigned short *rtable
, *gtable
, *btable
;
1113 const int cpccpc
= cpc
*cpc
;
1116 rtable
= computeTable(rmask
);
1117 gtable
= computeTable(gmask
);
1118 btable
= computeTable(bmask
);
1120 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
1121 RErrorCode
= RERR_NOMEMORY
;
1124 index
= rtable
[color
->red
]*cpccpc
+ gtable
[color
->green
]*cpc
1125 + btable
[color
->blue
];
1126 *retColor
= context
->colors
[index
];
1129 } else if (context
->vclass
== GrayScale
|| context
->vclass
== StaticGray
) {
1131 const int cpc
= context
->attribs
->colors_per_channel
;
1132 unsigned short gmask
;
1133 unsigned short *table
;
1136 if (context
->vclass
== StaticGray
)
1137 gmask
= (1<<context
->depth
) - 1; /* use all grays */
1139 gmask
= cpc
*cpc
*cpc
-1;
1141 table
= computeTable(gmask
);
1145 index
= table
[(color
->red
*30 + color
->green
*59 + color
->blue
*11)/100];
1147 *retColor
= context
->colors
[index
];
1149 RErrorCode
= RERR_INTERNAL
;