1 /* convert.c - convert RImage to Pixmap
3 * Raster graphics library
5 * Copyright (c) 1997-2000 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.
25 #include <X11/Xutil.h>
39 extern Pixmap
R_CreateXImageMappedPixmap(RContext
*context
, RXImage
*ximage
);
46 extern int x86_check_mmx();
48 extern void x86_TrueColor_32_to_16(unsigned char *image
,
49 unsigned short *ximage
,
50 short *err
, short *nerr
,
51 short *rtable
, short *gtable
,
53 int dr
, int dg
, int db
,
57 int width
, int height
,
66 typedef struct RConversionTable
{
67 unsigned short table
[256];
70 struct RConversionTable
*next
;
74 typedef struct RStdConversionTable
{
75 unsigned int table
[256];
80 struct RStdConversionTable
*next
;
81 } RStdConversionTable
;
85 static RConversionTable
*conversionTable
= NULL
;
86 static RStdConversionTable
*stdConversionTable
= NULL
;
89 static unsigned short*
90 computeTable(unsigned short mask
)
92 RConversionTable
*tmp
= conversionTable
;
96 if (tmp
->index
== mask
)
104 tmp
= (RConversionTable
*)malloc(sizeof(RConversionTable
));
109 tmp
->table
[i
] = (i
*mask
+ 0x7f)/0xff;
112 tmp
->next
= conversionTable
;
113 conversionTable
= tmp
;
119 computeStdTable(unsigned int mult
, unsigned int max
)
121 RStdConversionTable
*tmp
= stdConversionTable
;
125 if (tmp
->mult
== mult
&& tmp
->max
== max
)
133 tmp
= (RStdConversionTable
*)malloc(sizeof(RStdConversionTable
));
137 for (i
=0; i
<256; i
++) {
138 tmp
->table
[i
] = (i
*max
)/0xff * mult
;
143 tmp
->next
= stdConversionTable
;
144 stdConversionTable
= tmp
;
149 /***************************************************************************/
153 convertTrueColor_generic(RXImage
*ximg
, RImage
*image
,
154 char *err
, char *nerr
,
158 const int dr
, const int dg
, const int db
,
159 const unsigned short roffs
,
160 const unsigned short goffs
,
161 const unsigned short boffs
)
167 unsigned char *ptr
= image
->data
;
168 int channels
= image
->format
== RRGBAFormat
? 4 : 3;
170 /* convert and dither the image to XImage */
171 for (y
=0; y
<image
->height
; y
++) {
175 for (x
=0; x
<image
->width
; x
++, ptr
+=channels
) {
178 pixel
= *ptr
+ err
[x
];
179 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
185 pixel
= *(ptr
+1) + err
[x
+1];
186 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
192 pixel
= *(ptr
+2) + err
[x
+2];
193 if (pixel
<0) pixel
=0; else if (pixel
>0xff) pixel
=0xff;
199 pixel
= (r
<<roffs
) | (g
<<goffs
) | (b
<<boffs
);
200 XPutPixel(ximg
->image
, x
, y
, pixel
);
202 /* distribute error */
216 nerr
[x
+1+3*1]=ger
-2*g
;
217 nerr
[x
+2+3*1]=ber
-2*b
;
219 /* skip to next line */
230 image2TrueColor(RContext
*ctx
, RImage
*image
)
233 unsigned short rmask
, gmask
, bmask
;
234 unsigned short roffs
, goffs
, boffs
;
235 unsigned short *rtable
, *gtable
, *btable
;
236 int channels
= (image
->format
== RRGBAFormat
? 4 : 3);
238 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
243 roffs
= ctx
->red_offset
;
244 goffs
= ctx
->green_offset
;
245 boffs
= ctx
->blue_offset
;
247 rmask
= ctx
->visual
->red_mask
>> roffs
;
248 gmask
= ctx
->visual
->green_mask
>> goffs
;
249 bmask
= ctx
->visual
->blue_mask
>> boffs
;
251 rtable
= computeTable(rmask
);
252 gtable
= computeTable(gmask
);
253 btable
= computeTable(bmask
);
255 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
256 RErrorCode
= RERR_NOMEMORY
;
257 RDestroyXImage(ctx
, ximg
);
262 if (ctx
->attribs
->render_mode
==RBestMatchRendering
) {
266 unsigned char *ptr
= image
->data
;
270 puts("true color match");
272 for (y
=0, ofs
=0; y
< image
->height
; y
++) {
273 for (x
=0; x
< image
->width
; x
++, ofs
+=channels
-3) {
275 r
= rtable
[ptr
[ofs
++]];
276 g
= gtable
[ptr
[ofs
++]];
277 b
= btable
[ptr
[ofs
++]];
278 pixel
= (r
<<roffs
) | (g
<<goffs
) | (b
<<boffs
);
279 XPutPixel(ximg
->image
, x
, y
, pixel
);
284 const int dr
=0xff/rmask
;
285 const int dg
=0xff/gmask
;
286 const int db
=0xff/bmask
;
289 puts("true color dither");
297 if (ctx
->depth
== 16 && image
->format
== RRGBAFormat
298 && x86_check_mmx()) {
302 err
= malloc(8*(image
->width
+3));
303 nerr
= malloc(8*(image
->width
+3));
307 RErrorCode
= RERR_NOMEMORY
;
308 RDestroyXImage(ctx
, ximg
);
311 memset(err
, 0, 8*(image
->width
+3));
312 memset(nerr
, 0, 8*(image
->width
+3));
314 x86_TrueColor_32_to_16(image
->data
,
315 (unsigned short*)ximg
->image
->data
,
317 rtable
, gtable
, btable
,
320 image
->width
, image
->height
,
321 ximg
->image
->bytes_per_line
- 2*image
->width
);
326 #endif /* ASM_X86_MMX */
330 int ch
= image
->format
== RRGBAFormat
? 4 : 3;
332 err
= malloc(ch
*(image
->width
+2));
333 nerr
= malloc(ch
*(image
->width
+2));
337 RErrorCode
= RERR_NOMEMORY
;
338 RDestroyXImage(ctx
, ximg
);
342 memset(err
, 0, ch
*(image
->width
+2));
343 memset(nerr
, 0, ch
*(image
->width
+2));
345 convertTrueColor_generic(ximg
, image
, err
, nerr
,
346 rtable
, gtable
, btable
,
347 dr
, dg
, db
, roffs
, goffs
, boffs
);
362 /***************************************************************************/
366 image2PseudoColor(RContext
*ctx
, RImage
*image
)
369 register int x
, y
, r
, g
, b
;
372 const int cpc
=ctx
->attribs
->colors_per_channel
;
373 const unsigned short rmask
= cpc
-1; /* different sizes could be used */
374 const unsigned short gmask
= rmask
; /* for r,g,b */
375 const unsigned short bmask
= rmask
;
376 unsigned short *rtable
, *gtable
, *btable
;
377 const int cpccpc
= cpc
*cpc
;
380 int channels
= image
->format
== RRGBAFormat
? 4 : 3;
381 /*register unsigned char maxrgb = 0xff;*/
383 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
390 data
= (unsigned char *)ximg
->image
->data
;
392 /* Tables are same at the moment because rmask==gmask==bmask. */
393 rtable
= computeTable(rmask
);
394 gtable
= computeTable(gmask
);
395 btable
= computeTable(bmask
);
397 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
398 RErrorCode
= RERR_NOMEMORY
;
399 RDestroyXImage(ctx
, ximg
);
403 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
406 printf("pseudo color match with %d colors per channel\n", cpc
);
408 for (y
=0; y
<image
->height
; y
++) {
409 for (x
=0; x
<image
->width
; x
++, ptr
+=channels
-1) {
414 pixel
= r
*cpccpc
+ g
*cpc
+ b
;
415 /*data[ofs] = ctx->colors[pixel].pixel;*/
416 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[pixel
].pixel
);
425 const int dr
=0xff/rmask
;
426 const int dg
=0xff/gmask
;
427 const int db
=0xff/bmask
;
431 printf("pseudo color dithering with %d colors per channel\n", cpc
);
433 err
= (short*)malloc(3*(image
->width
+2)*sizeof(short));
434 nerr
= (short*)malloc(3*(image
->width
+2)*sizeof(short));
438 RErrorCode
= RERR_NOMEMORY
;
439 RDestroyXImage(ctx
, ximg
);
442 for (x
=0, i
=0; x
<image
->width
*3; x
+=channels
-3) {
447 err
[x
++] = err
[x
++] = err
[x
++] = 0;
448 /* convert and dither the image to XImage */
449 for (ofs
=0, y
=0; y
<image
->height
; y
++) {
450 if (y
<image
->height
-1) {
452 for (x
=0, x1
=((y
+1)*image
->width
)*channels
;
453 x
<image
->width
*3; x1
+=channels
-3) {
454 nerr
[x
++] = ptr
[x1
++];
455 nerr
[x
++] = ptr
[x1
++];
456 nerr
[x
++] = ptr
[x1
++];
460 nerr
[x
++] = ptr
[x1
++];
461 nerr
[x
++] = ptr
[x1
++];
462 nerr
[x
++] = ptr
[x1
++];
464 for (x
=0; x
<image
->width
*3; x
+=3, ofs
++) {
466 if (err
[x
]>0xff) err
[x
]=0xff; else if (err
[x
]<0) err
[x
]=0;
467 if (err
[x
+1]>0xff) err
[x
+1]=0xff; else if (err
[x
+1]<0) err
[x
+1]=0;
468 if (err
[x
+2]>0xff) err
[x
+2]=0xff; else if (err
[x
+2]<0) err
[x
+2]=0;
471 g
= gtable
[err
[x
+1]];
472 b
= btable
[err
[x
+2]];
474 pixel
= r
*cpccpc
+ g
*cpc
+ b
;
475 data
[ofs
] = ctx
->colors
[pixel
].pixel
;
479 ger
= err
[x
+1] - g
*dg
;
480 ber
= err
[x
+2] - b
*db
;
482 /* distribute error */
483 err
[x
+3*1]+=(rer
*7)/16;
484 err
[x
+1+3*1]+=(ger
*7)/16;
485 err
[x
+2+3*1]+=(ber
*7)/16;
492 nerr
[x
-3*1]+=(rer
*3)/16;
493 nerr
[x
-(3*1)+1]+=(ger
*3)/16;
494 nerr
[x
-(3*1)+2]+=(ber
*3)/16;
498 nerr
[x
+1+3*1]+=ger
/16;
499 nerr
[x
+2+3*1]+=ber
/16;
501 /* skip to next line */
506 ofs
+= ximg
->image
->bytes_per_line
- image
->width
;
511 ximg
->image
->data
= (char*)data
;
518 * For standard colormap
521 image2StandardPseudoColor(RContext
*ctx
, RImage
*image
)
524 register int x
, y
, r
, g
, b
;
528 unsigned int *rtable
, *gtable
, *btable
;
529 unsigned int base_pixel
= ctx
->std_rgb_map
->base_pixel
;
530 int channels
= image
->format
== RRGBAFormat
? 4 : 3;
531 /*register unsigned char maxrgb = 0xff;*/
533 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
540 data
= (unsigned char *)ximg
->image
->data
;
543 rtable
= computeStdTable(ctx
->std_rgb_map
->red_mult
,
544 ctx
->std_rgb_map
->red_max
);
546 gtable
= computeStdTable(ctx
->std_rgb_map
->green_mult
,
547 ctx
->std_rgb_map
->green_max
);
549 btable
= computeStdTable(ctx
->std_rgb_map
->blue_mult
,
550 ctx
->std_rgb_map
->blue_max
);
552 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
553 RErrorCode
= RERR_NOMEMORY
;
554 RDestroyXImage(ctx
, ximg
);
559 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
560 for (y
=0; y
<image
->height
; y
++) {
561 for (x
=0; x
<image
->width
; x
++, ptr
+=channels
-3) {
563 pixel
= (rtable
[*ptr
++] + gtable
[*ptr
++]
564 + btable
[*ptr
++] + base_pixel
) & 0xffffffff;
566 XPutPixel(ximg
->image
, x
, y
, pixel
);
577 printf("pseudo color dithering with %d colors per channel\n", cpc
);
579 err
= (short*)malloc(3*(image
->width
+2)*sizeof(short));
580 nerr
= (short*)malloc(3*(image
->width
+2)*sizeof(short));
584 RErrorCode
= RERR_NOMEMORY
;
585 RDestroyXImage(ctx
, ximg
);
588 for (x
=0, x1
=0; x
<image
->width
*3; x1
+=channels
-3) {
589 err
[x
++] = ptr
[x1
++];
590 err
[x
++] = ptr
[x1
++];
591 err
[x
++] = ptr
[x1
++];
593 err
[x
++] = err
[x
++] = err
[x
++] = 0;
594 /* convert and dither the image to XImage */
595 for (y
=0, ofs
=0; y
<image
->height
; y
++) {
596 if (y
<image
->height
-1) {
598 for (x
=0, x1
=(y
+1)*image
->width
*channels
;
601 nerr
[x
++] = ptr
[x1
++];
602 nerr
[x
++] = ptr
[x1
++];
603 nerr
[x
++] = ptr
[x1
++];
607 nerr
[x
++] = ptr
[x1
++];
608 nerr
[x
++] = ptr
[x1
++];
609 nerr
[x
++] = ptr
[x1
++];
611 for (x
=0; x
<image
->width
*3; x
+=3, ofs
++) {
613 if (err
[x
]>0xff) err
[x
]=0xff; else if (err
[x
]<0) err
[x
]=0;
614 if (err
[x
+1]>0xff) err
[x
+1]=0xff; else if (err
[x
+1]<0) err
[x
+1]=0;
615 if (err
[x
+2]>0xff) err
[x
+2]=0xff; else if (err
[x
+2]<0) err
[x
+2]=0;
618 g
= gtable
[err
[x
+1]];
619 b
= btable
[err
[x
+2]];
623 data
[ofs
] = base_pixel
+ pixel
;
625 XPutPixel(ximg->image, x, y, pixel+base_pixel);
629 rer
= err
[x
] - (ctx
->colors
[pixel
].red
>>8);
630 ger
= err
[x
+1] - (ctx
->colors
[pixel
].green
>>8);
631 ber
= err
[x
+2] - (ctx
->colors
[pixel
].blue
>>8);
633 /* distribute error */
634 err
[x
+3*1]+=(rer
*7)/16;
635 err
[x
+1+3*1]+=(ger
*7)/16;
636 err
[x
+2+3*1]+=(ber
*7)/16;
639 nerr
[x
+1]+=(ger
*5)/16;
640 nerr
[x
+2]+=(ber
*5)/16;
643 nerr
[x
-3*1]+=(rer
*3)/16;
644 nerr
[x
-3*1+1]+=(ger
*3)/16;
645 nerr
[x
-3*1+2]+=(ber
*3)/16;
649 nerr
[x
+1+3*1]+=ger
/16;
650 nerr
[x
+2+3*1]+=ber
/16;
652 /* skip to next line */
657 ofs
+= ximg
->image
->bytes_per_line
- image
->width
;
662 ximg
->image
->data
= (char*)data
;
670 image2GrayScale(RContext
*ctx
, RImage
*image
)
673 register int x
, y
, g
;
675 const int cpc
=ctx
->attribs
->colors_per_channel
;
676 unsigned short gmask
;
677 unsigned short *table
;
679 int channels
= image
->format
== RRGBAFormat
? 4 : 3;
681 /*register unsigned char maxrgb = 0xff;*/
683 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
690 data
= (unsigned char *)ximg
->image
->data
;
692 if (ctx
->vclass
== StaticGray
)
693 gmask
= (1<<ctx
->depth
) - 1; /* use all grays */
695 gmask
= cpc
*cpc
*cpc
-1;
697 table
= computeTable(gmask
);
700 RErrorCode
= RERR_NOMEMORY
;
701 RDestroyXImage(ctx
, ximg
);
705 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
708 printf("grayscale match with %d colors per channel\n", cpc
);
710 for (y
=0; y
<image
->height
; y
++) {
711 for (x
=0; x
<image
->width
; x
++) {
713 g
= table
[(*ptr
++ * 30 + *ptr
++ * 59 + *ptr
++ * 11)/100];
715 /*data[ofs] = ctx->colors[g].pixel;*/
716 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
725 const int dg
=0xff/gmask
;
728 printf("grayscale dither with %d colors per channel\n", cpc
);
730 gerr
= (short*)malloc((image
->width
+2)*sizeof(short));
731 ngerr
= (short*)malloc((image
->width
+2)*sizeof(short));
732 if (!gerr
|| !ngerr
) {
735 RErrorCode
= RERR_NOMEMORY
;
736 RDestroyXImage(ctx
, ximg
);
739 for (x
=0; x
<image
->width
; x
++) {
740 gerr
[x
] = (ptr
[x
*3]*30 + ptr
[x
*3+1]*59 + ptr
[x
*3+2]*11)/100;
743 /* convert and dither the image to XImage */
744 for (y
=0; y
<image
->height
; y
++) {
745 if (y
<image
->height
-1) {
747 for (x
=0, x1
=(y
+1)*image
->width
*3;
750 ngerr
[x
] = (ptr
[x1
++]*30 + ptr
[x1
++]*59 + ptr
[x1
++]*11)/100;
754 ngerr
[x
] = (ptr
[x1
++]*30 + ptr
[x1
++]*59 + ptr
[x1
++]*11)/100;
756 for (x
=0; x
<image
->width
; x
++) {
758 if (gerr
[x
]>0xff) gerr
[x
]=0xff; else if (gerr
[x
]<0) gerr
[x
]=0;
762 /*data[ofs] = ctx->colors[g].pixel;*/
763 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
765 ger
= gerr
[x
] - g
*dg
;
767 /* distribute error */
776 /* skip to next line */
784 ximg
->image
->data
= (char*)data
;
791 image2Bitmap(RContext
*ctx
, RImage
*image
, int threshold
)
794 unsigned char *alpha
;
797 ximg
= RCreateXImage(ctx
, 1, image
->width
, image
->height
);
801 alpha
= image
->data
+3;
803 for (y
= 0; y
< image
->height
; y
++) {
804 for (x
= 0; x
< image
->width
; x
++) {
805 XPutPixel(ximg
->image
, x
, y
, (*alpha
<= threshold
? 0 : 1));
816 RConvertImage(RContext
*context
, RImage
*image
, Pixmap
*pixmap
)
823 assert(context
!=NULL
);
825 assert(pixmap
!=NULL
);
827 /* clear error message */
828 if (context
->vclass
== TrueColor
) {
830 ximg
= image2TrueColor(context
, image
);
832 } else if (context
->vclass
== PseudoColor
833 || context
->vclass
== StaticColor
) {
835 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
)
836 ximg
= image2StandardPseudoColor(context
, image
);
838 ximg
= image2PseudoColor(context
, image
);
840 } else if (context
->vclass
== GrayScale
|| context
->vclass
== StaticGray
) {
842 ximg
= image2GrayScale(context
, image
);
850 *pixmap
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
,
851 image
->height
, context
->depth
);
854 if (context
->flags
.use_shared_pixmap
&& ximg
->is_shared
)
855 tmp
= R_CreateXImageMappedPixmap(context
, ximg
);
860 * We have to copy the shm Pixmap into a normal Pixmap because
861 * otherwise, we would have to control when Pixmaps are freed so
862 * that we can detach their shm segments. This is a problem if the
863 * program crash, leaving stale shared memory segments in the
864 * system (lots of them). But with some work, we can optimize
865 * things and remove this XCopyArea. This will require
866 * explicitly freeing all pixmaps when exiting or restarting
869 XCopyArea(context
->dpy
, tmp
, *pixmap
, context
->copy_gc
, 0, 0,
870 image
->width
, image
->height
, 0, 0);
871 XFreePixmap(context
->dpy
, tmp
);
873 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0,
874 image
->width
, image
->height
);
877 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0,
878 image
->width
, image
->height
);
881 RDestroyXImage(context
, ximg
);
888 RConvertImageMask(RContext
*context
, RImage
*image
, Pixmap
*pixmap
,
889 Pixmap
*mask
, int threshold
)
895 assert(context
!=NULL
);
897 assert(pixmap
!=NULL
);
900 if (!RConvertImage(context
, image
, pixmap
))
903 if (image
->format
==RRGBFormat
) {
908 ximg
= image2Bitmap(context
, image
, threshold
);
913 *mask
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
,
915 gcv
.foreground
= context
->black
;
916 gcv
.background
= context
->white
;
917 gcv
.graphics_exposures
= False
;
918 gc
= XCreateGC(context
->dpy
, *mask
, GCForeground
|GCBackground
919 |GCGraphicsExposures
, &gcv
);
920 RPutXImage(context
, *mask
, gc
, ximg
, 0, 0, 0, 0,
921 image
->width
, image
->height
);
922 RDestroyXImage(context
, ximg
);
929 RGetClosestXColor(RContext
*context
, RColor
*color
, XColor
*retColor
)
931 if (context
->vclass
== TrueColor
) {
932 unsigned short rmask
, gmask
, bmask
;
933 unsigned short roffs
, goffs
, boffs
;
934 unsigned short *rtable
, *gtable
, *btable
;
936 roffs
= context
->red_offset
;
937 goffs
= context
->green_offset
;
938 boffs
= context
->blue_offset
;
940 rmask
= context
->visual
->red_mask
>> roffs
;
941 gmask
= context
->visual
->green_mask
>> goffs
;
942 bmask
= context
->visual
->blue_mask
>> boffs
;
944 rtable
= computeTable(rmask
);
945 gtable
= computeTable(gmask
);
946 btable
= computeTable(bmask
);
948 retColor
->pixel
= (rtable
[color
->red
]<<roffs
) |
949 (gtable
[color
->green
]<<goffs
) | (btable
[color
->blue
]<<boffs
);
951 retColor
->red
= color
->red
<< 8;
952 retColor
->green
= color
->green
<< 8;
953 retColor
->blue
= color
->blue
<< 8;
954 retColor
->flags
= DoRed
|DoGreen
|DoBlue
;
956 } else if (context
->vclass
== PseudoColor
957 || context
->vclass
== StaticColor
) {
959 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
) {
960 unsigned int *rtable
, *gtable
, *btable
;
962 rtable
= computeStdTable(context
->std_rgb_map
->red_mult
,
963 context
->std_rgb_map
->red_max
);
965 gtable
= computeStdTable(context
->std_rgb_map
->green_mult
,
966 context
->std_rgb_map
->green_max
);
968 btable
= computeStdTable(context
->std_rgb_map
->blue_mult
,
969 context
->std_rgb_map
->blue_max
);
971 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
972 RErrorCode
= RERR_NOMEMORY
;
976 retColor
->pixel
= (rtable
[color
->red
]
977 + gtable
[color
->green
]
978 + btable
[color
->blue
]
979 + context
->std_rgb_map
->base_pixel
) & 0xffffffff;
980 retColor
->red
= color
->red
<<8;
981 retColor
->green
= color
->green
<<8;
982 retColor
->blue
= color
->blue
<<8;
983 retColor
->flags
= DoRed
|DoGreen
|DoBlue
;
986 const int cpc
=context
->attribs
->colors_per_channel
;
987 const unsigned short rmask
= cpc
-1; /* different sizes could be used */
988 const unsigned short gmask
= rmask
; /* for r,g,b */
989 const unsigned short bmask
= rmask
;
990 unsigned short *rtable
, *gtable
, *btable
;
991 const int cpccpc
= cpc
*cpc
;
994 rtable
= computeTable(rmask
);
995 gtable
= computeTable(gmask
);
996 btable
= computeTable(bmask
);
998 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
999 RErrorCode
= RERR_NOMEMORY
;
1002 index
= rtable
[color
->red
]*cpccpc
+ gtable
[color
->green
]*cpc
1003 + btable
[color
->blue
];
1004 *retColor
= context
->colors
[index
];
1007 } else if (context
->vclass
== GrayScale
|| context
->vclass
== StaticGray
) {
1009 const int cpc
= context
->attribs
->colors_per_channel
;
1010 unsigned short gmask
;
1011 unsigned short *table
;
1014 if (context
->vclass
== StaticGray
)
1015 gmask
= (1<<context
->depth
) - 1; /* use all grays */
1017 gmask
= cpc
*cpc
*cpc
-1;
1019 table
= computeTable(gmask
);
1023 index
= table
[(color
->red
*30 + color
->green
*59 + color
->blue
*11)/100];
1025 *retColor
= context
->colors
[index
];
1027 RErrorCode
= RERR_INTERNAL
;