I have an instance of a System.Drawing.Bitmap and would like to make it available to my WPF app in the form of a System.Windows.Media.Imaging.BitmapImage.
What would be the best approach for this?
I have an instance of a System.Drawing.Bitmap and would like to make it available to my WPF app in the form of a System.Windows.Media.Imaging.BitmapImage.
What would be the best approach for this?
The easiest thing is if you can make the WPF bitmap from a file directly.
Otherwise you will have to use System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap.
I work at an imaging vendor and wrote an adapter for WPF to our image format which is similar to a System.Drawing.Bitmap.
I wrote this KB to explain it to our customers:
http://www.atalasoft.com/kb/article.aspx?id=10156
And there is code there that does it. You need to replace AtalaImage with Bitmap and do the equivalent thing that we are doing -- it should be pretty straightforward.
Thanks to Hallgrim, here is the code I ended up with:
ScreenCapture = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(width, height));
I also ended up binding to a BitmapSource instead of a BitmapImage as in my original question
How about loading it from MemoryStream?
MemoryStream ms = new MemoryStream();
bitmap.Save(ms, ImageFormat.Png);
ms.Position = 0;
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
I know this has been answered, but here is an couple of extension methods (for .NET 3.0+) that do the conversion. :)
/// <summary>
/// Converts a <see cref="System.Drawing.Image"/> into a WPF <see cref="BitmapSource"/>.
/// </summary>
/// <param name="source">The source image.</param>
/// <returns>A BitmapSource</returns>
public static BitmapSource ToBitmapSource(this System.Drawing.Image source)
{
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(source);
var bitSrc = bitmap.ToBitmapSource();
bitmap.Dispose();
bitmap = null;
return bitSrc;
}
/// <summary>
/// Converts a <see cref="System.Drawing.Bitmap"/> into a WPF <see cref="BitmapSource"/>.
/// </summary>
/// <remarks>Uses GDI to do the conversion. Hence the call to the marshalled DeleteObject.
/// </remarks>
/// <param name="source">The source bitmap.</param>
/// <returns>A BitmapSource</returns>
public static BitmapSource ToBitmapSource(this System.Drawing.Bitmap source)
{
BitmapSource bitSrc = null;
var hBitmap = source.GetHbitmap();
try
{
bitSrc = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
catch (Win32Exception)
{
bitSrc = null;
}
finally
{
NativeMethods.DeleteObject(hBitmap);
}
return bitSrc;
}
and the NativeMethods class (to appease FxCop)
/// <summary>
/// FxCop requires all Marshalled functions to be in a class called NativeMethods.
/// </summary>
internal static class NativeMethods
{
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DeleteObject(IntPtr hObject);
}
I know this is old, but the solution offered in 5 will lead to memory leaks as is. Check out:
http://stackoverflow.com/questions/1546091/wpf-createbitmapsourcefromhbitmap-memory-leak