Reputation: 663
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.
Upvotes: 2
Views: 4761
Reputation: 1503439
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
}
Upvotes: 4
Reputation: 60276
If you know the dimensions in advance, why not creating the bitmap and use the Bitmap.LockBits method to get the input buffer address?
Upvotes: 0