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
31 #include <X11/Xutil.h>
46 extern Pixmap
R_CreateXImageMappedPixmap(RContext
*context
, RXImage
*ximage
);
52 extern void x86_PseudoColor_32_to_8(unsigned char *image
,
53 unsigned char *ximage
,
54 char *err
, char *nerr
,
56 int dr
, int dg
, int db
,
57 unsigned long *pixels
,
59 int width
, int height
,
66 extern int x86_check_mmx();
68 extern void x86_mmx_TrueColor_32_to_16(unsigned char *image
,
69 unsigned short *ximage
,
70 short *err
, short *nerr
,
71 const unsigned short *rtable
,
72 const unsigned short *gtable
,
73 const unsigned short *btable
,
74 int dr
, int dg
, int db
,
78 int width
, int height
,
83 #endif /* ASM_X86_MMX */
85 #define NFREE(n) if (n) free(n)
87 #define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
90 typedef struct RConversionTable
{
91 unsigned short table
[256];
94 struct RConversionTable
*next
;
98 typedef struct RStdConversionTable
{
99 unsigned int table
[256];
104 struct RStdConversionTable
*next
;
105 } RStdConversionTable
;
109 static RConversionTable
*conversionTable
= NULL
;
110 static RStdConversionTable
*stdConversionTable
= NULL
;
113 static unsigned short*
114 computeTable(unsigned short mask
)
116 RConversionTable
*tmp
= conversionTable
;
120 if (tmp
->index
== mask
)
128 tmp
= (RConversionTable
*)malloc(sizeof(RConversionTable
));
133 tmp
->table
[i
] = (i
*mask
+ 0x7f)/0xff;
136 tmp
->next
= conversionTable
;
137 conversionTable
= tmp
;
143 computeStdTable(unsigned int mult
, unsigned int max
)
145 RStdConversionTable
*tmp
= stdConversionTable
;
149 if (tmp
->mult
== mult
&& tmp
->max
== max
)
157 tmp
= (RStdConversionTable
*)malloc(sizeof(RStdConversionTable
));
161 for (i
=0; i
<256; i
++) {
162 tmp
->table
[i
] = (i
*max
)/0xff * mult
;
167 tmp
->next
= stdConversionTable
;
168 stdConversionTable
= tmp
;
173 /***************************************************************************/
177 convertTrueColor_generic(RXImage
*ximg
, RImage
*image
,
178 signed char *err
, signed char *nerr
,
179 const unsigned short *rtable
,
180 const unsigned short *gtable
,
181 const unsigned short *btable
,
182 const int dr
, const int dg
, const int db
,
183 const unsigned short roffs
,
184 const unsigned short goffs
,
185 const unsigned short boffs
)
191 unsigned char *ptr
= image
->data
;
192 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
194 /* convert and dither the image to XImage */
195 for (y
=0; y
<image
->height
; y
++) {
199 for (x
=0; x
<image
->width
; x
++, ptr
+=channels
) {
202 pixel
= *ptr
+ err
[x
];
203 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
209 pixel
= *(ptr
+1) + err
[x
+1];
210 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
216 pixel
= *(ptr
+2) + err
[x
+2];
217 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
223 pixel
= (r
<<roffs
) | (g
<<goffs
) | (b
<<boffs
);
224 XPutPixel(ximg
->image
, x
, y
, pixel
);
226 /* distribute error */
240 nerr
[x
+1+3*1]=ger
-2*g
;
241 nerr
[x
+2+3*1]=ber
-2*b
;
243 /* skip to next line */
249 /* redither the 1st line to distribute error better */
255 for (x
=0; x
<image
->width
; x
++, ptr
+=channels
) {
258 pixel
= *ptr
+ err
[x
];
259 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
265 pixel
= *(ptr
+1) + err
[x
+1];
266 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
272 pixel
= *(ptr
+2) + err
[x
+2];
273 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
279 pixel
= (r
<<roffs
) | (g
<<goffs
) | (b
<<boffs
);
280 XPutPixel(ximg
->image
, x
, y
, pixel
);
282 /* distribute error */
296 nerr
[x
+1+3*1]=ger
-2*g
;
297 nerr
[x
+2+3*1]=ber
-2*b
;
305 image2TrueColor(RContext
*ctx
, RImage
*image
)
308 unsigned short rmask
, gmask
, bmask
;
309 unsigned short roffs
, goffs
, boffs
;
310 unsigned short *rtable
, *gtable
, *btable
;
311 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
313 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
318 roffs
= ctx
->red_offset
;
319 goffs
= ctx
->green_offset
;
320 boffs
= ctx
->blue_offset
;
322 rmask
= ctx
->visual
->red_mask
>> roffs
;
323 gmask
= ctx
->visual
->green_mask
>> goffs
;
324 bmask
= ctx
->visual
->blue_mask
>> boffs
;
326 rtable
= computeTable(rmask
);
327 gtable
= computeTable(gmask
);
328 btable
= computeTable(bmask
);
330 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
331 RErrorCode
= RERR_NOMEMORY
;
332 RDestroyXImage(ctx
, ximg
);
341 if (ctx
->attribs
->render_mode
==RBestMatchRendering
) {
345 unsigned char *ptr
= image
->data
;
349 puts("true color match");
351 if (rmask
==0xff && gmask
==0xff && bmask
==0xff) {
352 for (y
=0; y
< image
->height
; y
++) {
353 for (x
=0; x
< image
->width
; x
++, ptr
+=channels
) {
355 pixel
= (*(ptr
)<<roffs
) | (*(ptr
+1)<<goffs
) | (*(ptr
+2)<<boffs
);
356 XPutPixel(ximg
->image
, x
, y
, pixel
);
360 for (y
=0, ofs
=0; y
< image
->height
; y
++) {
361 for (x
=0; x
< image
->width
; x
++, ofs
+=channels
-3) {
363 r
= rtable
[ptr
[ofs
++]];
364 g
= gtable
[ptr
[ofs
++]];
365 b
= btable
[ptr
[ofs
++]];
366 pixel
= (r
<<roffs
) | (g
<<goffs
) | (b
<<boffs
);
367 XPutPixel(ximg
->image
, x
, y
, pixel
);
373 const int dr
=0xff/rmask
;
374 const int dg
=0xff/gmask
;
375 const int db
=0xff/bmask
;
378 puts("true color dither");
382 if (ctx
->depth
==16 && HAS_ALPHA(image
) && x86_check_mmx()) {
386 err
= malloc(8*(image
->width
+3));
387 nerr
= malloc(8*(image
->width
+3));
391 RErrorCode
= RERR_NOMEMORY
;
392 RDestroyXImage(ctx
, ximg
);
395 memset(err
, 0, 8*(image
->width
+3));
396 memset(nerr
, 0, 8*(image
->width
+3));
398 x86_mmx_TrueColor_32_to_16(image
->data
,
399 (unsigned short*)ximg
->image
->data
,
401 rtable
, gtable
, btable
,
404 image
->width
, image
->height
,
405 ximg
->image
->bytes_per_line
- 2*image
->width
);
410 #endif /* ASM_X86_MMX */
414 int ch
= (HAS_ALPHA(image
) ? 4 : 3);
416 err
= malloc(ch
*(image
->width
+2));
417 nerr
= malloc(ch
*(image
->width
+2));
421 RErrorCode
= RERR_NOMEMORY
;
422 RDestroyXImage(ctx
, ximg
);
426 memset(err
, 0, ch
*(image
->width
+2));
427 memset(nerr
, 0, ch
*(image
->width
+2));
429 convertTrueColor_generic(ximg
, image
, err
, nerr
,
430 rtable
, gtable
, btable
,
431 dr
, dg
, db
, roffs
, goffs
, boffs
);
446 /***************************************************************************/
449 convertPseudoColor_to_8(RXImage
*ximg
, RImage
*image
,
450 signed char *err
, signed char *nerr
,
451 const unsigned short *rtable
,
452 const unsigned short *gtable
,
453 const unsigned short *btable
,
454 const int dr
, const int dg
, const int db
,
455 unsigned long *pixels
,
462 unsigned char *ptr
= image
->data
;
463 unsigned char *optr
= (unsigned char*)ximg
->image
->data
;
464 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
467 /* convert and dither the image to XImage */
468 for (y
=0; y
<image
->height
; y
++) {
472 for (x
=0; x
<image
->width
*3; x
+=3, ptr
+=channels
) {
475 pixel
= *ptr
+ err
[x
];
476 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
482 pixel
= *(ptr
+1) + err
[x
+1];
483 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
489 pixel
= *(ptr
+2) + err
[x
+2];
490 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
495 *optr
++ = pixels
[r
*cpcpc
+ g
*cpc
+ b
];
497 /* distribute error */
512 nerr
[x
+1+3*1]=ger
-2*g
;
513 nerr
[x
+2+3*1]=ber
-2*b
;
515 /* skip to next line */
520 optr
+= ximg
->image
->bytes_per_line
- image
->width
;
527 image2PseudoColor(RContext
*ctx
, RImage
*image
)
530 register int x
, y
, r
, g
, b
;
533 const int cpc
=ctx
->attribs
->colors_per_channel
;
534 const unsigned short rmask
= cpc
-1; /* different sizes could be used */
535 const unsigned short gmask
= rmask
; /* for r,g,b */
536 const unsigned short bmask
= rmask
;
537 unsigned short *rtable
, *gtable
, *btable
;
538 const int cpccpc
= cpc
*cpc
;
539 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
541 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
548 /* Tables are same at the moment because rmask==gmask==bmask. */
549 rtable
= computeTable(rmask
);
550 gtable
= computeTable(gmask
);
551 btable
= computeTable(bmask
);
553 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
554 RErrorCode
= RERR_NOMEMORY
;
555 RDestroyXImage(ctx
, ximg
);
559 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
562 printf("pseudo color match with %d colors per channel\n", cpc
);
564 for (y
=0; y
<image
->height
; y
++) {
565 for (x
=0; x
<image
->width
; x
++, ptr
+=channels
-3) {
570 pixel
= r
*cpccpc
+ g
*cpc
+ b
;
571 /*data[ofs] = ctx->colors[pixel].pixel;*/
572 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[pixel
].pixel
);
579 const int dr
=0xff/rmask
;
580 const int dg
=0xff/gmask
;
581 const int db
=0xff/bmask
;
585 printf("pseudo color dithering with %d colors per channel\n", cpc
);
587 err
= malloc(4*(image
->width
+3));
588 nerr
= malloc(4*(image
->width
+3));
592 RErrorCode
= RERR_NOMEMORY
;
593 RDestroyXImage(ctx
, ximg
);
596 memset(err
, 0, 4*(image
->width
+3));
597 memset(nerr
, 0, 4*(image
->width
+3));
601 x86_PseudoColor_32_to_8(image
->data
, ximg
->image
->data
,
604 dr
, dg
, db
, ctx
->pixels
, cpc
,
605 image
->width
, image
->height
,
607 ximg
->image
->bytes_per_line
- image
->width
);
609 convertPseudoColor_to_8(ximg
, image
, err
+4, nerr
+4,
610 rtable
, gtable
, btable
,
611 dr
, dg
, db
, ctx
->pixels
, cpc
);
623 * For standard colormap
626 image2StandardPseudoColor(RContext
*ctx
, RImage
*image
)
629 register int x
, y
, r
, g
, b
;
633 unsigned int *rtable
, *gtable
, *btable
;
634 unsigned int base_pixel
= ctx
->std_rgb_map
->base_pixel
;
635 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
638 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
645 data
= (unsigned char *)ximg
->image
->data
;
648 rtable
= computeStdTable(ctx
->std_rgb_map
->red_mult
,
649 ctx
->std_rgb_map
->red_max
);
651 gtable
= computeStdTable(ctx
->std_rgb_map
->green_mult
,
652 ctx
->std_rgb_map
->green_max
);
654 btable
= computeStdTable(ctx
->std_rgb_map
->blue_mult
,
655 ctx
->std_rgb_map
->blue_max
);
657 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
658 RErrorCode
= RERR_NOMEMORY
;
659 RDestroyXImage(ctx
, ximg
);
664 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
665 for (y
=0; y
<image
->height
; y
++) {
666 for (x
=0; x
<image
->width
; x
++, ptr
+=channels
) {
668 pixel
= (rtable
[*ptr
] + gtable
[*(ptr
+1)]
669 + btable
[*(ptr
+2)] + base_pixel
) & 0xffffffff;
671 XPutPixel(ximg
->image
, x
, y
, pixel
);
676 signed short *err
, *nerr
;
682 printf("pseudo color dithering with %d colors per channel\n",
683 ctx
->attribs
->colors_per_channel
);
685 err
= (short*)malloc(3*(image
->width
+2)*sizeof(short));
686 nerr
= (short*)malloc(3*(image
->width
+2)*sizeof(short));
690 RErrorCode
= RERR_NOMEMORY
;
691 RDestroyXImage(ctx
, ximg
);
694 for (x
=0, x1
=0; x
<image
->width
*3; x1
+=channels
-3) {
695 err
[x
++] = ptr
[x1
++];
696 err
[x
++] = ptr
[x1
++];
697 err
[x
++] = ptr
[x1
++];
699 err
[x
] = err
[x
+1] = err
[x
+2] = 0;
700 /* convert and dither the image to XImage */
701 for (y
=0, ofs
=0; y
<image
->height
; y
++) {
702 if (y
<image
->height
-1) {
704 for (x
=0, x1
=(y
+1)*image
->width
*channels
;
707 nerr
[x
++] = ptr
[x1
++];
708 nerr
[x
++] = ptr
[x1
++];
709 nerr
[x
++] = ptr
[x1
++];
713 nerr
[x
++] = ptr
[x1
++];
714 nerr
[x
++] = ptr
[x1
++];
715 nerr
[x
++] = ptr
[x1
++];
717 for (x
=0; x
<image
->width
*3; x
+=3, ofs
++) {
719 if (err
[x
]>0xff) err
[x
]=0xff; else if (err
[x
]<0) err
[x
]=0;
720 if (err
[x
+1]>0xff) err
[x
+1]=0xff; else if (err
[x
+1]<0) err
[x
+1]=0;
721 if (err
[x
+2]>0xff) err
[x
+2]=0xff; else if (err
[x
+2]<0) err
[x
+2]=0;
724 g
= gtable
[err
[x
+1]];
725 b
= btable
[err
[x
+2]];
729 data
[ofs
] = base_pixel
+ pixel
;
732 rer
= err
[x
] - (ctx
->colors
[pixel
].red
>>8);
733 ger
= err
[x
+1] - (ctx
->colors
[pixel
].green
>>8);
734 ber
= err
[x
+2] - (ctx
->colors
[pixel
].blue
>>8);
736 /* distribute error */
737 err
[x
+3*1]+=(rer
*7)/16;
738 err
[x
+1+3*1]+=(ger
*7)/16;
739 err
[x
+2+3*1]+=(ber
*7)/16;
742 nerr
[x
+1]+=(ger
*5)/16;
743 nerr
[x
+2]+=(ber
*5)/16;
746 nerr
[x
-3*1]+=(rer
*3)/16;
747 nerr
[x
-3*1+1]+=(ger
*3)/16;
748 nerr
[x
-3*1+2]+=(ber
*3)/16;
752 nerr
[x
+1+3*1]+=ger
/16;
753 nerr
[x
+2+3*1]+=ber
/16;
755 /* skip to next line */
760 ofs
+= ximg
->image
->bytes_per_line
- image
->width
;
765 ximg
->image
->data
= (char*)data
;
773 image2GrayScale(RContext
*ctx
, RImage
*image
)
776 register int x
, y
, g
;
778 const int cpc
=ctx
->attribs
->colors_per_channel
;
779 unsigned short gmask
;
780 unsigned short *table
;
782 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
785 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
792 data
= (unsigned char *)ximg
->image
->data
;
794 if (ctx
->vclass
== StaticGray
)
795 gmask
= (1<<ctx
->depth
) - 1; /* use all grays */
797 gmask
= cpc
*cpc
*cpc
-1;
799 table
= computeTable(gmask
);
802 RErrorCode
= RERR_NOMEMORY
;
803 RDestroyXImage(ctx
, ximg
);
807 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
810 printf("grayscale match with %d colors per channel\n", cpc
);
812 for (y
=0; y
<image
->height
; y
++) {
813 for (x
=0; x
<image
->width
; x
++) {
815 g
= table
[(*ptr
* 30 + *(ptr
+1) * 59 + *(ptr
+2) * 11)/100];
817 /*data[ofs] = ctx->colors[g].pixel;*/
818 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
827 const int dg
=0xff/gmask
;
830 printf("grayscale dither with %d colors per channel\n", cpc
);
832 gerr
= (short*)malloc((image
->width
+2)*sizeof(short));
833 ngerr
= (short*)malloc((image
->width
+2)*sizeof(short));
834 if (!gerr
|| !ngerr
) {
837 RErrorCode
= RERR_NOMEMORY
;
838 RDestroyXImage(ctx
, ximg
);
841 for (x
=0, y
=0; x
<image
->width
; x
++, y
+=channels
) {
842 gerr
[x
] = (ptr
[y
]*30 + ptr
[y
+1]*59 + ptr
[y
+2]*11)/100;
845 /* convert and dither the image to XImage */
846 for (y
=0; y
<image
->height
; y
++) {
847 if (y
<image
->height
-1) {
849 for (x
=0, x1
=(y
+1)*image
->width
*channels
; x
<image
->width
; x
++, x1
+=channels
) {
850 ngerr
[x
] = (ptr
[x1
]*30 + ptr
[x1
+1]*59 + ptr
[x1
+2]*11)/100;
854 ngerr
[x
] = (ptr
[x1
]*30 + ptr
[x1
+1]*59 + ptr
[x1
+2]*11)/100;
856 for (x
=0; x
<image
->width
; x
++) {
858 if (gerr
[x
]>0xff) gerr
[x
]=0xff; else if (gerr
[x
]<0) gerr
[x
]=0;
862 /*data[ofs] = ctx->colors[g].pixel;*/
863 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
865 ger
= gerr
[x
] - g
*dg
;
867 /* distribute error */
876 /* skip to next line */
884 ximg
->image
->data
= (char*)data
;
891 image2Bitmap(RContext
*ctx
, RImage
*image
, int threshold
)
894 unsigned char *alpha
;
897 ximg
= RCreateXImage(ctx
, 1, image
->width
, image
->height
);
901 alpha
= image
->data
+3;
903 for (y
= 0; y
< image
->height
; y
++) {
904 for (x
= 0; x
< image
->width
; x
++) {
905 XPutPixel(ximg
->image
, x
, y
, (*alpha
<= threshold
? 0 : 1));
915 RConvertImage(RContext
*context
, RImage
*image
, Pixmap
*pixmap
)
922 assert(context
!=NULL
);
924 assert(pixmap
!=NULL
);
926 switch (context
->vclass
) {
931 ximg
= image2TrueColor(context
, image
);
942 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
)
943 ximg
= image2StandardPseudoColor(context
, image
);
945 ximg
= image2PseudoColor(context
, image
);
953 ximg
= image2GrayScale(context
, image
);
962 *pixmap
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
,
963 image
->height
, context
->depth
);
966 if (context
->flags
.use_shared_pixmap
&& ximg
->is_shared
)
967 tmp
= R_CreateXImageMappedPixmap(context
, ximg
);
972 * We have to copy the shm Pixmap into a normal Pixmap because
973 * otherwise, we would have to control when Pixmaps are freed so
974 * that we can detach their shm segments. This is a problem if the
975 * program crash, leaving stale shared memory segments in the
976 * system (lots of them). But with some work, we can optimize
977 * things and remove this XCopyArea. This will require
978 * explicitly freeing all pixmaps when exiting or restarting
981 XCopyArea(context
->dpy
, tmp
, *pixmap
, context
->copy_gc
, 0, 0,
982 image
->width
, image
->height
, 0, 0);
983 XFreePixmap(context
->dpy
, tmp
);
985 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0,
986 image
->width
, image
->height
);
989 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0,
990 image
->width
, image
->height
);
993 RDestroyXImage(context
, ximg
);
999 /* make the gc permanent (create with context creation).
1000 * GC creation is very expensive. altering its properties is not. -Dan
1003 RConvertImageMask(RContext
*context
, RImage
*image
, Pixmap
*pixmap
,
1004 Pixmap
*mask
, int threshold
)
1010 assert(context
!=NULL
);
1011 assert(image
!=NULL
);
1012 assert(pixmap
!=NULL
);
1015 if (!RConvertImage(context
, image
, pixmap
))
1018 if (image
->format
==RRGBFormat
) {
1023 ximg
= image2Bitmap(context
, image
, threshold
);
1028 *mask
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
,
1030 gcv
.foreground
= context
->black
;
1031 gcv
.background
= context
->white
;
1032 gcv
.graphics_exposures
= False
;
1033 gc
= XCreateGC(context
->dpy
, *mask
, GCForeground
|GCBackground
1034 |GCGraphicsExposures
, &gcv
);
1035 RPutXImage(context
, *mask
, gc
, ximg
, 0, 0, 0, 0,
1036 image
->width
, image
->height
);
1037 RDestroyXImage(context
, ximg
);
1038 XFreeGC(context
->dpy
, gc
);
1045 RGetClosestXColor(RContext
*context
, RColor
*color
, XColor
*retColor
)
1047 if (context
->vclass
== TrueColor
) {
1048 unsigned short rmask
, gmask
, bmask
;
1049 unsigned short roffs
, goffs
, boffs
;
1050 unsigned short *rtable
, *gtable
, *btable
;
1052 roffs
= context
->red_offset
;
1053 goffs
= context
->green_offset
;
1054 boffs
= context
->blue_offset
;
1056 rmask
= context
->visual
->red_mask
>> roffs
;
1057 gmask
= context
->visual
->green_mask
>> goffs
;
1058 bmask
= context
->visual
->blue_mask
>> boffs
;
1060 rtable
= computeTable(rmask
);
1061 gtable
= computeTable(gmask
);
1062 btable
= computeTable(bmask
);
1064 retColor
->pixel
= (rtable
[color
->red
]<<roffs
) |
1065 (gtable
[color
->green
]<<goffs
) | (btable
[color
->blue
]<<boffs
);
1067 retColor
->red
= color
->red
<< 8;
1068 retColor
->green
= color
->green
<< 8;
1069 retColor
->blue
= color
->blue
<< 8;
1070 retColor
->flags
= DoRed
|DoGreen
|DoBlue
;
1072 } else if (context
->vclass
== PseudoColor
1073 || context
->vclass
== StaticColor
) {
1075 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
) {
1076 unsigned int *rtable
, *gtable
, *btable
;
1078 rtable
= computeStdTable(context
->std_rgb_map
->red_mult
,
1079 context
->std_rgb_map
->red_max
);
1081 gtable
= computeStdTable(context
->std_rgb_map
->green_mult
,
1082 context
->std_rgb_map
->green_max
);
1084 btable
= computeStdTable(context
->std_rgb_map
->blue_mult
,
1085 context
->std_rgb_map
->blue_max
);
1087 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
1088 RErrorCode
= RERR_NOMEMORY
;
1092 retColor
->pixel
= (rtable
[color
->red
]
1093 + gtable
[color
->green
]
1094 + btable
[color
->blue
]
1095 + context
->std_rgb_map
->base_pixel
) & 0xffffffff;
1096 retColor
->red
= color
->red
<<8;
1097 retColor
->green
= color
->green
<<8;
1098 retColor
->blue
= color
->blue
<<8;
1099 retColor
->flags
= DoRed
|DoGreen
|DoBlue
;
1102 const int cpc
=context
->attribs
->colors_per_channel
;
1103 const unsigned short rmask
= cpc
-1; /* different sizes could be used */
1104 const unsigned short gmask
= rmask
; /* for r,g,b */
1105 const unsigned short bmask
= rmask
;
1106 unsigned short *rtable
, *gtable
, *btable
;
1107 const int cpccpc
= cpc
*cpc
;
1110 rtable
= computeTable(rmask
);
1111 gtable
= computeTable(gmask
);
1112 btable
= computeTable(bmask
);
1114 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
1115 RErrorCode
= RERR_NOMEMORY
;
1118 index
= rtable
[color
->red
]*cpccpc
+ gtable
[color
->green
]*cpc
1119 + btable
[color
->blue
];
1120 *retColor
= context
->colors
[index
];
1123 } else if (context
->vclass
== GrayScale
|| context
->vclass
== StaticGray
) {
1125 const int cpc
= context
->attribs
->colors_per_channel
;
1126 unsigned short gmask
;
1127 unsigned short *table
;
1130 if (context
->vclass
== StaticGray
)
1131 gmask
= (1<<context
->depth
) - 1; /* use all grays */
1133 gmask
= cpc
*cpc
*cpc
-1;
1135 table
= computeTable(gmask
);
1139 index
= table
[(color
->red
*30 + color
->green
*59 + color
->blue
*11)/100];
1141 *retColor
= context
->colors
[index
];
1143 RErrorCode
= RERR_INTERNAL
;