[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
xgps/XGBitmap alpha transparacy fix
From: |
Wim Oudshoorn |
Subject: |
xgps/XGBitmap alpha transparacy fix |
Date: |
Wed, 27 Sep 2000 20:19:28 +0200 |
NOTE:
The mailing list does not seem to work. I never saw
my original mail `Newbie tries again', some mail
only get delivered after 4 days and I get some mail
multiple times.
Is this because it is moderated? Is the mailing list
configured in such a way that you never receive your
own e-mail.
Altogether, it makes me quite unsure if my mails
ever get received, and if I get all the mail sent
to the mailing lists.
Greetings,
Wim Oudshoorn.
--
BUG description:
- Displaying images with a non trivial
(not completely transparant or completely opaque) does
not work on all colordepths. (At least not on 16bpp)
REPRODUCE:
- run GWorkspace-0.1.2 in 16bpp with the default
NSGlobalDomain GraphicCompositing
set. Notice that the folder icons are not quite correct.
FIX below, only tested on 16bpp.
ChangeLog:
2000-09-27 Willem Rein Oudshoorn <woudshoo@sctcorp.com>
* XGBitmap.m:
Added macros to convert between RGB and X11 pixel values
(_pixmap_combine_alpha, _bitmap_combine_alpha):
Combined all XGDM_FAST methods in one block of code.
Fixed some bugs in the bitmanipulations.
Result DIFF:
diff -c ~/test/gstep-core-0.6.6/xgps/Source/XGBitmap.m xgps/Source/XGBitmap.m
(Note that, the ~/test/.. file is the originial file and
xgps/Source/XGBitmap.m is the new file.
Sorry I never got the hang of diff, I always mess up the pathnames etc.)
---------------------------------------------------------------------------
*** /home/wim/test/gstep-core-0.6.6/xgps/Source/XGBitmap.m Mon Aug 7
16:49:02 2000
--- xgps/Source/XGBitmap.m Wed Sep 27 19:54:22 2000
***************
*** 42,47 ****
--- 42,92 ----
#include <Foundation/NSDebug.h>
#include <Foundation/NSUserDefaults.h>
+ /* Macros that make it easier to convert
+ between (r,g,b) <--> pixels.
+ */
+
+ #define VARIABLES_DECLARATION \
+ unsigned char _rshift, _gshift, _bshift, _ashift; \
+ unsigned int _rmask, _gmask, _bmask, _amask; \
+ unsigned char _rwidth, _gwidth, _bwidth, _awidth
+
+
+
+ #define InitRGBShiftsAndMasks(rs,rw,gs,gw,bs,bw,as,aw) { \
+ _rshift = rs; \
+ _rmask = (1<<rw) -1; \
+ _rwidth = rw; \
+ _gshift = gs; \
+ _gmask = (1<<gw) -1; \
+ _gwidth = gw; \
+ _bshift = bs; \
+ _bmask = (1<<bw) -1; \
+ _bwidth = bw; \
+ _amask = (1<<aw) -1; \
+ _ashift = as; \
+ _awidth = aw; \
+ } while(0)
+
+
+ #define PixelToRGB(pixel,r,g,b) { \
+ r = (pixel >> _rshift) & _rmask; \
+ g = (pixel >> _gshift) & _gmask; \
+ b = (pixel >> _bshift) & _bmask; \
+ } while(0)
+
+ /* Note that RGBToPixel assumes that the
+ r,g,b values are in the correct domain.
+ If not, the value is nonsense.
+ */
+
+ #define RGBToPixel(r,g,b, pixel) { \
+ pixel = ((r) << _rshift) \
+ |((g) << _gshift) \
+ |((b) << _bshift); \
+ } while(0)
+
+
/* Composite source image (pixmap) onto a destination image with alpha.
Only works for op=Sover now */
int
***************
*** 54,100 ****
unsigned long pixel;
unsigned short oldAlpha = 0;
unsigned long oldPixel = 0;
! unsigned char oldAr = 0;
! unsigned char oldAg = 0;
! unsigned char oldAb = 0;
unsigned char oldBr = 0;
unsigned char oldBg = 0;
unsigned char oldBb = 0;
! if (drawMechanism == XGDM_FAST15 || drawMechanism == XGDM_FAST16)
{
! unsigned rshift, gshift;
unsigned row;
! rshift = 11; gshift = 6;
! if (drawMechanism == XGDM_FAST15)
! {
! rshift = 10;
! gshift = 5;
}
-
for (row = 0; row < NSHeight(drect); row++)
{
unsigned col;
for (col = 0; col < NSWidth(drect); col++)
{
! int r, g, b, alpha;
pixel = XGetPixel(source_im->image,
col+origin_x, row+origin_y);
! r = (pixel >> rshift) & 0x1f;
! g = (pixel >> 5) & 0x1f;
! b = pixel & 0x1f;
pixel = 255;
if (source_alpha)
pixel = XGetPixel(source_alpha->image,
col+origin_x, row+origin_y);
! alpha = pixel >> 3;
if (alpha == 0)
continue; // background unchanged.
! if (alpha != 31)
! {
! unsigned short ialpha = 31 - alpha;
!
/*
* Get the background pixel and convert to RGB.
*/
--- 99,163 ----
unsigned long pixel;
unsigned short oldAlpha = 0;
unsigned long oldPixel = 0;
! unsigned short oldAr = 0;
! unsigned short oldAg = 0;
! unsigned short oldAb = 0;
unsigned char oldBr = 0;
unsigned char oldBg = 0;
unsigned char oldBb = 0;
! if (drawMechanism == XGDM_FAST15
! || drawMechanism == XGDM_FAST16
! || drawMechanism == XGDM_FAST32
! || drawMechanism == XGDM_FAST32_BGR)
{
! VARIABLES_DECLARATION;
unsigned row;
!
! switch (drawMechanism)
! {
! case XGDM_FAST15:
! InitRGBShiftsAndMasks(10,5,5,5,0,5,0,8);
! break;
! case XGDM_FAST16:
! InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8);
! break;
! case XGDM_FAST32:
! InitRGBShiftsAndMasks(16,8,8,8,0,8,0,8);
! break;
! case XGDM_FAST32_BGR:
! InitRGBShiftsAndMasks(0,8,8,8,16,8,0,8);
! break;
! default:
! NSLog(@"Huh? Backend confused about XGDrawMechanism");
! //Try something. With a bit of luck we see
! //which picture goes wrong.
! InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8);
}
for (row = 0; row < NSHeight(drect); row++)
{
unsigned col;
for (col = 0; col < NSWidth(drect); col++)
{
! unsigned r, g, b, alpha;
pixel = XGetPixel(source_im->image,
col+origin_x, row+origin_y);
!
! PixelToRGB(pixel,r,g,b);
!
pixel = 255;
if (source_alpha)
pixel = XGetPixel(source_alpha->image,
col+origin_x, row+origin_y);
!
! alpha = (pixel >> _ashift) & _amask;
!
if (alpha == 0)
continue; // background unchanged.
! if (alpha != _amask)
! { // We really have something to mix!
! unsigned short ialpha = _amask - alpha;
/*
* Get the background pixel and convert to RGB.
*/
***************
*** 102,169 ****
if (pixel != oldPixel)
{
oldPixel = pixel;
! oldBb = pixel & 0x1f;
! pixel >>= gshift;
! oldBg = pixel & 0x1f;
! pixel >>= 5;
! oldBr = pixel;
! oldAlpha = 0;
! }
! if (alpha != oldAlpha)
! {
! oldAlpha = alpha;
! oldAr = ialpha * oldBr;
! oldAg = ialpha * oldBg;
! oldAb = ialpha * oldBb;
! }
!
! // mix in alpha to produce RGB out
! r = (oldAr + (r*alpha))/31;
! g = (oldAg + (g*alpha))/31;
! b = (oldAb + (b*alpha))/31;
! }
! pixel = (((r << 5) + g) << gshift) + b;
! XPutPixel(dest_im->image, col, row, pixel);
! if (dest_alpha)
! XPutPixel(dest_alpha->image, col, row, (alpha << 3));
! }
! }
! }
! else if (drawMechanism == XGDM_FAST32)
! {
! unsigned row;
!
! for (row = 0; row < NSHeight(drect); row++)
! {
! unsigned col;
!
! for (col = 0; col < NSWidth(drect); col++)
! {
! int r, g, b, alpha;
! pixel = XGetPixel(source_im->image,
! col+origin_x, row+origin_y);
! r = (pixel >> 16) & 0xff;
! g = (pixel >> 8) & 0xff;
! b = pixel & 0xff;
! pixel = 255;
! if (source_alpha)
! pixel = XGetPixel(source_alpha->image,
! col+origin_x, row+origin_y);
! alpha = pixel & 0xff;
! if (alpha == 0)
! continue; // background unchanged.
!
! if (alpha != 255)
! {
! unsigned short ialpha = 255 - alpha;
!
! pixel = XGetPixel(dest_im->image, col, row);
! if (pixel != oldPixel)
! {
! oldPixel = pixel;
! oldBr = (pixel & 0xff0000) >> 16;
! oldBg = (pixel & 0xff00) >> 8;
! oldBb = pixel & 0xff;
oldAlpha = 0;
}
if (alpha != oldAlpha)
--- 165,171 ----
if (pixel != oldPixel)
{
oldPixel = pixel;
! PixelToRGB(pixel, oldBr,oldBg,oldBb);
oldAlpha = 0;
}
if (alpha != oldAlpha)
***************
*** 175,245 ****
}
// mix in alpha to produce RGB out
! r = (oldAr + (r*alpha))/255;
! g = (oldAg + (g*alpha))/255;
! b = (oldAb + (b*alpha))/255;
}
! pixel = (((r << 8) + g) << 8) + b;
XPutPixel(dest_im->image, col, row, pixel);
if (dest_alpha)
! XPutPixel(dest_alpha->image, col, row, alpha);
! }
! }
! }
! else if (drawMechanism == XGDM_FAST32_BGR)
! {
! unsigned row;
!
! for (row = 0; row < NSHeight(drect); row++)
! {
! unsigned col;
!
! for (col = 0; col < NSWidth(drect); col++)
! {
! int r, g, b, alpha;
! pixel = XGetPixel(source_im->image,
! col+origin_x, row+origin_y);
! b = (pixel >> 16) & 0xff;
! r = (pixel >> 8) & 0xff;
! g = pixel & 0xff;
! pixel = 255;
! if (source_alpha)
! pixel = XGetPixel(source_alpha->image,
! col+origin_x, row+origin_y);
! alpha = pixel & 0xff;
! if (alpha == 0)
! continue; // background unchanged.
!
! if (alpha != 255)
! {
! unsigned short ialpha = 255 - alpha;
!
! pixel = XGetPixel(dest_im->image, col, row);
! if (pixel != oldPixel)
! {
! oldPixel = pixel;
! oldBb = (pixel & 0xff0000) >> 16;
! oldBg = (pixel & 0xff00) >> 8;
! oldBr = pixel & 0xff;
! oldAlpha = 0;
! }
! if (alpha != oldAlpha)
! {
! oldAlpha = alpha;
! oldAr = ialpha * oldBr;
! oldAg = ialpha * oldBg;
! oldAb = ialpha * oldBb;
! }
!
! // mix in alpha to produce RGB out
! r = (oldAr + (r*alpha))/255;
! g = (oldAg + (g*alpha))/255;
! b = (oldAb + (b*alpha))/255;
! }
! pixel = (((b << 8) + g) << 8) + r;
! XPutPixel(dest_im->image, col, row, pixel);
! if (dest_alpha)
! XPutPixel(dest_alpha->image, col, row, alpha);
}
}
}
--- 177,190 ----
}
// mix in alpha to produce RGB out
! r = (oldAr + (r*alpha))/_amask;
! g = (oldAg + (g*alpha))/_amask;
! b = (oldAb + (b*alpha))/_amask;
}
! RGBToPixel(r,g,b,pixel);
XPutPixel(dest_im->image, col, row, pixel);
if (dest_alpha)
! XPutPixel(dest_alpha->image, col, row, alpha << _ashift );
}
}
}
***************
*** 354,727 ****
{
XColor c0;
XColor c1;
! if (numColors == 3 || (numColors == 4 && usesAlpha)
! || numColors == 1 || (numColors == 2 && usesAlpha))
{
! BOOL colorimage;
! unsigned long pixel;
! unsigned short oldAlpha = 0;
! unsigned long oldPixel = 0;
! unsigned char oldAr = 0;
! unsigned char oldAg = 0;
! unsigned char oldAb = 0;
! unsigned char oldBr = 0;
! unsigned char oldBg = 0;
! unsigned char oldBb = 0;
!
! colorimage = NO;
! if (numColors == 3 || (numColors == 4 && usesAlpha))
! colorimage = YES;
!
! if (drawMechanism == XGDM_FAST15 || drawMechanism == XGDM_FAST16)
! {
! unsigned rshift, gshift;
! unsigned row;
! rshift = 11; gshift = 6;
! if (drawMechanism == XGDM_FAST15)
! {
! rshift = 10;
! gshift = 5;
! }
!
! for (row = 0; row < height; row++)
! {
! unsigned col;
!
! for (col = 0; col < width; col++)
! {
! unsigned short alpha;
! unsigned char r, g, b;
! if (colorimage)
! {
! r = *image_data++;
! g = *image_data++;
! b = *image_data++;
! }
! else
! r = g = b = *image_data++;
! if (row >= NSHeight(drect) || col >= NSWidth(drect))
! {
! if (usesAlpha)
! image_data++;
! continue;
! }
!
! /*
! * Convert 8-bit components down to the 5-bit values
! * that the display system can actually handle.
! */
! r >>= 3;
! g >>= 3;
! b >>= 3;
! if (usesAlpha)
! {
! alpha = (unsigned short)*image_data++;
! if (dest_alpha)
! XPutPixel(dest_alpha->image, col, row, alpha);
! if (alpha == 0)
! continue; // background unchanged.
!
! alpha >>= 3; // Convert to 5-bit.
!
! if (alpha != 31)
! {
! unsigned short ialpha = 31 - alpha;
!
! /*
! * Get the background pixel and convert to RGB.
! */
! pixel = XGetPixel(dest_im->image, col, row);
! if (pixel != oldPixel)
! {
! oldPixel = pixel;
! oldBb = pixel & 0x1f;
! pixel >>= gshift;
! oldBg = pixel & 0x1f;
! pixel >>= 5;
! oldBr = pixel;
! oldAlpha = 0;
! }
! if (alpha != oldAlpha)
! {
! oldAlpha = alpha;
! oldAr = ialpha * oldBr;
! oldAg = ialpha * oldBg;
! oldAb = ialpha * oldBb;
! }
!
! // mix in alpha to produce RGB out
! r = (oldAr + (r*alpha))/31;
! g = (oldAg + (g*alpha))/31;
! b = (oldAb + (b*alpha))/31;
! }
! }
! pixel = (((r << 5) + g) << gshift) + b;
! XPutPixel(dest_im->image, col, row, pixel);
! }
! }
! }
! else if (drawMechanism == XGDM_FAST32)
! {
! unsigned row;
!
! for (row = 0; row < height; row++)
! {
! unsigned col;
!
! for (col = 0; col < width; col++)
! {
! unsigned short alpha;
! unsigned char r, g, b;
! if (colorimage)
! {
! r = *image_data++;
! g = *image_data++;
! b = *image_data++;
! }
! else
! r = g = b = *image_data++;
! if (row >= NSHeight(drect) || col >= NSWidth(drect))
! {
! if (usesAlpha)
! image_data++;
! continue;
! }
!
! if (usesAlpha)
! {
!
! alpha = (unsigned short)*image_data++;
! if (dest_alpha)
! XPutPixel(dest_alpha->image, col, row, alpha);
! if (alpha == 0)
! continue; // background unchanged.
!
! if (alpha != 255)
! {
! unsigned short ialpha = 255 - alpha;
!
! pixel = XGetPixel(dest_im->image, col, row);
! if (pixel != oldPixel)
! {
! oldPixel = pixel;
! oldBr = (pixel & 0xff0000) >> 16;
! oldBg = (pixel & 0xff00) >> 8;
! oldBb = pixel & 0xff;
! oldAlpha = 0;
! }
! if (alpha != oldAlpha)
! {
! oldAlpha = alpha;
! oldAr = ialpha * oldBr;
! oldAg = ialpha * oldBg;
! oldAb = ialpha * oldBb;
! }
!
! // mix in alpha to produce RGB out
! r = (oldAr + (r*alpha))/255;
! g = (oldAg + (g*alpha))/255;
! b = (oldAb + (b*alpha))/255;
! }
! }
! pixel = (((r << 8) + g) << 8) + b;
! XPutPixel(dest_im->image, col, row, pixel);
! }
! }
! }
! else if (drawMechanism == XGDM_FAST32_BGR)
! {
! unsigned row;
!
! for (row = 0; row < height; row++)
! {
! unsigned col;
!
! for (col = 0; col < width; col++)
! {
! unsigned short alpha;
! unsigned char r, g, b;
! if (colorimage)
! {
! r = *image_data++;
! g = *image_data++;
! b = *image_data++;
! }
! else
! r = g = b = *image_data++;
! if (row >= NSHeight(drect) || col >= NSWidth(drect))
! {
! if (usesAlpha)
! image_data++;
! continue;
! }
!
! if (usesAlpha)
! {
! alpha = (unsigned short)*image_data++;
! if (dest_alpha)
! XPutPixel(dest_alpha->image, col, row, alpha);
! if (alpha == 0)
! continue; // background unchanged.
!
! if (alpha != 255)
! {
! unsigned short ialpha = 255 - alpha;
!
! pixel = XGetPixel(dest_im->image, col, row);
! if (pixel != oldPixel)
! {
! oldPixel = pixel;
! oldBb = (pixel & 0xff0000) >> 16;
! oldBg = (pixel & 0xff00) >> 8;
! oldBr = pixel & 0xff;
! oldAlpha = 0;
! }
! if (alpha != oldAlpha)
! {
! oldAlpha = alpha;
! oldAr = ialpha * oldBr;
! oldAg = ialpha * oldBg;
! oldAb = ialpha * oldBb;
! }
!
! // mix in alpha to produce RGB out
! r = (oldAr + (r*alpha))/255;
! g = (oldAg + (g*alpha))/255;
! b = (oldAb + (b*alpha))/255;
! }
! }
! pixel = (((b << 8) + g) << 8) + r;
! XPutPixel(dest_im->image, col, row, pixel);
! }
! }
! }
! else
! {
! XColor c2, a2;
! unsigned row, oldAlpha = 65537;
!
! /*
! * This block of code should be totally portable as it uses the
! * 'official' X mechanism for converting from pixel values to
! * RGB color values - on the downside, it's very slow.
! */
! pixel = (unsigned long)-1; // Never valid?
! c2.pixel = pixel;
!
! for (row = 0; row < height; row++)
! {
! unsigned col;
!
! for (col = 0; col < width; col++)
! {
! unsigned short alpha;
! unsigned char r, g, b;
! if (colorimage)
! {
! r = *image_data++;
! g = *image_data++;
! b = *image_data++;
! }
! else
! r = g = b = *image_data++;
! if (row >= NSHeight(drect) || col >= NSWidth(drect))
! {
! if (usesAlpha)
! image_data++;
! continue;
! }
!
! if (usesAlpha)
! {
! alpha = (unsigned short)*image_data++;
! if (alpha != oldAlpha)
! {
! oldAlpha = alpha;
! a2.red = alpha << 8;
! a2.green = alpha << 8;
! a2.blue = alpha << 8;
! XAllocColor(context->dpy, context->cmap, &a2);
! }
! if (dest_alpha)
! XPutPixel(dest_alpha->image, col, row, a2.pixel);
! if (alpha == 0)
! continue; // background unchanged.
!
! if (alpha == 255)
! {
! c1.red = r << 8;
! c1.green = g << 8;
! c1.blue = b << 8;
! }
! else
! {
! unsigned short ialpha = 255 - alpha;
!
! /*
! * RGB color components in X are 16-bit values -
! * but our bitmap contains 8-bit values so we must
! * adjust our values up to 16-bit, which we can do
! * by increasing their alpha component by 256.
! */
! alpha <<= 8;
!
! /*
! * Get the background pixel and convert to RGB if
! * we haven't already done the conversion earlier.
! */
! c0.pixel = XGetPixel(dest_im->image, col, row);
! if (c0.pixel != pixel)
! {
! pixel = c0.pixel;
! XQueryColor(context->dpy, context->cmap, &c0);
! }
!
! // mix in alpha to produce RGB out
! c1.red = ((c0.red*ialpha) + (r*alpha))/255;
! c1.green = ((c0.green*ialpha) + (g*alpha))/255;
! c1.blue = ((c0.blue*ialpha) + (b*alpha))/255;
! }
! }
! else
! {
! /*
! * Simply convert our 8-bit RGB values to X-style
! * 16-bit values, then determine the X colormap
! * entry and set the pixel.
! */
! c1.red = r << 8;
! c1.green = g << 8;
! c1.blue = b << 8;
! }
!
! /*
! * Convert the X RGB value to a colormap entry if we
! * don't already have one. Then set the pixel.
! * NB. XAllocColor() will not necessarily return a
! * color with exactly the rgb components we gave it, so
! * we must record those components beforehand.
! */
! if (c2.pixel == (unsigned long)-1
! || c2.red != c1.red
! || c2.green != c1.green
! || c2.blue != c1.blue)
! {
! c2.red = c1.red;
! c2.green = c1.green;
! c2.blue = c1.blue;
! XAllocColor(context->dpy, context->cmap, &c1);
! c2.pixel = c1.pixel;
! }
! XPutPixel(dest_im->image, col, row, c1.pixel);
! }
! }
! }
}
! else
{
NSLog(@"Backend cannot handle images with %d colors", numColors);
}
return 0;
}
--- 299,559 ----
{
XColor c0;
XColor c1;
+ BOOL colorimage = NO;
! if (numColors == 3 || (numColors == 4 && usesAlpha))
{
! colorimage = YES;
}
! else if ( ! (numColors == 1 || (numColors == 2 && usesAlpha)))
{
NSLog(@"Backend cannot handle images with %d colors", numColors);
+ return 0;
}
+
+ {
+ unsigned long pixel;
+ unsigned short oldAlpha = 0;
+ unsigned long oldPixel = 0;
+ unsigned short oldAr = 0;
+ unsigned short oldAg = 0;
+ unsigned short oldAb = 0;
+ unsigned char oldBr = 0;
+ unsigned char oldBg = 0;
+ unsigned char oldBb = 0;
+
+ /* Two cases, the *_FAST* method, which
+ is covered in the first a part of the if
+ clause.
+ When no FAST method is available (or recognized)
+ use the `official' X mechanism. This is
+ covered in the else clause */
+
+ if (drawMechanism == XGDM_FAST15
+ || drawMechanism == XGDM_FAST16
+ || drawMechanism == XGDM_FAST32
+ || drawMechanism == XGDM_FAST32_BGR)
+ {
+ VARIABLES_DECLARATION;
+ unsigned row;
+
+ switch (drawMechanism)
+ {
+ case XGDM_FAST15:
+ InitRGBShiftsAndMasks(10,5,5,5,0,5,0,8);
+ break;
+ case XGDM_FAST16:
+ InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8);
+ break;
+ case XGDM_FAST32:
+ InitRGBShiftsAndMasks(16,8,8,8,0,8,0,8);
+ break;
+ case XGDM_FAST32_BGR:
+ InitRGBShiftsAndMasks(0,8,8,8,16,8,0,8);
+ break;
+ default:
+ NSLog(@"Huh? Backend confused about XGDrawMechanism");
+ //Try something. With a bit of luck we see
+ //which picture goes wrong.
+ InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8);
+ }
+
+ for (row = 0; row < height; row++)
+ {
+ unsigned col;
+
+ for (col = 0; col < width; col++)
+ {
+ unsigned short alpha;
+ unsigned short r, g, b;
+
+ if (colorimage)
+ {
+ r = *image_data++;
+ g = *image_data++;
+ b = *image_data++;
+ }
+ else
+ r = g = b = *image_data++;
+
+ if (row >= NSHeight(drect) || col >= NSWidth(drect))
+ {
+ if (usesAlpha)
+ image_data++;
+ continue;
+ }
+
+ /*
+ * Convert 8-bit components down to the 5-bit values
+ * that the display system can actually handle.
+ */
+ r >>= (8 - _rwidth);
+ g >>= (8 - _gwidth);
+ b >>= (8 - _bwidth);
+
+ if (usesAlpha)
+ {
+ alpha = (unsigned short)*image_data++;
+ if (dest_alpha)
+ XPutPixel(dest_alpha->image, col, row, alpha);
+ if (alpha == 0)
+ continue; // background unchanged.
+
+ if (alpha != _amask)
+ {
+ unsigned short ialpha = _amask - alpha;
+ /*
+ * Get the background pixel and convert to RGB.
+ */
+ pixel = XGetPixel(dest_im->image, col, row);
+ if (pixel != oldPixel)
+ {
+ oldPixel = pixel;
+ PixelToRGB(pixel,oldBr,oldBg,oldBb);
+ oldAlpha = 0;
+ }
+ if (alpha != oldAlpha)
+ {
+ oldAlpha = alpha;
+ oldAr = ialpha * oldBr;
+ oldAg = ialpha * oldBg;
+ oldAb = ialpha * oldBb;
+ }
+
+ // mix in alpha to produce RGB out
+ r = (oldAr + (r * alpha)) / _amask;
+ g = (oldAg + (g * alpha)) / _amask;
+ b = (oldAb + (b * alpha)) / _amask;
+ }
+ }
+ RGBToPixel(r,g,b,pixel);
+ XPutPixel(dest_im->image, col, row, pixel);
+ }
+ }
+ }
+ else
+ {
+ XColor c2, a2;
+ unsigned row, oldAlpha = 65537;
+
+ /*
+ * This block of code should be totally portable as it uses the
+ * 'official' X mechanism for converting from pixel values to
+ * RGB color values - on the downside, it's very slow.
+ */
+ pixel = (unsigned long)-1; // Never valid?
+ c2.pixel = pixel;
+
+ for (row = 0; row < height; row++)
+ {
+ unsigned col;
+
+ for (col = 0; col < width; col++)
+ {
+ unsigned short alpha;
+ unsigned char r, g, b;
+
+ if (colorimage)
+ {
+ r = *image_data++;
+ g = *image_data++;
+ b = *image_data++;
+ }
+ else
+ r = g = b = *image_data++;
+ if (row >= NSHeight(drect) || col >= NSWidth(drect))
+ {
+ if (usesAlpha)
+ image_data++;
+ continue;
+ }
+
+ if (usesAlpha)
+ {
+ alpha = (unsigned short)*image_data++;
+ if (alpha != oldAlpha)
+ {
+ oldAlpha = alpha;
+ a2.red = alpha << 8;
+ a2.green = alpha << 8;
+ a2.blue = alpha << 8;
+ XAllocColor(context->dpy, context->cmap, &a2);
+ }
+ if (dest_alpha)
+ XPutPixel(dest_alpha->image, col, row, a2.pixel);
+ if (alpha == 0)
+ continue; // background unchanged.
+
+ if (alpha == 255)
+ {
+ c1.red = r << 8;
+ c1.green = g << 8;
+ c1.blue = b << 8;
+ }
+ else
+ {
+ unsigned short ialpha = 255 - alpha;
+
+ /*
+ * RGB color components in X are 16-bit values -
+ * but our bitmap contains 8-bit values so we must
+ * adjust our values up to 16-bit, which we can do
+ * by increasing their alpha component by 256.
+ */
+ alpha <<= 8;
+
+ /*
+ * Get the background pixel and convert to RGB if
+ * we haven't already done the conversion earlier.
+ */
+ c0.pixel = XGetPixel(dest_im->image, col, row);
+ if (c0.pixel != pixel)
+ {
+ pixel = c0.pixel;
+ XQueryColor(context->dpy, context->cmap, &c0);
+ }
+
+ // mix in alpha to produce RGB out
+ c1.red = ((c0.red*ialpha) + (r*alpha))/255;
+ c1.green = ((c0.green*ialpha) + (g*alpha))/255;
+ c1.blue = ((c0.blue*ialpha) + (b*alpha))/255;
+ }
+ }
+ else
+ {
+ /*
+ * Simply convert our 8-bit RGB values to X-style
+ * 16-bit values, then determine the X colormap
+ * entry and set the pixel.
+ */
+ c1.red = r << 8;
+ c1.green = g << 8;
+ c1.blue = b << 8;
+ }
+
+ /*
+ * Convert the X RGB value to a colormap entry if we
+ * don't already have one. Then set the pixel.
+ * NB. XAllocColor() will not necessarily return a
+ * color with exactly the rgb components we gave it, so
+ * we must record those components beforehand.
+ */
+ if (c2.pixel == (unsigned long)-1
+ || c2.red != c1.red
+ || c2.green != c1.green
+ || c2.blue != c1.blue)
+ {
+ c2.red = c1.red;
+ c2.green = c1.green;
+ c2.blue = c1.blue;
+ XAllocColor(context->dpy, context->cmap, &c1);
+ c2.pixel = c1.pixel;
+ }
+ XPutPixel(dest_im->image, col, row, c1.pixel);
+ }
+ }
+ }
+ }
return 0;
}