开发者

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:

  1. Why is 255 being shifted by 8 bits to the right and then devided by the alpha?
  2. 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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜