[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Alpha compositing in gnustep-back
From: |
Jeff Teunissen |
Subject: |
Re: Alpha compositing in gnustep-back |
Date: |
Sat, 27 Jul 2002 12:44:53 -0400 |
Adam Fedor wrote:
> Jeff Teunissen wrote:
[snip]
> > As part of trying to understand the functions, I partially rewrote the
> > fast paths for them. The code is shorter, but it may be slower since
> > the math is done in floating point.
>
> It's about 10% slower in my tests. But that may not be accurate.
I've done a little bit of work to make it faster. The math is integer now,
and there's some more avoidance of unnecessary work. It feels a little
faster (to me, at least).
--
| Jeff Teunissen -=- Pres., Dusk To Dawn Computing -=- deek @ d2dc.net
| GPG: 1024D/9840105A 7102 808A 7733 C2F3 097B 161B 9222 DAB8 9840 105A
| Core developer, The QuakeForge Project http://www.quakeforge.net/
| Specializing in Debian GNU/Linux http://www.d2dc.net/~deek/
Index: back/Source/xlib/XGBitmap.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/back/Source/xlib/XGBitmap.m,v
retrieving revision 1.3
diff -u -r1.3 XGBitmap.m
--- back/Source/xlib/XGBitmap.m 15 Jul 2002 02:50:59 -0000 1.3
+++ back/Source/xlib/XGBitmap.m 27 Jul 2002 16:43:32 -0000
@@ -150,18 +150,18 @@
for (col = 0; col < srect.width; col++)
{
- unsigned sr, sg, sb, sa; // source
- unsigned dr, dg, db, da; // dest
- double alpha, ialpha;
+ unsigned sr, sg, sb, sa; // source
+ unsigned dr, dg, db, da; // dest
+ unsigned ialpha;
// Get the source pixel information
- pixel = XGetPixel (source_im->image, srect.x+col, srect.y+row);
- PixelToRGB (pixel, sr, sg, sb);
+ pixel = XGetPixel(source_im->image, srect.x+col, srect.y+row);
+ PixelToRGB(pixel, sr, sg, sb);
if (source_alpha)
{
- pixel = XGetPixel(source_alpha->image,
- srect.x+col, srect.y+row);
+ pixel = XGetPixel(source_alpha->image,
+ srect.x + col, srect.y + row);
sa = (pixel >> _ashift) & _amask;
}
else
@@ -173,30 +173,37 @@
if (fraction < 1.0)
sa *= fraction;
- alpha = ((double) sa) / _amask;
+ sr *= sa;
+ sg *= sa;
+ sb *= sa;
+
+ ialpha = (_amask - sa);
// Now get dest pixel
- pixel = XGetPixel(dest_im->image, col, row);
- PixelToRGB (pixel, dr, dg, db);
+ pixel = XGetPixel(dest_im->image, col, row);
+ PixelToRGB(pixel, dr, dg, db);
+ dr *= ialpha;
+ dg *= ialpha;
+ db *= ialpha;
+
if (dest_alpha)
- {
+ {
pixel = XGetPixel(dest_alpha->image, col, row);
da = (pixel >> _ashift) & _amask;
- }
+ }
else // no alpha channel, background is opaque
da = _amask;
-
- ialpha = (1.0 - alpha);
- dr = (sr * alpha) + (dr * ialpha);
- dg = (sg * alpha) + (dg * ialpha);
- db = (sb * alpha) + (db * ialpha);
+
+ dr = (sr + dr) / _amask;
+ dg = (sg + dg) / _amask;
+ db = (sb + db) / _amask;
// calc final alpha
if (sa == _amask || da == _amask)
da = _amask;
else
- da = sa + (da * ialpha);
+ da = sa + ((da * ialpha) / _amask);
CLAMP(dr);
CLAMP(dg);
@@ -857,7 +864,7 @@
img.a = malloc(img.screen_w);
{
- unsigned long pixel;
+ unsigned long pixel;
/* Two cases, the *_FAST* method, which
is covered in the first a part of the if
@@ -911,24 +918,21 @@
unsigned short sg = (*gptr++ >> (8 - _gwidth));
unsigned short sb = (*bptr++ >> (8 - _bwidth));
unsigned short sa = (*aptr++ >> (8 - _awidth));
- unsigned dr, dg, db, da;
- double alpha = (double) sa / ((1 << _rwidth) - 1);
+ unsigned dr, dg, db, da; // dest
if (sa == 0) // dest wouldn't be changed
continue;
- /*
- * Unscale alpha value in each color component
- */
- if (sa < _amask)
+ if (sa == _amask) // source only, don't bother with the rest
{
- double multiplier = (double) _amask / sa;
-
- sr *= multiplier;
- sg *= multiplier;
- sb *= multiplier;
+ // Yes, this is duplicated code -- but it's worth it.
+ RGBToPixel(sr, sg, sb, pixel);
+ XPutPixel(dest_im->image, col, row, pixel);
+ if (dest_alpha)
+ XPutPixel(dest_alpha->image, col, row, sa << _ashift);
+ continue;
}
-
+
// get the destination pixel
pixel = XGetPixel(dest_im->image, col, row);
PixelToRGB(pixel, dr, dg, db);
@@ -940,24 +944,28 @@
}
else // no alpha channel, background is opaque
da = _amask;
-
- if (sa == _amask || da == 0) // source only
- {
- dr = sr;
- dg = sg;
- db = sb;
+
+ if (da == 0)
+ {
+ /*
+ * Unscale the colors
+ */
+ dr = (sr * _amask) / sa;
+ dg = (sg * _amask) / sa;
+ db = (sb * _amask) / sa;
da = sa;
}
else
{
- double ialpha = (1.0 - alpha);
- dr = (sr * alpha) + (dr * ialpha);
- dg = (sg * alpha) + (dg * ialpha);
- db = (sb * alpha) + (db * ialpha);
+ unsigned ialpha = _amask - sa;
+
+ dr = (sr * sa + (dr * ialpha)) / _amask;
+ dg = (sg * sa + (dg * ialpha)) / _amask;
+ db = (sb * sa + (db * ialpha)) / _amask;
if (da == _amask || da == _amask)
da = _amask;
else
- da = sa + (da * ialpha);
+ da = sa + ((da * ialpha) / _amask);
}
CLAMP(dr);