tags:

views:

57

answers:

1

Hi All,

I am trying to implement a Photoshop style color filtering feature in my application. I have a Bitmap, and 4 check-boxes (R,G,B,A). I wanted to know what is the fastest way of doing it

Currently I am doing it as follows

        Byte[] rgbValues = new Byte[data.Stride * data.Height];
        for (int row = 0; row < data.Height; row++)
        {
            // Loop through each pixel on this scan line
            int bufPos = (m_height - row - 1) * m_width;
            int index = row * data.Stride;
            for (int col = 0; col < data.Width; col++, bufPos++, index += 4)
            {
                bool drawCheckerBoard = true; // for alpha
                UInt32 rgba = m_image[bufPos];
                UInt32 r =  EnableRedChannel ? ((rgba >> 0) & 0xFF) : 0x00;
                UInt32 g =  EnableGreenChannel ? ((rgba >> 8) & 0xFF) : 0x00;
                UInt32 b =  EnableBlueChannel ? ((rgba >> 16) & 0xFF) : 0x00;
                UInt32 a = (rgba >> 24) & 0xFF;
                ...
                ...
            }
        }

and then the usual Marshal.Copy and unlock bits etc...

As you can see it is not really an optimized way, I wanted some suggestions for a faster method.

Thanks

A: 

It's unclear what you want to do with the individual r,g,b & a values, but one thing I see right off is that you can move your enable flags out of the loop.

   UInt32 rMask = EnableRedChannel   ? 0x000000FF : 00;
   UInt32 gMask = EnableGreenChannel ? 0x0000FF00 : 00;
   UInt32 bMask = EnableBlueChannel  ? 0x00FF0000 : 00;
   UInt32 aMask = 0xFF000000;

   for (int row = 0; row < data.Height; row++)
    {
        // Loop through each pixel on this scan line
        int bufPos = (m_height - row - 1) * m_width;
        int index = row * data.Stride;
        for (int col = 0; col < data.Width; col++, bufPos++, index += 4)
        {
            bool drawCheckerBoard = true; // for alpha
            UInt32 rgba = m_image[bufPos];
            UInt32 r =  (rgba & aMask) >> 0;
            UInt32 g =  (rgba & gMask) >> 8;
            UInt32 b =  (rgba & bMask) >> 16;
            UInt32 a =  (rgba & aMask) >> 24;
            ...
            ...
        }
    }

Going one step beyond that, you can build a composite mask if you don't actually need to pull out the r,g,b& a values.

   UInt32 mask  = 0xFF000000;
   if (EnableRedChannel)
      mask |= 0x000000FF;
   if (EnableGreenChannel)
      mask |= 0x0000FF00;
   if (EnableBlueChannel)
      mask |= 0x00FF0000;

   for (int row = 0; row < data.Height; row++)
    {
        // Loop through each pixel on this scan line
        int bufPos = (m_height - row - 1) * m_width;
        int index = row * data.Stride;
        for (int col = 0; col < data.Width; col++, bufPos++, index += 4)
        {
            bool drawCheckerBoard = true; // for alpha
            UInt32 rgba = m_image[bufPos] & mask;
            ...
            ...
        }
    }

You might also find it helpful to have your of your m_image[] be an array of bytes, this would make it easier to pick out the individual color channels just by adjusting your offset and stride through the data.

John Knoeller
Thanks.. Will try that...
ofarooq