tags:

views:

1795

answers:

2

I am trying to dynamically create a Bitmap Image using byte array using following code

Bitmap GetImage()
{
    IntPtr  ip = Marshal.AllocCoTaskMem(imagesize);

    //some code to fill ip

    Image img =  new Bitmap(
                    w,
                    h,
                    -stride,
                    PixelFormat.Format24bppRgb,
                    (IntPtr)(ip.ToInt32() + imagesize - stride)
                    );

    Marshal.FreeCoTaskMem( ip); // Comment this line to work

    return img;
}

void SaveImage()
{
    Image img =  GetImage();
    img.save("test.bmp"); // This call fails
    img.Dispose();
}

Now my problem is I want to return a Bitmap but at the same time I don't want to keep the ip pointer as that memory allocated leaks. It is never freed. How can I return a Image created with bytes array and without bothering the caller of the function GetImage() to free up the memory.

+3  A: 

The simplest way may be to create the bitmap (although in similar code I've used a normal byte[] and then a fixed block, rather than directly using AllocCoTaskMem), and then create a second Bitmap of the same size. Call Graphics.FromImage on the second bitmap, then Graphics.DrawImage using the first bitmap to effectively copy the contents of the first bitmap onto the second. You can then call Dispose on the first bitmap, release the memory, and use the second bitmap which is basically a copy.

There may well be a more efficient way to do it if you're more proficient with image stuff, but if you're just looking for a way to get it to work, it's a starting point :)

EDIT: zachrrs's comment does indeed make things easier using the Bitmap(Image) constructor:

using (Bitmap original = new Bitmap(...))
{
    Bitmap copy = new Bitmap(originalImage);
    // Then return "copy" from your method, and you can free the
    // memory
}
Jon Skeet
I am getting the data from a unmanaged buffer which is nothing but DirectX SampleGrabber Filter thats the reason I am using AllocCoTaskMem
Ankit
Fair enough :) Hope this works out for you. Let me know if you need a more complete sample.
Jon Skeet
You don't need to create an intermediary Graphics object, just create a new Bitmap instance with the original Bitmap instance in the constructor.
pyrochild
Yes it worked. Thanks. I tried .Clone() but it didnt help can u explain why ?
Ankit
A: 

If you know the dimensions in advance, why not creating the bitmap and use the Bitmap.LockBits method to get the input buffer address?

Lucero