Coder Perfect

Use a System to load a WPF BitmapImage. Drawing. Bitmap


I’ve got a System instance. Drawing. I have a Bitmap that I’d like to make available to my WPF app as a System. Windows.Media.Imaging. BitmapImage.

What would be the best course of action in this situation?

Asked by Kevin

Solution #1

Why don’t you load it from MemoryStream?

using(MemoryStream memory = new MemoryStream())
    bitmap.Save(memory, ImageFormat.Png);
    memory.Position = 0;
    BitmapImage bitmapImage = new BitmapImage();
    bitmapImage.StreamSource = memory;
    bitmapImage.CacheOption = BitmapCacheOption.OnLoad;

Answered by Pawel Lesnikowski

Solution #2

Here’s the code I came up with, thanks to Hallgrim:

ScreenCapture = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
   BitmapSizeOptions.FromWidthAndHeight(width, height));

In addition, instead of a BitmapImage, like in my initial question, I ended up binding to a BitmapSource.

Answered by Kevin

Solution #3

I know this has already been answered, but here are a few of extension methods that accomplish the conversion (for.NET 3.0+).

        /// <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 = 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();

            bitSrc = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
        catch (Win32Exception)
            bitSrc = null;

        return bitSrc;

, as well as the NativeMethods class (to appease FxCop)

    /// <summary>
/// FxCop requires all Marshalled functions to be in a class called NativeMethods.
/// </summary>
internal static class NativeMethods

[return: MarshalAs(UnmanagedType.Bool)]

internal static extern bool DeleteObject(IntPtr hObject); }

Answered by Alastair Pitts

Solution #4

It took me some time to figure out how to make the conversion work in both directions, so here are the two techniques I came up with:

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Media.Imaging;

public static class BitmapConversion {

    public static Bitmap ToWinFormsBitmap(this BitmapSource bitmapsource) {
        using (MemoryStream stream = new MemoryStream()) {
            BitmapEncoder enc = new BmpBitmapEncoder();

            using (var tempBitmap = new Bitmap(stream)) {
                // According to MSDN, one "must keep the stream open for the lifetime of the Bitmap."
                // So we return a copy of the new bitmap, allowing us to dispose both the bitmap and the stream.
                return new Bitmap(tempBitmap);

    public static BitmapSource ToWpfBitmap(this Bitmap bitmap) {
        using (MemoryStream stream = new MemoryStream()) {
            bitmap.Save(stream, ImageFormat.Bmp);

            stream.Position = 0;
            BitmapImage result = new BitmapImage();
            // According to MSDN, "The default OnDemand cache option retains access to the stream until the image is needed."
            // Force the bitmap to load right now so we can dispose the stream.
            result.CacheOption = BitmapCacheOption.OnLoad;
            result.StreamSource = stream;
            return result;

Answered by Daniel Wolf

Solution #5

The simplest option is to create the WPF bitmap directly from a file.

Otherwise, you’ll have no choice but to use System. Windows.Interop.Imaging. CreateBitmapSourceFromHBitmap.

Answered by Hallgrim

Post is based on