Add one to use mul and cheap bit shift for multiplicaltion

Dec 13, 2010 at 5:01 PM

To further my own understanding I am trying to determine what the code below (occurs several times in the library) is actually doing and how it works, particularly the parts that are like: ((color.R * a) >> 8).  Please comment.

         // Add one to use mul and cheap bit shift for multiplicaltion
         var a = color.A + 1;
         var col = (color.A << 24)
                  | ((byte)((color.R * a) >> 8) << 16)
                  | ((byte)((color.G * a) >> 8) << 8)
                  | ((byte)((color.B * a) >> 8));
Coordinator
Dec 13, 2010 at 5:41 PM

The Writeablebitmap uses premultiplied ARGB (pARGB) as color information. That's why the alpha values has to be multiplied if Color values are used. I use some bit twiddling to avoid floating point arithmetics and stay with faster integer arithmetic.   

You can read more about premultiplied alpa here http://blogs.msdn.com/b/shawnhar/archive/2009/11/06/premultiplied-alpha.aspx

 

- Rene Schulte

Dec 13, 2010 at 6:34 PM
Edited Dec 13, 2010 at 6:36 PM

I have read the article at the link and several others but my understanding of premultiplied ARGB is woolly - the term 'bitchmaps' has come to mind as I've been sitting here struggling with it :)

If a have some images on my hard drive could they be stored in a premultiplied format - or is that a meaningless question?

If I loaded an array with pixel data from an image (i.e. one element per pixel, not split into channels) could it be or not be in premultiplied format  - or is that a meaningless question?

If I created 2 arrays both 4 times the size of my previous array and loaded the pixel data to each array split out into ARGB channels, then what would display in each array would depend on whether I premultiplied the RGB or not?  i.e. to one array I could extract just the straight ARGB information and in the other I could premultiply it - does this make any sense?

If it does, then what about a writeable bitmap, if I had a 10 pixel by 10 pixel writeable bitmap, are just 100 pixels stored in an array somewhere or is the pixel information split out internally in a premultiplied way and stored in separate channels, or is the premultiplied value for a channel calculated and returned by default when I request it in some way?

If I have an array of non-premultiplied pixel data do I have to premultiply it before loading it to a writeable bitmap in order that it will display properly?

Or am I just thinking about this in entirely the wrong way?

 

 

Coordinator
Dec 13, 2010 at 8:57 PM

Bitchmaps - lol.

pARGB is faster since the multiplication hasn't to be done each alpha blending in real-time. That's the reason why it's used.

When you set a pixel with alpha less than 255, you have to multiply the alpha value with each color component. When you want to get the pixel with an alpha != 255, you have to do the inverse. See the GetPixel and SetPixel methods that use the Color struct how to do this.

If you load a PNG image with the BitmapImage class and use it to initialize the WriteableBitmap via the appropriate ctor, everything is done for you. The WriteableBitmapEx library also handles everything for you. You only need to think about this when you are manually dealing with pixels and alpha values. 

 

- rene