How to make ARGB transparency using bitwise operators

I need to do transparency with 2 pixels:

pixel1: {A, R, G, B} - foreground pixel
pixel2: {A, R, G, B} - background pixel

A, R, G, B - byte values

each color is represented by a byte value

Now I calculate the transparency as:

newR = pixel2_R * alpha / 255 + pixel1_R * (255 - alpha) / 255
newG = pixel2_G * alpha / 255 + pixel1_G * (255 - alpha) / 255
newB = pixel2_B * alpha / 255 + pixel1_B * (255 - alpha) / 255

but it's too slow I need to do this with bitwise operators ( AND, OR, XOR, NEGATION, BIT MOVE )

I want to do this on Windows Phone 7 XNA

--- C # code ---

    public static uint GetPixelForOpacity(uint reduceOpacityLevel, uint pixelBackground, uint pixelForeground, uint pixelCanvasAlpha)
    {
        byte surfaceR = (byte)((pixelForeground & 0x00FF0000) >> 16);
        byte surfaceG = (byte)((pixelForeground & 0x0000FF00) >> 8);
        byte surfaceB = (byte)((pixelForeground & 0x000000FF));

        byte sourceR = (byte)((pixelBackground & 0x00FF0000) >> 16);
        byte sourceG = (byte)((pixelBackground & 0x0000FF00) >> 8);
        byte sourceB = (byte)((pixelBackground & 0x000000FF));

        uint newR = sourceR * pixelCanvasAlpha / 256 + surfaceR * (255 - pixelCanvasAlpha) / 256;
        uint newG = sourceG * pixelCanvasAlpha / 256 + surfaceG * (255 - pixelCanvasAlpha) / 256;
        uint newB = sourceB * pixelCanvasAlpha / 256 + surfaceB * (255 - pixelCanvasAlpha) / 256;

        return (uint)255 << 24 | newR << 16 | newG << 8 | newB;
    }
+3
source share
2 answers

You cannot use an 8-bit alpha mix using only bitwise operations, unless you basically invent multiplication with basic ops (8 shift-add).

, : 256 255 . , . , : , , , . :

: 256x256 - 64 . . , , . , -, A → 3, 32x256 = 8 , .

256 255: , 256, - ​​ 8. , , , R = 255, A = 255, ( R * A)/256 = 254. : (R * A + R + A)/256 (R * A + R)/256 (R * A + A)/256 = 255. , A 0..256, : A = (256 * A)/255. divide-by-255 6. (R * A)/256 = 255.

+3

, , . , , LUT ( LUT , )

// allocate the LUT (64KB)
unsigned char lut[256*256] __cacheline_aligned; // __cacheline_aligned is a GCC-ism

// macro to access the LUT
#define LUT(pixel, alpha) (lut[(alpha)*256+(pixel)])

// precompute the LUT
for (int alpha_value=0; alpha_value<256; alpha_value++) {
  for (int pixel_value=0; pixel_value<256; pixel_value++) {
    LUT(pixel_value, alpha_value) = (unsigned char)((double)(pixel_value) * (double)(alpha_value) / 255.0));
  }
}

// in the loop
unsigned char ialpha = 255-alpha;
newR = LUT(pixel2_R, alpha) + LUT(pixel1_R, ialpha);
newG = LUT(pixel2_G, alpha) + LUT(pixel1_G, ialpha);
newB = LUT(pixel2_B, alpha) + LUT(pixel1_B, ialpha);

. . , , .

0

All Articles