C# WriteableBitmapEx Pixels Premultiplying Bit-shifting
This is about extracting the RGB from a pixel value. Here is the code snippet:
Byte a = (Byte)(myColor >> 24);
// Prevent division by zero
UInt32 ai = a;
if (ai == 0)
{
ai = 1;
}
ai = ((255 << 8) / ai);
Byte bA = a;
Byte bR = (Byte)((((myColor >> 16) & 0xFF) * ai) >> 8);
Byte bG = (Byte)((((myColo开发者_Python百科r >> 8) & 0xFF) * ai) >> 8);
Byte bB = (Byte)((((myColor & 0xFF) * ai) >> 8));
I understand technically, i.e. at the level of bits, and binary what is going on. I understand in particular the 'Byte b# = (Byte)((((myColor >> n) & 0xFF)' parts. What I do not understand is the premultiplication (I mean the implementation here, not the theory). In particular I want to understand - and so to my questions:
- Why is 255 being shifted by 8 bits to the right and then devided by the alpha?
- Why is each value being multiplied by the result of this and then shifted 8 bits to the left?
This is done to increase the precision while using integer division. Reason to use integer operations could be for speed.
If MyColor = 0xAABBCCDD
AA = 170
BB = 187
CC = 204
DD = 221
Expected values:
bA = 170
bR = 187 * (255 / 170) = 280.5
bG = 204 * (255 / 170) = 306
bB = 221 * (255 / 170) = 331.5
with integer division 255/170, 255/204, 255/221 will all evaluate to 1 and premultiplication becomes ineffective.
By using this operation ai = ((255 << 8) / ai)
with integer division: ai = (255*256)/170 = 384
and subsequent multiplications and shifts gives you a more accurate result.
E.g.
bR = 187 * 384 / 256 = 280
bG = 204 * 384 / 256 = 306
bB = 221 * 384 / 256 = 331
Having said that I'm not convinced that this is a good formula for alpha premultiply.
If you are interested, and for more information read up on Fixed Point Arithmetic
精彩评论