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
29 #include <X11/Xutil.h>
38 extern Pixmap
R_CreateXImageMappedPixmap(RContext
* context
, RXImage
* ximage
);
41 #define NFREE(n) if (n) free(n)
43 #define HAS_ALPHA(I) ((I)->format == RRGBAFormat)
45 typedef struct RConversionTable
{
46 unsigned short table
[256];
49 struct RConversionTable
*next
;
52 typedef struct RStdConversionTable
{
53 unsigned int table
[256];
58 struct RStdConversionTable
*next
;
59 } RStdConversionTable
;
61 static RConversionTable
*conversionTable
= NULL
;
62 static RStdConversionTable
*stdConversionTable
= NULL
;
64 static unsigned short *computeTable(unsigned short mask
)
66 RConversionTable
*tmp
= conversionTable
;
70 if (tmp
->index
== mask
)
78 tmp
= (RConversionTable
*) malloc(sizeof(RConversionTable
));
82 for (i
= 0; i
< 256; i
++)
83 tmp
->table
[i
] = (i
* mask
+ 0x7f) / 0xff;
86 tmp
->next
= conversionTable
;
87 conversionTable
= tmp
;
91 static unsigned int *computeStdTable(unsigned int mult
, unsigned int max
)
93 RStdConversionTable
*tmp
= stdConversionTable
;
97 if (tmp
->mult
== mult
&& tmp
->max
== max
)
105 tmp
= (RStdConversionTable
*) malloc(sizeof(RStdConversionTable
));
109 for (i
= 0; i
< 256; i
++) {
110 tmp
->table
[i
] = (i
* max
) / 0xff * mult
;
115 tmp
->next
= stdConversionTable
;
116 stdConversionTable
= tmp
;
121 /***************************************************************************/
124 convertTrueColor_generic(RXImage
* ximg
, RImage
* image
,
125 signed char *err
, signed char *nerr
,
126 const unsigned short *rtable
,
127 const unsigned short *gtable
,
128 const unsigned short *btable
,
129 const int dr
, const int dg
, const int db
,
130 const unsigned short roffs
, const unsigned short goffs
, const unsigned short boffs
)
136 unsigned char *ptr
= image
->data
;
137 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
139 /* convert and dither the image to XImage */
140 for (y
= 0; y
< image
->height
; y
++) {
144 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
147 pixel
= *ptr
+ err
[x
];
150 else if (pixel
> 0xff)
154 rer
= pixel
- r
* dr
;
157 pixel
= *(ptr
+ 1) + err
[x
+ 1];
160 else if (pixel
> 0xff)
164 ger
= pixel
- g
* dg
;
167 pixel
= *(ptr
+ 2) + err
[x
+ 2];
170 else if (pixel
> 0xff)
174 ber
= pixel
- b
* db
;
176 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
177 XPutPixel(ximg
->image
, x
, y
, pixel
);
179 /* distribute error */
185 err
[x
+ 1 + 3 * 1] += g
;
186 err
[x
+ 2 + 3 * 1] += b
;
192 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
193 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
194 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
196 /* skip to next line */
202 /* redither the 1st line to distribute error better */
208 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
211 pixel
= *ptr
+ err
[x
];
214 else if (pixel
> 0xff)
218 rer
= pixel
- r
* dr
;
221 pixel
= *(ptr
+ 1) + err
[x
+ 1];
224 else if (pixel
> 0xff)
228 ger
= pixel
- g
* dg
;
231 pixel
= *(ptr
+ 2) + err
[x
+ 2];
234 else if (pixel
> 0xff)
238 ber
= pixel
- b
* db
;
240 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
241 XPutPixel(ximg
->image
, x
, y
, pixel
);
243 /* distribute error */
249 err
[x
+ 1 + 3 * 1] += g
;
250 err
[x
+ 2 + 3 * 1] += b
;
256 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
257 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
258 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
262 static RXImage
*image2TrueColor(RContext
* ctx
, RImage
* image
)
265 unsigned short rmask
, gmask
, bmask
;
266 unsigned short roffs
, goffs
, boffs
;
267 unsigned short *rtable
, *gtable
, *btable
;
268 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
270 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
275 roffs
= ctx
->red_offset
;
276 goffs
= ctx
->green_offset
;
277 boffs
= ctx
->blue_offset
;
279 rmask
= ctx
->visual
->red_mask
>> roffs
;
280 gmask
= ctx
->visual
->green_mask
>> goffs
;
281 bmask
= ctx
->visual
->blue_mask
>> boffs
;
283 rtable
= computeTable(rmask
);
284 gtable
= computeTable(gmask
);
285 btable
= computeTable(bmask
);
287 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
288 RErrorCode
= RERR_NOMEMORY
;
289 RDestroyXImage(ctx
, ximg
);
293 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
297 unsigned char *ptr
= image
->data
;
301 fputs("true color match\n", stderr
);
303 if (rmask
== 0xff && gmask
== 0xff && bmask
== 0xff) {
304 for (y
= 0; y
< image
->height
; y
++) {
305 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
307 pixel
= (*(ptr
) << roffs
) | (*(ptr
+ 1) << goffs
) | (*(ptr
+ 2) << boffs
);
308 XPutPixel(ximg
->image
, x
, y
, pixel
);
312 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
313 for (x
= 0; x
< image
->width
; x
++, ofs
+= channels
- 3) {
315 r
= rtable
[ptr
[ofs
++]];
316 g
= gtable
[ptr
[ofs
++]];
317 b
= btable
[ptr
[ofs
++]];
318 pixel
= (r
<< roffs
) | (g
<< goffs
) | (b
<< boffs
);
319 XPutPixel(ximg
->image
, x
, y
, pixel
);
325 const int dr
= 0xff / rmask
;
326 const int dg
= 0xff / gmask
;
327 const int db
= 0xff / bmask
;
330 fputs("true color dither\n", stderr
);
336 int ch
= (HAS_ALPHA(image
) ? 4 : 3);
338 err
= malloc(ch
* (image
->width
+ 2));
339 nerr
= malloc(ch
* (image
->width
+ 2));
343 RErrorCode
= RERR_NOMEMORY
;
344 RDestroyXImage(ctx
, ximg
);
348 memset(err
, 0, ch
* (image
->width
+ 2));
349 memset(nerr
, 0, ch
* (image
->width
+ 2));
351 convertTrueColor_generic(ximg
, image
, err
, nerr
,
352 rtable
, gtable
, btable
, dr
, dg
, db
, roffs
, goffs
, boffs
);
362 /***************************************************************************/
365 convertPseudoColor_to_8(RXImage
* ximg
, RImage
* image
,
366 signed char *err
, signed char *nerr
,
367 const unsigned short *rtable
,
368 const unsigned short *gtable
,
369 const unsigned short *btable
,
370 const int dr
, const int dg
, const int db
, unsigned long *pixels
, int cpc
)
376 unsigned char *ptr
= image
->data
;
377 unsigned char *optr
= (unsigned char *)ximg
->image
->data
;
378 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
379 int cpcpc
= cpc
* cpc
;
381 /* convert and dither the image to XImage */
382 for (y
= 0; y
< image
->height
; y
++) {
386 for (x
= 0; x
< image
->width
* 3; x
+= 3, ptr
+= channels
) {
389 pixel
= *ptr
+ err
[x
];
392 else if (pixel
> 0xff)
396 rer
= pixel
- r
* dr
;
399 pixel
= *(ptr
+ 1) + err
[x
+ 1];
402 else if (pixel
> 0xff)
406 ger
= pixel
- g
* dg
;
409 pixel
= *(ptr
+ 2) + err
[x
+ 2];
412 else if (pixel
> 0xff)
416 ber
= pixel
- b
* db
;
418 *optr
++ = pixels
[r
* cpcpc
+ g
* cpc
+ b
];
420 /* distribute error */
427 err
[x
+ 1 + 3 * 1] += g
;
428 err
[x
+ 2 + 3 * 1] += b
;
434 nerr
[x
+ 3 * 1] = rer
- 2 * r
;
435 nerr
[x
+ 1 + 3 * 1] = ger
- 2 * g
;
436 nerr
[x
+ 2 + 3 * 1] = ber
- 2 * b
;
438 /* skip to next line */
443 optr
+= ximg
->image
->bytes_per_line
- image
->width
;
447 static RXImage
*image2PseudoColor(RContext
* ctx
, RImage
* image
)
450 register int x
, y
, r
, g
, b
;
453 const int cpc
= ctx
->attribs
->colors_per_channel
;
454 const unsigned short rmask
= cpc
- 1; /* different sizes could be used */
455 const unsigned short gmask
= rmask
; /* for r,g,b */
456 const unsigned short bmask
= rmask
;
457 unsigned short *rtable
, *gtable
, *btable
;
458 const int cpccpc
= cpc
* cpc
;
459 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
461 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
468 /* Tables are same at the moment because rmask==gmask==bmask. */
469 rtable
= computeTable(rmask
);
470 gtable
= computeTable(gmask
);
471 btable
= computeTable(bmask
);
473 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
474 RErrorCode
= RERR_NOMEMORY
;
475 RDestroyXImage(ctx
, ximg
);
479 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
482 fprintf(stderr
, "pseudo color match with %d colors per channel\n", cpc
);
484 for (y
= 0; y
< image
->height
; y
++) {
485 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
- 3) {
490 pixel
= r
* cpccpc
+ g
* cpc
+ b
;
491 /*data[ofs] = ctx->colors[pixel].pixel; */
492 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[pixel
].pixel
);
499 const int dr
= 0xff / rmask
;
500 const int dg
= 0xff / gmask
;
501 const int db
= 0xff / bmask
;
504 fprintf(stderr
, "pseudo color dithering with %d colors per channel\n", cpc
);
506 err
= malloc(4 * (image
->width
+ 3));
507 nerr
= malloc(4 * (image
->width
+ 3));
511 RErrorCode
= RERR_NOMEMORY
;
512 RDestroyXImage(ctx
, ximg
);
515 memset(err
, 0, 4 * (image
->width
+ 3));
516 memset(nerr
, 0, 4 * (image
->width
+ 3));
518 convertPseudoColor_to_8(ximg
, image
, err
+ 4, nerr
+ 4,
519 rtable
, gtable
, btable
, dr
, dg
, db
, ctx
->pixels
, cpc
);
529 * For standard colormap
531 static RXImage
*image2StandardPseudoColor(RContext
* ctx
, RImage
* image
)
534 register int x
, y
, r
, g
, b
;
538 unsigned int *rtable
, *gtable
, *btable
;
539 unsigned int base_pixel
= ctx
->std_rgb_map
->base_pixel
;
540 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
542 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
549 data
= (unsigned char *)ximg
->image
->data
;
551 rtable
= computeStdTable(ctx
->std_rgb_map
->red_mult
, ctx
->std_rgb_map
->red_max
);
553 gtable
= computeStdTable(ctx
->std_rgb_map
->green_mult
, ctx
->std_rgb_map
->green_max
);
555 btable
= computeStdTable(ctx
->std_rgb_map
->blue_mult
, ctx
->std_rgb_map
->blue_max
);
557 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
558 RErrorCode
= RERR_NOMEMORY
;
559 RDestroyXImage(ctx
, ximg
);
563 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
564 for (y
= 0; y
< image
->height
; y
++) {
565 for (x
= 0; x
< image
->width
; x
++, ptr
+= channels
) {
567 pixel
= (rtable
[*ptr
] + gtable
[*(ptr
+ 1)]
568 + btable
[*(ptr
+ 2)] + base_pixel
) & 0xffffffff;
570 XPutPixel(ximg
->image
, x
, y
, pixel
);
575 signed short *err
, *nerr
;
581 fprintf(stderr
, "pseudo color dithering with %d colors per channel\n",
582 ctx
->attribs
->colors_per_channel
);
584 err
= (short *)malloc(3 * (image
->width
+ 2) * sizeof(short));
585 nerr
= (short *)malloc(3 * (image
->width
+ 2) * sizeof(short));
589 RErrorCode
= RERR_NOMEMORY
;
590 RDestroyXImage(ctx
, ximg
);
593 for (x
= 0, x1
= 0; x
< image
->width
* 3; x1
+= channels
- 3) {
594 err
[x
++] = ptr
[x1
++];
595 err
[x
++] = ptr
[x1
++];
596 err
[x
++] = ptr
[x1
++];
598 err
[x
] = err
[x
+ 1] = err
[x
+ 2] = 0;
599 /* convert and dither the image to XImage */
600 for (y
= 0, ofs
= 0; y
< image
->height
; y
++) {
601 if (y
< image
->height
- 1) {
603 for (x
= 0, x1
= (y
+ 1) * image
->width
* channels
;
604 x
< image
->width
* 3; x1
+= channels
- 3) {
605 nerr
[x
++] = ptr
[x1
++];
606 nerr
[x
++] = ptr
[x1
++];
607 nerr
[x
++] = ptr
[x1
++];
611 nerr
[x
++] = ptr
[x1
++];
612 nerr
[x
++] = ptr
[x1
++];
613 nerr
[x
++] = ptr
[x1
++];
615 for (x
= 0; x
< image
->width
* 3; x
+= 3, ofs
++) {
621 if (err
[x
+ 1] > 0xff)
623 else if (err
[x
+ 1] < 0)
625 if (err
[x
+ 2] > 0xff)
627 else if (err
[x
+ 2] < 0)
631 g
= gtable
[err
[x
+ 1]];
632 b
= btable
[err
[x
+ 2]];
636 data
[ofs
] = base_pixel
+ pixel
;
639 rer
= err
[x
] - (ctx
->colors
[pixel
].red
>> 8);
640 ger
= err
[x
+ 1] - (ctx
->colors
[pixel
].green
>> 8);
641 ber
= err
[x
+ 2] - (ctx
->colors
[pixel
].blue
>> 8);
643 /* distribute error */
644 err
[x
+ 3 * 1] += (rer
* 7) / 16;
645 err
[x
+ 1 + 3 * 1] += (ger
* 7) / 16;
646 err
[x
+ 2 + 3 * 1] += (ber
* 7) / 16;
648 nerr
[x
] += (rer
* 5) / 16;
649 nerr
[x
+ 1] += (ger
* 5) / 16;
650 nerr
[x
+ 2] += (ber
* 5) / 16;
653 nerr
[x
- 3 * 1] += (rer
* 3) / 16;
654 nerr
[x
- 3 * 1 + 1] += (ger
* 3) / 16;
655 nerr
[x
- 3 * 1 + 2] += (ber
* 3) / 16;
658 nerr
[x
+ 3 * 1] += rer
/ 16;
659 nerr
[x
+ 1 + 3 * 1] += ger
/ 16;
660 nerr
[x
+ 2 + 3 * 1] += ber
/ 16;
662 /* skip to next line */
667 ofs
+= ximg
->image
->bytes_per_line
- image
->width
;
672 ximg
->image
->data
= (char *)data
;
677 static RXImage
*image2GrayScale(RContext
* ctx
, RImage
* image
)
680 register int x
, y
, g
;
682 const int cpc
= ctx
->attribs
->colors_per_channel
;
683 unsigned short gmask
;
684 unsigned short *table
;
686 int channels
= (HAS_ALPHA(image
) ? 4 : 3);
688 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
695 data
= (unsigned char *)ximg
->image
->data
;
697 if (ctx
->vclass
== StaticGray
)
698 gmask
= (1 << ctx
->depth
) - 1; /* use all grays */
700 gmask
= cpc
* cpc
* cpc
- 1;
702 table
= computeTable(gmask
);
705 RErrorCode
= RERR_NOMEMORY
;
706 RDestroyXImage(ctx
, ximg
);
710 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
713 fprintf(stderr
, "grayscale match with %d colors per channel\n", cpc
);
715 for (y
= 0; y
< image
->height
; y
++) {
716 for (x
= 0; x
< image
->width
; x
++) {
718 g
= table
[(*ptr
* 30 + *(ptr
+ 1) * 59 + *(ptr
+ 2) * 11) / 100];
720 /*data[ofs] = ctx->colors[g].pixel; */
721 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
730 const int dg
= 0xff / gmask
;
733 fprintf(stderr
, "grayscale dither with %d colors per channel\n", cpc
);
735 gerr
= (short *)malloc((image
->width
+ 2) * sizeof(short));
736 ngerr
= (short *)malloc((image
->width
+ 2) * sizeof(short));
737 if (!gerr
|| !ngerr
) {
740 RErrorCode
= RERR_NOMEMORY
;
741 RDestroyXImage(ctx
, ximg
);
744 for (x
= 0, y
= 0; x
< image
->width
; x
++, y
+= channels
) {
745 gerr
[x
] = (ptr
[y
] * 30 + ptr
[y
+ 1] * 59 + ptr
[y
+ 2] * 11) / 100;
748 /* convert and dither the image to XImage */
749 for (y
= 0; y
< image
->height
; y
++) {
750 if (y
< image
->height
- 1) {
752 for (x
= 0, x1
= (y
+ 1) * image
->width
* channels
; x
< image
->width
;
753 x
++, x1
+= channels
) {
754 ngerr
[x
] = (ptr
[x1
] * 30 + ptr
[x1
+ 1] * 59 + ptr
[x1
+ 2] * 11) / 100;
758 ngerr
[x
] = (ptr
[x1
] * 30 + ptr
[x1
+ 1] * 59 + ptr
[x1
+ 2] * 11) / 100;
760 for (x
= 0; x
< image
->width
; x
++) {
764 else if (gerr
[x
] < 0)
769 /*data[ofs] = ctx->colors[g].pixel; */
770 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
772 ger
= gerr
[x
] - g
* dg
;
774 /* distribute error */
781 ngerr
[x
+ 1] += ger
- 2 * g
;
783 /* skip to next line */
791 ximg
->image
->data
= (char *)data
;
796 static RXImage
*image2Bitmap(RContext
* ctx
, RImage
* image
, int threshold
)
799 unsigned char *alpha
;
802 ximg
= RCreateXImage(ctx
, 1, image
->width
, image
->height
);
806 alpha
= image
->data
+ 3;
808 for (y
= 0; y
< image
->height
; y
++) {
809 for (x
= 0; x
< image
->width
; x
++) {
810 XPutPixel(ximg
->image
, x
, y
, (*alpha
<= threshold
? 0 : 1));
818 int RConvertImage(RContext
* context
, RImage
* image
, Pixmap
* pixmap
)
820 RXImage
*ximg
= NULL
;
825 assert(context
!= NULL
);
826 assert(image
!= NULL
);
827 assert(pixmap
!= NULL
);
829 switch (context
->vclass
) {
831 ximg
= image2TrueColor(context
, image
);
836 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
)
837 ximg
= image2StandardPseudoColor(context
, image
);
839 ximg
= image2PseudoColor(context
, image
);
844 ximg
= image2GrayScale(context
, image
);
852 *pixmap
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
, image
->height
, context
->depth
);
855 if (context
->flags
.use_shared_pixmap
&& ximg
->is_shared
)
856 tmp
= R_CreateXImageMappedPixmap(context
, ximg
);
861 * We have to copy the shm Pixmap into a normal Pixmap because
862 * otherwise, we would have to control when Pixmaps are freed so
863 * that we can detach their shm segments. This is a problem if the
864 * program crash, leaving stale shared memory segments in the
865 * system (lots of them). But with some work, we can optimize
866 * things and remove this XCopyArea. This will require
867 * explicitly freeing all pixmaps when exiting or restarting
870 XCopyArea(context
->dpy
, tmp
, *pixmap
, context
->copy_gc
, 0, 0, image
->width
, image
->height
, 0, 0);
871 XFreePixmap(context
->dpy
, tmp
);
873 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
876 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
879 RDestroyXImage(context
, ximg
);
884 /* make the gc permanent (create with context creation).
885 * GC creation is very expensive. altering its properties is not. -Dan
887 int RConvertImageMask(RContext
* context
, RImage
* image
, Pixmap
* pixmap
, Pixmap
* mask
, int threshold
)
891 RXImage
*ximg
= NULL
;
893 assert(context
!= NULL
);
894 assert(image
!= NULL
);
895 assert(pixmap
!= NULL
);
896 assert(mask
!= NULL
);
898 if (!RConvertImage(context
, image
, pixmap
))
901 if (image
->format
== RRGBFormat
) {
906 ximg
= image2Bitmap(context
, image
, threshold
);
911 *mask
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
, image
->height
, 1);
912 gcv
.foreground
= context
->black
;
913 gcv
.background
= context
->white
;
914 gcv
.graphics_exposures
= False
;
915 gc
= XCreateGC(context
->dpy
, *mask
, GCForeground
| GCBackground
| GCGraphicsExposures
, &gcv
);
916 RPutXImage(context
, *mask
, gc
, ximg
, 0, 0, 0, 0, image
->width
, image
->height
);
917 RDestroyXImage(context
, ximg
);
918 XFreeGC(context
->dpy
, gc
);
923 Bool
RGetClosestXColor(RContext
* context
, RColor
* color
, XColor
* retColor
)
925 if (context
->vclass
== TrueColor
) {
926 unsigned short rmask
, gmask
, bmask
;
927 unsigned short roffs
, goffs
, boffs
;
928 unsigned short *rtable
, *gtable
, *btable
;
930 roffs
= context
->red_offset
;
931 goffs
= context
->green_offset
;
932 boffs
= context
->blue_offset
;
934 rmask
= context
->visual
->red_mask
>> roffs
;
935 gmask
= context
->visual
->green_mask
>> goffs
;
936 bmask
= context
->visual
->blue_mask
>> boffs
;
938 rtable
= computeTable(rmask
);
939 gtable
= computeTable(gmask
);
940 btable
= computeTable(bmask
);
942 retColor
->pixel
= (rtable
[color
->red
] << roffs
) |
943 (gtable
[color
->green
] << goffs
) | (btable
[color
->blue
] << boffs
);
945 retColor
->red
= color
->red
<< 8;
946 retColor
->green
= color
->green
<< 8;
947 retColor
->blue
= color
->blue
<< 8;
948 retColor
->flags
= DoRed
| DoGreen
| DoBlue
;
950 } else if (context
->vclass
== PseudoColor
|| context
->vclass
== StaticColor
) {
952 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
) {
953 unsigned int *rtable
, *gtable
, *btable
;
955 rtable
= computeStdTable(context
->std_rgb_map
->red_mult
, context
->std_rgb_map
->red_max
);
957 gtable
= computeStdTable(context
->std_rgb_map
->green_mult
,
958 context
->std_rgb_map
->green_max
);
960 btable
= computeStdTable(context
->std_rgb_map
->blue_mult
, context
->std_rgb_map
->blue_max
);
962 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
963 RErrorCode
= RERR_NOMEMORY
;
967 retColor
->pixel
= (rtable
[color
->red
]
968 + gtable
[color
->green
]
969 + btable
[color
->blue
]
970 + context
->std_rgb_map
->base_pixel
) & 0xffffffff;
971 retColor
->red
= color
->red
<< 8;
972 retColor
->green
= color
->green
<< 8;
973 retColor
->blue
= color
->blue
<< 8;
974 retColor
->flags
= DoRed
| DoGreen
| DoBlue
;
977 const int cpc
= context
->attribs
->colors_per_channel
;
978 const unsigned short rmask
= cpc
- 1; /* different sizes could be used */
979 const unsigned short gmask
= rmask
; /* for r,g,b */
980 const unsigned short bmask
= rmask
;
981 unsigned short *rtable
, *gtable
, *btable
;
982 const int cpccpc
= cpc
* cpc
;
985 rtable
= computeTable(rmask
);
986 gtable
= computeTable(gmask
);
987 btable
= computeTable(bmask
);
989 if (rtable
== NULL
|| gtable
== NULL
|| btable
== NULL
) {
990 RErrorCode
= RERR_NOMEMORY
;
993 index
= rtable
[color
->red
] * cpccpc
+ gtable
[color
->green
] * cpc
+ btable
[color
->blue
];
994 *retColor
= context
->colors
[index
];
997 } else if (context
->vclass
== GrayScale
|| context
->vclass
== StaticGray
) {
999 const int cpc
= context
->attribs
->colors_per_channel
;
1000 unsigned short gmask
;
1001 unsigned short *table
;
1004 if (context
->vclass
== StaticGray
)
1005 gmask
= (1 << context
->depth
) - 1; /* use all grays */
1007 gmask
= cpc
* cpc
* cpc
- 1;
1009 table
= computeTable(gmask
);
1013 index
= table
[(color
->red
* 30 + color
->green
* 59 + color
->blue
* 11) / 100];
1015 *retColor
= context
->colors
[index
];
1017 RErrorCode
= RERR_INTERNAL
;