nanogui: Re: [FIX] add alpha channel into GdDrawImage software handling
Subject:
Re: [nanogui] Re: Re: [FIX] add alpha channel into GdDrawImage software handling
From:
"Greg Haerr" ####@####.####
Date:
22 Mar 2010 22:38:50 -0000
Message-Id: <0a1c01caca10$6f7c3920$6564a8c0@winXP>
> Why? I can see no value in beeing accurate here, because:
> a) The error of dividing by 256 instead of 255 gives you an
> amplitude error of 0,4%. Nobody will see this - never.
>
> b) You are not accurate at all. You are doing integer division,
> without rounding. This will give you another 0,2% (max).
Wolfgang - thanks for your excellent comments!
In looking much further into alpha blending and optimizations,
I agree with you. The original integer alpha blend contained
two multiplies and one divide:
bg = (a*fg + (255-a)*bg)/255;
This can be rearranged algebraically without loss of any accuracy to
one multiply and one divide:
bg = ((a*(fg-bg))/255 + bg;
Finally, the divide can be replaced by an increment and
shift, providing 92% accuracy, and still exact at alpha 0
and 255. This is very fast and accurate for the fully
translucent and opaque cases:
bg = ((a*(fg-bg+1))>>8 + bg;
I have tested all the above, and developed a macro
for the alpha blend using:
#define muldiv255(a,b) (((a)*(b)/255) /* slow divide*/
#define muldiv255(a,b) (((a)*(b+1))>>8) /* fast, 92% accurate*/
allowing the alpha blend to take a very fast form:
bg += muldiv255(a, fg-bg);
> If accuracy is a problem, why not doing:
> alpha *= 257; // alpha == 0..65535
> color = (alpha * fg + (65535-alpha) * bg) >> 16;
Good idea. However, the above muldiv255 is faster with one
less multiply. All these methods, including yours, are
compared in an interesting article:
http://my.opera.com/Vorlath/blog/2006/12/20/project-v-advanced-alpha-blending
> An optimized loop will look very different, with very much code
> duplication....
Agreed.
Regards,
Greg