SetPixel Alpha Behavior

Feb 26, 2010 at 4:10 AM

 

Thanks for creating this library, it has saved me a ton of work.

I am not a graphics expert so maybe this is common in teh field but I do not understand why the SetPixel method will scale the value of R, G & B with the value of Alpha. In other words, SetPixel does not seem to set the values of Alpha, R, G & B as passed on its parameters but rather it will set to the values of R, G & B as scaled by Alpha.

For example, it is not posible to set a pixel to #80FFFFFF by calling SetPixel(128, 255, 255, 255). This value is valid and would represent a White pixel with 50% transparency.

Am I misunderstading the behavior? If I understand it correctly, why is this behavior implemented instead of the direct use of Alpha, R, G & B in the parameters?

It also appears as if BlendMode.AlphaBlend relies on the sourcePixel having R, G * B that are always equal or smaller than Alpha.

Thanks for any clarification you can provide on this.

ercercerc

Coordinator
Feb 26, 2010 at 8:17 AM

Thanks for the feedback and glad it helped you.

The WriteableBitmap uses pre-multiplied alpha values (pARGB). From the MSDN:

When assigning colors to pixels in your bitmap, use pre-multiplied colors.

Nokola wrote a nice blog post where explains it well: The Most Important Silverlight WriteableBitmap Gotcha - Does It Lose/Change Colors?

Why do you think that "BlendMode.AlphaBlend relies on the sourcePixel having R, G * B that are always equal or smaller than Alpha" ?

 

BTW, I'm curious to know for what you use it. Do you have something online?

Feb 26, 2010 at 2:22 PM

 

Got it, I will read more about pre-multiplied alpha values.

My comment on AlphaBlend comes from the equation to determine destPixel (below) which does not have any upper-bound checking. For example, if you had destPixel #FFFFFFFF (opaque white) and sourcePixel #800000FF (50% blue) you would get overflow (wraparound) on the blue component. I haven't tested this so maybe my code inspection is wrong.

As for my application, it is just food for my programming hobby hunger. There is a very early version at www.monto.me but there are no instructions or a real UI yet. I will let youknow if it gets to a usable stage.

Last question: is there any reference that further explains the fast-divide-by-255 trick?

ercercerc

 

destPixel =

((sa + (((da * (255 - sa)) * 0x8081) >> 23)) << 24) |

((sr + (((dr * (255 - sa)) * 0x8081) >> 23)) << 16) |

((sg + (((dg * (255 - sa)) * 0x8081) >> 23)) << 8) |

((sb + (((db * (255 - sa)) * 0x8081) >> 23)) ) ;

Developer
Feb 26, 2010 at 8:01 PM

sa, sr, sg, sb, da, dr, dg, and db are all 0-255, so you can't get wraparound. I'm looking for the original doc where I found the divide algorithm, having trouble finding it right now.

Feb 26, 2010 at 10:01 PM

 

In pre-multiplied-alpha format the values of R, G & B cannot exceed the value of Alpha. With this condition the equation does not produce wraparound.

My comment only applies if R, G, B & Alpha are all independent values, like in a PNG. In this case you would have wraparound when any of the color components in sourcePixel is greater than its Alpha.

For example, with dextPixel 0xFFFFFF00 and sourcePixel 0x800000FF you get wraparound on B. The equation returns 0xff7f7fff instead of the correct 0xff7f7f7f.

The above example is invalid in the case of this library as sourcePixel does not meet the format of a pre-multiplied-alpha since B is greater than Alpha.

ercercerc

Mar 5, 2010 at 1:23 AM

 

I updated the app in which I am using a modified version of this library. The UI is embarrasingly complicated, not really designed yet. But the basic functionality is there.

Feel free to try it at at www.monto.me  Try loading one of the saved canvases to see the type of output I am after.

Thanks again for making this work available.

ercercerc

Apr 3, 2010 at 5:11 PM

 

I finally got around to updating the UI and doing some more performance work. The current (far from good-enough) version is at www.monto.me

I need to provide hue/saturation/brightness/contrast for the backgrounds and I want to do that real-time as the user adjusts some sliders. The routines I found were not fast enough so I created a fixed-point set of functions using integer math. I will integrate them into the app and can post the code if of interest to someone.

Thanks again for having created this library, it has been of great use to me.

ercercerc

Coordinator
Apr 5, 2010 at 7:47 PM

Cool app and I'm always interested in some fast algorithmic code.  :)