I capture images from my web camera to Image control in WPF with WebCam_Capture.dll. For every captured frame i have event called webCam_imageCaptured. It calls every time when i receive new image from web camera. In this event I call method LoadBitmap to get hBitmap and receive BitmapSource to put this captured picture to the Image control.
Here is code of this method:
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr handle);
public BitmapSource bs;
public IntPtr ip;
public BitmapSource LoadBitmap(System.Drawing.Bitmap source)
{
ip = source.GetHbitmap();
bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip, IntPtr.Zero, System.Windows.Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ip);
return bs;
}
And here is the code of the event:
private void webcam_ImageCaptured(object source, WebcamEventArgs e)
{
//_frameImage is Image WPF control.
_frameImage.Source = LoadBitmap((System.Drawing.Bitmap)e.WebCamImage);
}
And I have a leak here! RAM loads up to 1 GB and sometimes more! DeleteObject(ip) works not every time when it called. When RAM is 1 GB or more, it releases or show me Out of memory error. How to solve this?
Without the aid of a profiler or even seeing the rest of your code, I can almost guarantee that the “leak” is here:
That method is certainly being called very quickly and you are not
Dispose()ing of yourBitmaps. The GC won’t have time to come clean up after you and call the finalizer on eachBitmap, so you run out of memory.You need to call
Dispose()on thatBitmapafter you’re done with it. TheBitmapSourcemakes a copy of the image data anyway, so it shouldn’t be needed. I would try this:This of course assumes that disposing of the bitmap inside this event handler is a valid thing to do (i.e., does anyone else handle this event?) You may want to expose a
BitmapSourcein theWebCamEventArgsclass instead so that you can make sure no other clients are relying on thatBitmapremaining valid.That is of course if you wrote the API to being with. If not you could write a wrapper to make sure your code never actually sees a
Bitmapand deals only with WPF image types.