bug-gnustep
[Top][All Lists]
Advanced

[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);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]