Best Method for Pixel Manipulation

Jul 27, 2011 at 5:49 PM

I have a byte array of alpha values and a WriteableBitmap I want to apply those alpha values to. My current solution is something like:

 

for(int x = 0; x < width; x++)

{

for (int y = 0; y < height; y++)

{

var pixel = WriteableBitmap.GetPixel(x, y);

pixel.A = array[x, y];

WriteableBitmap.SetPixel(x, y, pixel);

}

}

 

I could pull out the GetPixel/SetPixel logic for a small speed boost but I feel like something like a Buffer.BlockCopy could be much faster than what I'm doing. I just don't know how to go about implementing it. Any suggestions are welcome, thanks.

Coordinator
Jul 27, 2011 at 6:33 PM

Don't use the Get/Set Pixel calls. Just access the pixels via the index of the Pixels property (inline get set pixel). Go through the code of the project and see how it's done. Use a local var for the Pixels property!

BTW, Block Copy won't work, since you're manipulating each pixel and don't just copy a batch of those.

 

- Rene Schulte

Jul 27, 2011 at 7:28 PM
Edited Jul 28, 2011 at 10:08 PM

This is what I have now, is there a more efficient way to bypass using a color? Sorry I'm so clueless when it comes to bitwise manipulation.

 

int[] pixels = WriteableBitmap.Pixels;
                               
for (int y = 0; y < height; y++)
{

   // Assume this is initialized
   byte[] alphaBytes = new byte[#];

   for (int x = 0; x < width; x++)
   {
         var c = pixels[((height - 1) - y) * width + x];
         var a = (byte)(c >> 24);

         // Prevent division by zero
         int ai = a;
         if (ai == 0)
         {
            ai = 1;
         }

         // Scale inverse alpha to use cheap integer mul bit shift
         ai = ((255 << 8) / ai);
         var color = Color.FromArgb(a,
               (byte)((((c >> 16) & 0xFF) * ai) >> 8),
               (byte)((((c >> 8) & 0xFF) * ai) >> 8),
               (byte)((((c & 0xFF) * ai) >> 8)));

         color.A = alphaBytes[x];

         var a2 = color.A + 1;
         pixels[((height - 1) - y) * width + x] = (color.A << 24)
               | ((byte)((color.R * a2) >> 8) << 16)
               | ((byte)((color.G * a2) >> 8) << 8)
               | ((byte)((color.B * a2) >> 8));
    }
}