Robin Rodricks
Robin Rodricks

Reputation: 113976

Speed - Copy bitmap data into array or work with it directly?

I'm using a LockedBitmap class that simplifies working with bitmap data in C#. Currently it is copying the data into a local byte[] array which is then accessed by its class methods to get/set pixel color values.

Is this faster or better than accessing the locked bitmap data directly via the pointer? Is a copy needed at all?

Edit: I'm not asking if its possible to directly work with bitmap data, I work with this everyday. I'm just asking for a comparison between the 2 methods and if its necessary at all to copy pixel data.


Copying pixel data into a temp array:

// create byte array to copy pixel values
int step = Depth / 8;
Pixels = new byte[PixelCount * step];
Iptr = bitmapData.Scan0;

// Copy data from pointer to array
Marshal.Copy(Iptr, Pixels, 0, Pixels.Length);

Directly reading pixel values:

byte* p = (byte*)(void*)bmData.Scan0.ToPointer();
int ws = bmData.Stride;
byte* row = &p[i * ws];
byte Gcolor = row[j];
byte Bcolor = row[j + 1];
byte Rcolor = row[j + 2];

Upvotes: 3

Views: 7260

Answers (2)

Rotem
Rotem

Reputation: 21917

Is this faster or better than accessing the locked bitmap data directly via the pointer?

No. It requires an additional copy operation, and then another operation to copy the processed values back to the bitmap.

Is a copy needed at all?

Only in an environment where unsafe code is undesired or unavailable.

Upvotes: 3

David Hope
David Hope

Reputation: 2256

You can definitely operate directly on the bitmap data without copying it. Here is some code that I used to pull in a customer 16bpp gray scale format into a displayable bitmap:

    Rectangle rect = new Rectangle(0, 0, bmOut.Width, bmOut.Height);
    System.Drawing.Imaging.BitmapData bmpData =
        bmOut.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
        bmOut.PixelFormat);
    IntPtr ptr = bmpData.Scan0;
    Byte[] bytes;

    bytes = rawIn.ReadBytes(framesize);

    for (int x = 0; x < bytes.Length; x += 2)
    {
        short[] rgb = new short[3];
        int value = bytes[x + 1] * 256 + bytes[x];
        //value = value / 32;
        value = iMax * (value - iMin) / (iMax - iMin);

        if (value < iMin)
        {
            value = iMin;
        }
        else if (value > iMax)
        {
            value = iMax;
        }

        value = 65536 * (value - iMin) / (iMax - iMin);

        rgb[0] = rgb[1] = rgb[2] = (short)(value);
        System.Runtime.InteropServices.Marshal.Copy(rgb, 0, ptr + (x) * 3, 3);

    }
    bmOut.UnlockBits(bmpData);

The key is the LockBits and UnlockBits

As a quick explanation, I'm reading 16bpp from the file into bytes, reconstructing the 16 bits into value. Then, using externally supplied iMin and iMax scaling to get the shading right. Then taking that single value and constructing the RGB and using the Marshal.Copy to put it into the bitmap.

Upvotes: 2

Related Questions