1 /* convert.c - convert RImage to Pixmap
3 * Raster graphics library
5 * Copyright (c) 1997 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 /* AIX requires this to be the first thing in the file. */
25 # define alloca __builtin_alloca
33 # ifndef alloca /* predefined by HP cc +Olibcalls */
42 #include <X11/Xutil.h>
52 Pixmap
R_CreateXImageMappedPixmap(RContext
*context
, RXImage
*ximage
);
57 typedef struct RConversionTable
{
58 unsigned short table
[256];
61 struct RConversionTable
*next
;
65 typedef struct RStdConversionTable
{
66 unsigned int table
[256];
71 struct RStdConversionTable
*next
;
72 } RStdConversionTable
;
76 static RConversionTable
*conversionTable
= NULL
;
77 static RStdConversionTable
*stdConversionTable
= NULL
;
80 static unsigned short*
81 computeTable(unsigned short mask
)
83 RConversionTable
*tmp
= conversionTable
;
87 if (tmp
->index
== mask
)
95 tmp
= (RConversionTable
*)malloc(sizeof(RConversionTable
));
100 tmp
->table
[i
] = (i
*mask
+ 0x7f)/0xff;
103 tmp
->next
= conversionTable
;
104 conversionTable
= tmp
;
110 computeStdTable(unsigned int mult
, unsigned int max
)
112 RStdConversionTable
*tmp
= stdConversionTable
;
116 if (tmp
->mult
== mult
&& tmp
->max
== max
)
124 tmp
= (RStdConversionTable
*)malloc(sizeof(RStdConversionTable
));
128 for (i
=0; i
<256; i
++) {
129 tmp
->table
[i
] = (i
*max
)/0xff * mult
;
134 tmp
->next
= stdConversionTable
;
135 stdConversionTable
= tmp
;
143 image2TrueColorD16(RContext
*ctx
, RImage
*image
)
146 register int x
, y
, r
, g
, b
;
147 unsigned char *red
, *grn
, *blu
;
148 unsigned short rmask
, gmask
, bmask
;
149 unsigned short roffs
, goffs
, boffs
;
150 unsigned short *rtable
, *gtable
, *btable
;
153 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
158 red
= image
->data
[0];
159 grn
= image
->data
[1];
160 blu
= image
->data
[2];
162 roffs
= ctx
->red_offset
;
163 goffs
= ctx
->green_offset
;
164 boffs
= ctx
->blue_offset
;
166 rmask
= ctx
->visual
->red_mask
>> roffs
;
167 gmask
= ctx
->visual
->green_mask
>> goffs
;
168 bmask
= ctx
->visual
->blue_mask
>> boffs
;
170 rtable
= computeTable(rmask
);
171 gtable
= computeTable(gmask
);
172 btable
= computeTable(bmask
);
174 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
175 RErrorCode
= RERR_NOMEMORY
;
176 RDestroyXImage(ctx
, ximg
);
182 short *rerr
, *gerr
, *berr
;
183 short *nrerr
, *ngerr
, *nberr
;
185 unsigned short *dataP
;
188 const int dr
=0xff/rmask
;
189 const int dg
=0xff/gmask
;
190 const int db
=0xff/bmask
;
192 rerr
= (short*)alloca((image
->width
+2)*sizeof(short));
193 gerr
= (short*)alloca((image
->width
+2)*sizeof(short));
194 berr
= (short*)alloca((image
->width
+2)*sizeof(short));
195 nrerr
= (short*)alloca((image
->width
+2)*sizeof(short));
196 ngerr
= (short*)alloca((image
->width
+2)*sizeof(short));
197 nberr
= (short*)alloca((image
->width
+2)*sizeof(short));
198 if (!rerr
|| !gerr
|| !berr
|| !nrerr
|| !ngerr
|| !nberr
) {
199 RErrorCode
= RERR_NOMEMORY
;
200 RDestroyXImage(ctx
, ximg
);
203 for (x
=0; x
<image
->width
; x
++) {
208 rerr
[x
] = gerr
[x
] = berr
[x
] = 0;
210 dataP
= (unsigned short*)ximg
->image
->data
;
211 line_offset
= ximg
->image
->bytes_per_line
- image
->width
* 2;
213 /* convert and dither the image to XImage */
214 for (y
=0, ofs
=0; y
<image
->height
; y
++) {
215 if (y
<image
->height
-1) {
217 for (x
=0, x1
=ofs
+image
->width
; x
<image
->width
; x
++, x1
++) {
228 for (x
=0; x
<image
->width
; x
++) {
230 if (rerr
[x
]>0xff) rerr
[x
]=0xff; else if (rerr
[x
]<0) rerr
[x
]=0;
231 if (gerr
[x
]>0xff) gerr
[x
]=0xff; else if (gerr
[x
]<0) gerr
[x
]=0;
232 if (berr
[x
]>0xff) berr
[x
]=0xff; else if (berr
[x
]<0) berr
[x
]=0;
238 *(dataP
++) = (r
<<roffs
) | (g
<<goffs
) | (b
<<boffs
);
241 rer
= rerr
[x
] - r
*dr
;
242 ger
= gerr
[x
] - g
*dg
;
243 ber
= berr
[x
] - b
*db
;
245 /* distribute error */
263 /*(char*)dataP += line_offset;*/
264 dataP
= (unsigned short *)((char *)dataP
+ line_offset
);
266 /* skip to next line */
285 image2TrueColor(RContext
*ctx
, RImage
*image
)
288 register int x
, y
, r
, g
, b
;
289 unsigned char *red
, *grn
, *blu
;
291 unsigned short rmask
, gmask
, bmask
;
292 unsigned short roffs
, goffs
, boffs
;
293 unsigned short *rtable
, *gtable
, *btable
;
296 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
301 red
= image
->data
[0];
302 grn
= image
->data
[1];
303 blu
= image
->data
[2];
305 roffs
= ctx
->red_offset
;
306 goffs
= ctx
->green_offset
;
307 boffs
= ctx
->blue_offset
;
309 rmask
= ctx
->visual
->red_mask
>> roffs
;
310 gmask
= ctx
->visual
->green_mask
>> goffs
;
311 bmask
= ctx
->visual
->blue_mask
>> boffs
;
314 /* this do not seem to increase speed. Only 0.06 second faster in
315 * rendering a 800x600 image to pixmap. 1.12 sec instead of 1.18.
316 * But does not require a 256*256*256 lookup table.
318 if (ctx
->depth
==24) {
320 puts("true color match for 24bpp");
322 for (y
=0; y
< image
->height
; y
++) {
323 for (x
=0; x
< image
->width
; x
++) {
324 pixel
= (*(red
++)<<roffs
) | (*(grn
++)<<goffs
) | (*(blu
++)<<boffs
);
325 XPutPixel(ximg
->image
, x
, y
, pixel
);
332 rtable
= computeTable(rmask
);
333 gtable
= computeTable(gmask
);
334 btable
= computeTable(bmask
);
336 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
337 RErrorCode
= RERR_NOMEMORY
;
338 RDestroyXImage(ctx
, ximg
);
342 if (ctx
->attribs
->render_mode
==RBestMatchRendering
) {
345 puts("true color match");
347 for (y
=0, ofs
=0; y
< image
->height
; y
++) {
348 for (x
=0; x
< image
->width
; x
++, ofs
++) {
350 r
= rtable
[red
[ofs
]];
351 g
= gtable
[grn
[ofs
]];
352 b
= btable
[blu
[ofs
]];
353 pixel
= (r
<<roffs
) | (g
<<goffs
) | (b
<<boffs
);
354 XPutPixel(ximg
->image
, x
, y
, pixel
);
359 short *rerr
, *gerr
, *berr
;
360 short *nrerr
, *ngerr
, *nberr
;
363 const int dr
=0xff/rmask
;
364 const int dg
=0xff/gmask
;
365 const int db
=0xff/bmask
;
368 puts("true color dither");
370 rerr
= (short*)alloca((image
->width
+2)*sizeof(short));
371 gerr
= (short*)alloca((image
->width
+2)*sizeof(short));
372 berr
= (short*)alloca((image
->width
+2)*sizeof(short));
373 nrerr
= (short*)alloca((image
->width
+2)*sizeof(short));
374 ngerr
= (short*)alloca((image
->width
+2)*sizeof(short));
375 nberr
= (short*)alloca((image
->width
+2)*sizeof(short));
376 if (!rerr
|| !gerr
|| !berr
|| !nrerr
|| !ngerr
|| !nberr
) {
377 RErrorCode
= RERR_NOMEMORY
;
378 RDestroyXImage(ctx
, ximg
);
381 for (x
=0; x
<image
->width
; x
++) {
386 rerr
[x
] = gerr
[x
] = berr
[x
] = 0;
387 /* convert and dither the image to XImage */
388 for (y
=0, ofs
=0; y
<image
->height
; y
++) {
389 if (y
<image
->height
-1) {
391 for (x
=0, x1
=ofs
+image
->width
; x
<image
->width
; x
++, x1
++) {
402 for (x
=0; x
<image
->width
; x
++) {
404 if (rerr
[x
]>0xff) rerr
[x
]=0xff; else if (rerr
[x
]<0) rerr
[x
]=0;
405 if (gerr
[x
]>0xff) gerr
[x
]=0xff; else if (gerr
[x
]<0) gerr
[x
]=0;
406 if (berr
[x
]>0xff) berr
[x
]=0xff; else if (berr
[x
]<0) berr
[x
]=0;
412 pixel
= (r
<<roffs
) | (g
<<goffs
) | (b
<<boffs
);
413 XPutPixel(ximg
->image
, x
, y
, pixel
);
415 rer
= rerr
[x
] - r
*dr
;
416 ger
= gerr
[x
] - g
*dg
;
417 ber
= berr
[x
] - b
*db
;
419 /* distribute error */
437 /* skip to next line */
458 image2PseudoColor(RContext
*ctx
, RImage
*image
)
461 register int x
, y
, r
, g
, b
;
462 unsigned char *red
, *grn
, *blu
;
464 const int cpc
=ctx
->attribs
->colors_per_channel
;
465 const unsigned short rmask
= cpc
-1; /* different sizes could be used */
466 const unsigned short gmask
= rmask
; /* for r,g,b */
467 const unsigned short bmask
= rmask
;
468 unsigned short *rtable
, *gtable
, *btable
;
469 const int cpccpc
= cpc
*cpc
;
472 /*register unsigned char maxrgb = 0xff;*/
474 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
479 red
= image
->data
[0];
480 grn
= image
->data
[1];
481 blu
= image
->data
[2];
483 data
= (unsigned char *)ximg
->image
->data
;
485 /* Tables are same at the moment because rmask==gmask==bmask. */
486 rtable
= computeTable(rmask
);
487 gtable
= computeTable(gmask
);
488 btable
= computeTable(bmask
);
490 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
491 RErrorCode
= RERR_NOMEMORY
;
492 RDestroyXImage(ctx
, ximg
);
496 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
499 printf("pseudo color match with %d colors per channel\n", cpc
);
501 for (y
=0, ofs
= 0; y
<image
->height
; y
++) {
502 for (x
=0; x
<image
->width
; x
++, ofs
++) {
504 r
= rtable
[red
[ofs
]];
505 g
= gtable
[grn
[ofs
]];
506 b
= btable
[blu
[ofs
]];
507 pixel
= r
*cpccpc
+ g
*cpc
+ b
;
508 /*data[ofs] = ctx->colors[pixel].pixel;*/
509 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[pixel
].pixel
);
514 short *rerr
, *gerr
, *berr
;
515 short *nrerr
, *ngerr
, *nberr
;
518 const int dr
=0xff/rmask
;
519 const int dg
=0xff/gmask
;
520 const int db
=0xff/bmask
;
523 printf("pseudo color dithering with %d colors per channel\n", cpc
);
525 rerr
= (short*)alloca((image
->width
+2)*sizeof(short));
526 gerr
= (short*)alloca((image
->width
+2)*sizeof(short));
527 berr
= (short*)alloca((image
->width
+2)*sizeof(short));
528 nrerr
= (short*)alloca((image
->width
+2)*sizeof(short));
529 ngerr
= (short*)alloca((image
->width
+2)*sizeof(short));
530 nberr
= (short*)alloca((image
->width
+2)*sizeof(short));
531 if (!rerr
|| !gerr
|| !berr
|| !nrerr
|| !ngerr
|| !nberr
) {
532 RErrorCode
= RERR_NOMEMORY
;
533 RDestroyXImage(ctx
, ximg
);
536 for (x
=0; x
<image
->width
; x
++) {
541 rerr
[x
] = gerr
[x
] = berr
[x
] = 0;
542 /* convert and dither the image to XImage */
543 for (y
=0, ofs
=0; y
<image
->height
; y
++) {
544 if (y
<image
->height
-1) {
546 for (x
=0, x1
=ofs
+image
->width
; x
<image
->width
; x
++, x1
++) {
557 for (x
=0; x
<image
->width
; x
++, ofs
++) {
559 if (rerr
[x
]>0xff) rerr
[x
]=0xff; else if (rerr
[x
]<0) rerr
[x
]=0;
560 if (gerr
[x
]>0xff) gerr
[x
]=0xff; else if (gerr
[x
]<0) gerr
[x
]=0;
561 if (berr
[x
]>0xff) berr
[x
]=0xff; else if (berr
[x
]<0) berr
[x
]=0;
567 pixel
= r
*cpccpc
+ g
*cpc
+ b
;
568 /*data[ofs] = ctx->colors[pixel].pixel;*/
569 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[pixel
].pixel
);
572 rer
= rerr
[x
] - r
*dr
;
573 ger
= gerr
[x
] - g
*dg
;
574 ber
= berr
[x
] - b
*db
;
576 /* distribute error */
577 rerr
[x
+1]+=(rer
*7)/16;
578 gerr
[x
+1]+=(ger
*7)/16;
579 berr
[x
+1]+=(ber
*7)/16;
581 nrerr
[x
]+=(rer
*5)/16;
582 ngerr
[x
]+=(ger
*5)/16;
583 nberr
[x
]+=(ber
*5)/16;
586 nrerr
[x
-1]+=(rer
*3)/16;
587 ngerr
[x
-1]+=(ger
*3)/16;
588 nberr
[x
-1]+=(ber
*3)/16;
595 /* distribute error */
613 /* skip to next line */
627 ximg
->image
->data
= (char*)data
;
634 * For standard colormap
637 image2StandardPseudoColor(RContext
*ctx
, RImage
*image
)
640 register int x
, y
, r
, g
, b
;
641 unsigned char *red
, *grn
, *blu
;
644 unsigned int *rtable
, *gtable
, *btable
;
645 unsigned int base_pixel
= ctx
->std_rgb_map
->base_pixel
;
647 /*register unsigned char maxrgb = 0xff;*/
649 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
654 red
= image
->data
[0];
655 grn
= image
->data
[1];
656 blu
= image
->data
[2];
658 data
= (unsigned char *)ximg
->image
->data
;
661 rtable
= computeStdTable(ctx
->std_rgb_map
->red_mult
,
662 ctx
->std_rgb_map
->red_max
);
664 gtable
= computeStdTable(ctx
->std_rgb_map
->green_mult
,
665 ctx
->std_rgb_map
->green_max
);
667 btable
= computeStdTable(ctx
->std_rgb_map
->blue_mult
,
668 ctx
->std_rgb_map
->blue_max
);
670 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
671 RErrorCode
= RERR_NOMEMORY
;
672 RDestroyXImage(ctx
, ximg
);
677 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
678 for (y
=0, ofs
= 0; y
<image
->height
; y
++) {
679 for (x
=0; x
<image
->width
; x
++, ofs
++) {
682 pixel
= (rtable
[red
[ofs
]] + gtable
[grn
[ofs
]]
683 + btable
[blu
[ofs
]] + base_pixel
) & 0xffffffff;
685 XPutPixel(ximg
->image
, x
, y
, pixel
);
690 short *rerr
, *gerr
, *berr
;
691 short *nrerr
, *ngerr
, *nberr
;
696 printf("pseudo color dithering with %d colors per channel\n", cpc
);
698 rerr
= (short*)alloca((image
->width
+2)*sizeof(short));
699 gerr
= (short*)alloca((image
->width
+2)*sizeof(short));
700 berr
= (short*)alloca((image
->width
+2)*sizeof(short));
701 nrerr
= (short*)alloca((image
->width
+2)*sizeof(short));
702 ngerr
= (short*)alloca((image
->width
+2)*sizeof(short));
703 nberr
= (short*)alloca((image
->width
+2)*sizeof(short));
704 if (!rerr
|| !gerr
|| !berr
|| !nrerr
|| !ngerr
|| !nberr
) {
705 RErrorCode
= RERR_NOMEMORY
;
706 RDestroyXImage(ctx
, ximg
);
709 for (x
=0; x
<image
->width
; x
++) {
714 rerr
[x
] = gerr
[x
] = berr
[x
] = 0;
715 /* convert and dither the image to XImage */
716 for (y
=0, ofs
=0; y
<image
->height
; y
++) {
717 if (y
<image
->height
-1) {
719 for (x
=0, x1
=ofs
+image
->width
; x
<image
->width
; x
++, x1
++) {
730 for (x
=0; x
<image
->width
; x
++, ofs
++) {
732 if (rerr
[x
]>0xff) rerr
[x
]=0xff; else if (rerr
[x
]<0) rerr
[x
]=0;
733 if (gerr
[x
]>0xff) gerr
[x
]=0xff; else if (gerr
[x
]<0) gerr
[x
]=0;
734 if (berr
[x
]>0xff) berr
[x
]=0xff; else if (berr
[x
]<0) berr
[x
]=0;
742 XPutPixel(ximg
->image
, x
, y
, pixel
+base_pixel
);
745 rer
= rerr
[x
] - (ctx
->colors
[pixel
].red
>>8);
746 ger
= gerr
[x
] - (ctx
->colors
[pixel
].green
>>8);
747 ber
= berr
[x
] - (ctx
->colors
[pixel
].blue
>>8);
749 /* distribute error */
750 rerr
[x
+1]+=(rer
*7)/16;
751 gerr
[x
+1]+=(ger
*7)/16;
752 berr
[x
+1]+=(ber
*7)/16;
754 nrerr
[x
]+=(rer
*5)/16;
755 ngerr
[x
]+=(ger
*5)/16;
756 nberr
[x
]+=(ber
*5)/16;
759 nrerr
[x
-1]+=(rer
*3)/16;
760 ngerr
[x
-1]+=(ger
*3)/16;
761 nberr
[x
-1]+=(ber
*3)/16;
768 /* skip to next line */
782 ximg
->image
->data
= (char*)data
;
790 image2GrayScale(RContext
*ctx
, RImage
*image
)
793 register int x
, y
, g
;
794 unsigned char *red
, *grn
, *blu
;
795 const int cpc
=ctx
->attribs
->colors_per_channel
;
796 unsigned short gmask
;
797 unsigned short *table
;
800 /*register unsigned char maxrgb = 0xff;*/
802 ximg
= RCreateXImage(ctx
, ctx
->depth
, image
->width
, image
->height
);
807 red
= image
->data
[0];
808 grn
= image
->data
[1];
809 blu
= image
->data
[2];
811 data
= (unsigned char *)ximg
->image
->data
;
813 if (ctx
->vclass
== StaticGray
)
814 gmask
= (1<<ctx
->depth
) - 1; /* use all grays */
816 gmask
= cpc
*cpc
*cpc
-1;
818 table
= computeTable(gmask
);
821 RErrorCode
= RERR_NOMEMORY
;
822 RDestroyXImage(ctx
, ximg
);
826 if (ctx
->attribs
->render_mode
== RBestMatchRendering
) {
829 printf("grayscale match with %d colors per channel\n", cpc
);
831 for (y
=0, ofs
= 0; y
<image
->height
; y
++) {
832 for (x
=0; x
<image
->width
; x
++, ofs
++) {
834 g
= table
[(red
[ofs
]*30+grn
[ofs
]*59+blu
[ofs
]*11)/100];
836 /*data[ofs] = ctx->colors[g].pixel;*/
837 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
846 const int dg
=0xff/gmask
;
849 printf("grayscale dither with %d colors per channel\n", cpc
);
851 gerr
= (short*)alloca((image
->width
+2)*sizeof(short));
852 ngerr
= (short*)alloca((image
->width
+2)*sizeof(short));
853 if (!gerr
|| !ngerr
) {
854 RErrorCode
= RERR_NOMEMORY
;
855 RDestroyXImage(ctx
, ximg
);
858 for (x
=0; x
<image
->width
; x
++) {
859 gerr
[x
] = (red
[x
]*30 + grn
[x
]*59 + blu
[x
]*11)/100;
862 /* convert and dither the image to XImage */
863 for (y
=0, ofs
=0; y
<image
->height
; y
++) {
864 if (y
<image
->height
-1) {
866 for (x
=0, x1
=ofs
+image
->width
; x
<image
->width
; x
++, x1
++) {
867 ngerr
[x
] = (red
[x1
]*30 + grn
[x1
]*59 + blu
[x1
]*11)/100;
871 ngerr
[x
] = (red
[x1
]*30 + grn
[x1
]*59 + blu
[x1
]*11)/100;
873 for (x
=0; x
<image
->width
; x
++, ofs
++) {
875 if (gerr
[x
]>0xff) gerr
[x
]=0xff; else if (gerr
[x
]<0) gerr
[x
]=0;
879 /*data[ofs] = ctx->colors[g].pixel;*/
880 XPutPixel(ximg
->image
, x
, y
, ctx
->colors
[g
].pixel
);
882 ger
= gerr
[x
] - g
*dg
;
884 /* distribute error */
893 /* skip to next line */
899 ximg
->image
->data
= (char*)data
;
906 image2Bitmap(RContext
*ctx
, RImage
*image
, int threshold
)
909 unsigned char *alpha
;
912 ximg
= RCreateXImage(ctx
, 1, image
->width
, image
->height
);
916 alpha
= image
->data
[3];
918 for (y
= 0; y
< image
->height
; y
++) {
919 for (x
= 0; x
< image
->width
; x
++) {
920 XPutPixel(ximg
->image
, x
, y
, (*alpha
<= threshold
? 0 : 1));
931 RConvertImage(RContext
*context
, RImage
*image
, Pixmap
*pixmap
)
938 assert(context
!=NULL
);
940 assert(pixmap
!=NULL
);
942 /* clear error message */
943 if (context
->vclass
== TrueColor
) {
945 if (context
->attribs
->render_mode
== RDitheredRendering
946 && (context
->depth
== 15 || context
->depth
== 16))
947 ximg
= image2TrueColorD16(context
, image
);
949 ximg
= image2TrueColor(context
, image
);
951 } else if (context
->vclass
== PseudoColor
952 || context
->vclass
== StaticColor
) {
954 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
)
955 ximg
= image2StandardPseudoColor(context
, image
);
957 ximg
= image2PseudoColor(context
, image
);
959 } else if (context
->vclass
== GrayScale
|| context
->vclass
== StaticGray
) {
961 ximg
= image2GrayScale(context
, image
);
972 *pixmap
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
,
973 image
->height
, context
->depth
);
976 if (context
->flags
.use_shared_pixmap
&& ximg
->is_shared
)
977 tmp
= R_CreateXImageMappedPixmap(context
, ximg
);
982 * We have to copy the shm Pixmap into a normal Pixmap because
983 * otherwise, we would have to control when Pixmaps are freed so
984 * that we can detach their shm segments. This is a problem if the
985 * program crash, leaving stale shared memory segments in the
986 * system (lots of them). But with some work, we can optimize
987 * things and remove this XCopyArea. This will require
988 * explicitly freeing all pixmaps when exiting or restarting
991 XCopyArea(context
->dpy
, tmp
, *pixmap
, context
->copy_gc
, 0, 0,
992 image
->width
, image
->height
, 0, 0);
993 XFreePixmap(context
->dpy
, tmp
);
995 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0,
996 image
->width
, image
->height
);
999 RPutXImage(context
, *pixmap
, context
->copy_gc
, ximg
, 0, 0, 0, 0,
1000 image
->width
, image
->height
);
1003 RDestroyXImage(context
, ximg
);
1013 RConvertImageMask(RContext
*context
, RImage
*image
, Pixmap
*pixmap
,
1014 Pixmap
*mask
, int threshold
)
1020 assert(context
!=NULL
);
1021 assert(image
!=NULL
);
1022 assert(pixmap
!=NULL
);
1025 if (!RConvertImage(context
, image
, pixmap
))
1028 if (image
->data
[3]==NULL
) {
1033 ximg
= image2Bitmap(context
, image
, threshold
);
1041 *mask
= XCreatePixmap(context
->dpy
, context
->drawable
, image
->width
,
1043 gcv
.foreground
= context
->black
;
1044 gcv
.background
= context
->white
;
1045 gcv
.graphics_exposures
= False
;
1046 gc
= XCreateGC(context
->dpy
, *mask
, GCForeground
|GCBackground
1047 |GCGraphicsExposures
, &gcv
);
1048 RPutXImage(context
, *mask
, gc
, ximg
, 0, 0, 0, 0,
1049 image
->width
, image
->height
);
1050 RDestroyXImage(context
, ximg
);
1060 RGetClosestXColor(RContext
*context
, RColor
*color
, XColor
*retColor
)
1062 if (context
->vclass
== TrueColor
) {
1063 unsigned short rmask
, gmask
, bmask
;
1064 unsigned short roffs
, goffs
, boffs
;
1065 unsigned short *rtable
, *gtable
, *btable
;
1067 roffs
= context
->red_offset
;
1068 goffs
= context
->green_offset
;
1069 boffs
= context
->blue_offset
;
1071 rmask
= context
->visual
->red_mask
>> roffs
;
1072 gmask
= context
->visual
->green_mask
>> goffs
;
1073 bmask
= context
->visual
->blue_mask
>> boffs
;
1075 rtable
= computeTable(rmask
);
1076 gtable
= computeTable(gmask
);
1077 btable
= computeTable(bmask
);
1079 retColor
->pixel
= (rtable
[color
->red
]<<roffs
) |
1080 (gtable
[color
->green
]<<goffs
) | (btable
[color
->blue
]<<boffs
);
1082 retColor
->red
= color
->red
<< 8;
1083 retColor
->green
= color
->green
<< 8;
1084 retColor
->blue
= color
->blue
<< 8;
1085 retColor
->flags
= DoRed
|DoGreen
|DoBlue
;
1087 } else if (context
->vclass
== PseudoColor
1088 || context
->vclass
== StaticColor
) {
1090 if (context
->attribs
->standard_colormap_mode
!= RIgnoreStdColormap
) {
1091 unsigned int *rtable
, *gtable
, *btable
;
1093 rtable
= computeStdTable(context
->std_rgb_map
->red_mult
,
1094 context
->std_rgb_map
->red_max
);
1096 gtable
= computeStdTable(context
->std_rgb_map
->green_mult
,
1097 context
->std_rgb_map
->green_max
);
1099 btable
= computeStdTable(context
->std_rgb_map
->blue_mult
,
1100 context
->std_rgb_map
->blue_max
);
1102 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
1103 RErrorCode
= RERR_NOMEMORY
;
1107 retColor
->pixel
= (rtable
[color
->red
]
1108 + gtable
[color
->green
]
1109 + btable
[color
->blue
]
1110 + context
->std_rgb_map
->base_pixel
) & 0xffffffff;
1111 retColor
->red
= color
->red
<<8;
1112 retColor
->green
= color
->green
<<8;
1113 retColor
->blue
= color
->blue
<<8;
1114 retColor
->flags
= DoRed
|DoGreen
|DoBlue
;
1117 const int cpc
=context
->attribs
->colors_per_channel
;
1118 const unsigned short rmask
= cpc
-1; /* different sizes could be used */
1119 const unsigned short gmask
= rmask
; /* for r,g,b */
1120 const unsigned short bmask
= rmask
;
1121 unsigned short *rtable
, *gtable
, *btable
;
1122 const int cpccpc
= cpc
*cpc
;
1125 rtable
= computeTable(rmask
);
1126 gtable
= computeTable(gmask
);
1127 btable
= computeTable(bmask
);
1129 if (rtable
==NULL
|| gtable
==NULL
|| btable
==NULL
) {
1130 RErrorCode
= RERR_NOMEMORY
;
1133 index
= rtable
[color
->red
]*cpccpc
+ gtable
[color
->green
]*cpc
1134 + btable
[color
->blue
];
1135 *retColor
= context
->colors
[index
];
1138 } else if (context
->vclass
== GrayScale
|| context
->vclass
== StaticGray
) {
1140 const int cpc
= context
->attribs
->colors_per_channel
;
1141 unsigned short gmask
;
1142 unsigned short *table
;
1145 if (context
->vclass
== StaticGray
)
1146 gmask
= (1<<context
->depth
) - 1; /* use all grays */
1148 gmask
= cpc
*cpc
*cpc
-1;
1150 table
= computeTable(gmask
);
1154 index
= table
[(color
->red
*30 + color
->green
*59 + color
->blue
*11)/100];
1156 *retColor
= context
->colors
[index
];
1158 RErrorCode
= RERR_INTERNAL
;