tags:

views:

13691

answers:

6

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?

+2  A: 

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.

Hallgrim
+1  A: 

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.

Lou Franco
Thanks Lou - was able to do what I needed with one line of code
Kevin
+8  A: 

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

Kevin
Great! Why don't you select your own answer as the answer to the question? Your's is much better now.
Hallgrim
Since yours is the accepted answer already, you could edit your answer to make it more complete.
Alan Jackson
Do mind that this code leaks a HBitmap. See http://stackoverflow.com/questions/1118496/using-image-control-in-wpf-to-display-system-drawing-bitmap/1118557#1118557 for a fix
Lars Truijens
+16  A: 

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();
Pawel Lesnikowski
You could add this code as an extension method on System.Drawing.Bitmap, something like ToBitmapImage()
Luke Puplett
Using ImageFormat.Bmp is an order of magnitude faster.
RandomEngy
In case others are having problems with this code:I had to add `ms.Seek(0, SeekOrigin.Begin);` before setting `bi.StreamSource`. I'm using .NET 4.0.
mlsteeves
@mls that would be true of any version of .net. I'm gonna sneak in there and fix that code; nobody tell Pawel.
Will
+9  A: 

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);
}
Alastair Pitts
A: 

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

Larry