|
From: Stephan A. <sup...@gm...> - 2004-06-18 08:27:01
|
Hi Maxim, > I could reproduce your result with 0...255 range. Yes, it might be > less accurate, but it looks exactly the same as in your "linear" > blending > picture. It might well be that my code is flawed and doesn't offer any additional precision. > > 1: top alpha == 255 or bottom alpha == 0, resulting color = top > > color > > 2: bottom alpha == 255, equation is much simpler, in fact it is > > what I > > think you're doing > > 3: bottom alpha != 255, here we have to use a different equation, > > and I > > think you're not handling this correctly. > > There are 3 cases, but there is only "top" alpha counts. If it's 255, > it's > opaque, including alpha, if it's 0 it doesn't have any effect. > Intermediate > values blend. > > > 3: bottom alpha != 255, here we have to use a different equation, > > and I > > think you're not handling this correctly. > > It might be. Although, the formulae (yours and mine) are essentially > the same. > I just optimized it to use one MUL instead of two. t*a + b*(1-a) is > the same as b+(t-b)*a (in terms of 0...1 range). There might be > slight > difference with rounding, tho. But even if it's incorrect, you can > always > replace it with your own, not modifying existing (possibly wrong) > code. I think you're wrong assuming only top alpha counts. Consider the case of bottom alpha to be 0. This is by implication an invalid or undefined color. If by pure chance the bottom color resembles black, you're blending to black background, where as you really should just assign the top color to the pixel ignoring the bottom color completely. The situation stays the same for increasing bottom pixel alpha, the influence of the bottom color should be wheighted by the bottom alpha. Of course for rgb24, you're code is absolutely correct, as there is no such thing as bottom pixel alpha. For rgba32, there should be an additional case. Pixel I with color A and alpha a contributes a*A color to the image one, A' Pixel J with color B and alpha b contributes b*B color to the image two, B' When blending pixel J over pixel I, you could say that J allows (1-b) percent of pixel I to shine through. Thus, the formular for correct alpha blending is this: C' = B' + (1-b)A' C' = b*B + (1-b) * a*A C is optained by dividing C' by the resulting alpha c which is optained by c = b + (1-b) * a I also think it is really worth looking into what Marc Van Olmen wrote. I knew of that trick but never really put it to use because at the time I read about it, I didn't know my way arround that level of byte juggling. Where I read about it, it was called Packed Multiply. The idea is similar to SIMD, only for portable C code. Of course it works only for uint8 calulations. I'm going to explain it in my words, because for me, the code Marc posted takes a second look to understand it. Basically you put 2 uint8 values in the first and third byte of a uint32. Then you do the multiplication by a uint8 value, now your two values have 16 bit results in the first half and second half of the uint32, to scale them correctly, you shift by one byte to the right and mask out the lower half of the upper value, which is now in the upper half of the lower value. Now you're back to two uint8 on byte one and three of the uint32. I think that should work on both big endian and little endian machines. Regards, -Stephan |