My code is essentially attempting to create a video feed by constantly updating a BitmapImage that is binded to the UI (WPF). This means a bitmap is being converted to BitmapImage multiple times per second. However this is causing constant garbage collection (multiple times per second) which seems like a bad sign?
The bitmaps are being disposed of correctly its just the BitmapImage part which is causing the problem. I've tried writing to the BitmapImage instead of creating a new one, But once frozen it becomes Readonly. And if I unfreeze it I get Error: "Must create DependencySource on same Thread as the DependencyObject".
Below is the method I'm using to create a bitmap Image
//CapturedBitmapmapImage bound to the UI
CapturedBitmapImage = BitMap2BitMapImage(bitmap);
//Method for converting Bitmap to BitmapImage
public static BitmapImage BitMap2BitMapImage(Bitmap bitmap)
{
MemoryStream ms = new MemoryStream();
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
BitmapImage image = new BitmapImage();
image.BeginInit();
ms.Seek(0, SeekOrigin.Begin);
image.StreamSource = ms;
image.EndInit();
image.Freeze();
return image;
}
Instead of creating a new BitmapImage for each frame, you should use a WriteableBitmap that is once assigned to the Source property of an Image element.
int frameWidth = ...
int frameHeight = ...
var pixelFormat = PixelFormats.Bgr24; // must match Bitmap.PixelFormat
var writeableBitmap = new WriteableBitmap(
frameWidth, frameHeight, 96, 96, pixelFormat, null);
image.Source = writeableBitmap;
You would then cyclically update the WriteableBitmap (and hence also the Image element) from a Bitmap like this:
Bitmap bitmap = ... // a frame
var bitmapData = bitmap.LockBits(
new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);
image.Dispatcher.Invoke(() => writeableBitmap.WritePixels(
new Int32Rect(0, 0, bitmap.Width, bitmap.Height),
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride));
bitmap.UnlockBits(bitmapData);