Converting BitmapImage to Bitmap and vice versa

C#.NetBitmap

C# Problem Overview


I have BitmapImage in C#. I need to do operations on image. For example grayscaling, adding text on image, etc.

I have found function in stackoverflow for grayscaling which accepts Bitmap and returns Bitmap.

So I need to convert BitmapImage to Bitmap, do operation and convert back.

How can I do this? Is this best way?

C# Solutions


Solution 1 - C#

There is no need to use foreign libraries.

Convert a BitmapImage to Bitmap:

private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
{
    // BitmapImage bitmapImage = new BitmapImage(new Uri("../Images/test.png", UriKind.Relative));

    using(MemoryStream outStream = new MemoryStream())
    {
        BitmapEncoder enc = new BmpBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create(bitmapImage));
        enc.Save(outStream);
        System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);

        return new Bitmap(bitmap);
    }
}

To convert the Bitmap back to a BitmapImage:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

private BitmapImage Bitmap2BitmapImage(Bitmap bitmap)
{
    IntPtr hBitmap = bitmap.GetHbitmap();
    BitmapImage retval;

    try
    {
        retval = (BitmapImage)Imaging.CreateBitmapSourceFromHBitmap(
                     hBitmap,
                     IntPtr.Zero,
                     Int32Rect.Empty,
                     BitmapSizeOptions.FromEmptyOptions());
    }
    finally
    {
        DeleteObject(hBitmap);
    }

    return retval;
}

Solution 2 - C#

Here's an extension method for converting a Bitmap to BitmapImage.

    public static BitmapImage ToBitmapImage(this Bitmap bitmap)
    {
        using (var memory = new MemoryStream())
        {
            bitmap.Save(memory, ImageFormat.Png);
            memory.Position = 0;

            var bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = memory;
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.EndInit();
            bitmapImage.Freeze();

            return bitmapImage;
        }
    }

Solution 3 - C#

If you just need to go from BitmapImage to Bitmap it's quite easy,

private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
	{
		return new Bitmap(bitmapImage.StreamSource);
	}

Solution 4 - C#

using System.Windows.Interop; ...

 private BitmapImage Bitmap2BitmapImage(Bitmap bitmap)
        {                
            BitmapSource i = Imaging.CreateBitmapSourceFromHBitmap(
                           bitmap.GetHbitmap(),
                           IntPtr.Zero,
                           Int32Rect.Empty,
                           BitmapSizeOptions.FromEmptyOptions());
            return (BitmapImage)i;
        }

Solution 5 - C#

I've just been trying to use the above in my code and I believe that there is a problem with the Bitmap2BitmapImage function (and possibly the other one as well).

using (MemoryStream ms = new MemoryStream())

Does the above line result in the stream being disposed of? Which means that the returned BitmapImage loses its content.

As I'm a WPF newbie I'm not sure that this is the correct technical explanation, but the code didn't work in my application until I removed the using directive.

Solution 6 - C#

Here the async version.

public static Task<BitmapSource> ToBitmapSourceAsync(this Bitmap bitmap)
{
    return Task.Run(() =>
    {
        using (System.IO.MemoryStream memory = new System.IO.MemoryStream())
        {
            bitmap.Save(memory, ImageFormat.Png);
            memory.Position = 0;
            BitmapImage bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = memory;
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.EndInit();
            bitmapImage.Freeze();
            return bitmapImage as BitmapSource;
        }
    });

}

Solution 7 - C#

Thanks Guillermo Hernandez, I created a variation of your code that works. I added the namespaces in this code for reference.

System.Reflection.Assembly theAsm = Assembly.LoadFrom("My.dll");
// Get a stream to the embedded resource
System.IO.Stream stream = theAsm.GetManifestResourceStream(@"picture.png");

// Here is the most important part:
System.Windows.Media.Imaging.BitmapImage bmi = new BitmapImage();
bmi.BeginInit();
bmi.StreamSource = stream;
bmi.EndInit();

Solution 8 - C#

This converts from System.Drawing.Bitmap to BitmapImage:

MemoryStream ms = new MemoryStream();
YOURBITMAP.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
BitmapImage image = new BitmapImage();
image.BeginInit();
ms.Seek(0, SeekOrigin.Begin);
image.StreamSource = ms;
image.EndInit();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTigran TokmajyanView Question on Stackoverflow
Solution 1 - C#Sascha HennigView Answer on Stackoverflow
Solution 2 - C#LawManView Answer on Stackoverflow
Solution 3 - C#C0bra5View Answer on Stackoverflow
Solution 4 - C#Aurelio López OvandoView Answer on Stackoverflow
Solution 5 - C#WolfsheadView Answer on Stackoverflow
Solution 6 - C#AndreasView Answer on Stackoverflow
Solution 7 - C#LawrenceView Answer on Stackoverflow
Solution 8 - C#Guillermo HernandezView Answer on Stackoverflow