50

As far as I can tell the only way to convert from BitmapSource to Bitmap is through unsafe code... Like this (from Lesters WPF blog):

myBitmapSource.CopyPixels(bits, stride, 0); unsafe { fixed (byte* pBits = bits) { IntPtr ptr = new IntPtr(pBits); System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap( width, height, stride, System.Drawing.Imaging.PixelFormat.Format32bppPArgb,ptr); return bitmap; } } 

To do the reverse:

System.Windows.Media.Imaging.BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); 

Is there an easier way in the framework? And what is the reason it isn't in there (if it's not)? I would think it's fairly usable.

The reason I need it is because I use AForge to do certain image operations in an WPF app. WPF wants to show BitmapSource/ImageSource but AForge works on Bitmaps.

3
  • 10
    To do the reverse, you really must delete the bitmap handle you get with GetHbitmap. This bug is all over the internet. It's unfixable. The world is slowly leaking GDI handles; we'll soon be swimming in them! Commented Dec 31, 2011 at 4:25
  • 2
    romkyns is referring to this: stackoverflow.com/questions/1546091/… Commented Apr 26, 2012 at 21:24
  • If you do not want to create a copy in memory a sharedbitmapsource is what you want. stackoverflow.com/a/32841840/690656 Commented Oct 28, 2015 at 10:16

6 Answers 6

76

It is possible to do without using unsafe code by using Bitmap.LockBits and copy the pixels from the BitmapSource straight to the Bitmap

Bitmap GetBitmap(BitmapSource source) { Bitmap bmp = new Bitmap( source.PixelWidth, source.PixelHeight, PixelFormat.Format32bppPArgb); BitmapData data = bmp.LockBits( new Rectangle(Point.Empty, bmp.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppPArgb); source.CopyPixels( Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride); bmp.UnlockBits(data); return bmp; } 
Sign up to request clarification or add additional context in comments.

8 Comments

That would work only if the pixel format is known beforehand, its pretty much the way I went with and additional function to map between pixel formats.
Does this work with WPF? The Bitmap seems to come from System.Drawing and used in WinForms. The BitmapSource is used in WPF though.
The code above is used to convert a WPF BitmapSource to a Windows Forms Bitmap, the code should "work" in WPF, provided the correct assemblies are referenced, however it will not be very useful since if you already have a BitmapSource you can use it directly in WPF.
If both Windows.Media and System.Drawing.Imaging are referenced in the file, that PixelFormat should be specifically written out as System.Drawing.Imaging.PixelFormat though. Same thing with System.Drawing.Point.
At minimum there should be code to check the Bitmap format and convert it or you'll lose transparency (among other things). Or at least use PixelFormat.Format32bppArgb which seems to be the most common format for clipboard images from the Web browser. Here's the version I use: gist.github.com/RickStrahl/fe395578bb0f95e63cb65011fc207fc1
|
45

You can just use these two methods:

public static BitmapSource ConvertBitmap(Bitmap source) { return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( source.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } public static Bitmap BitmapFromSource(BitmapSource bitmapsource) { Bitmap bitmap; using (var outStream = new MemoryStream()) { BitmapEncoder enc = new BmpBitmapEncoder(); enc.Frames.Add(BitmapFrame.Create(bitmapsource)); enc.Save(outStream); bitmap = new Bitmap(outStream); } return bitmap; } 

It works perfectly for me.

5 Comments

I was trying this for ages! Thank you so much! Works perfectly!
This is a robust solution, but beware that its not as efficient as the bitmap is copied to the memory stream then copied into the new bitmap's memory a second time. For hi-res images this could be a performance issue. The accepted answer addresses this.
MSDN says: "You must keep the stream open for the lifetime of the Bitmap." Workaround is clone bitmap to new and Dispose bitmap created from stream.
ConvertBitmap() leaks memory. See this answer for a similar alternative which does not.
as for 05/2019 this throws GDI+ error and is not correct
1

Is this what your looking for?

Bitmap bmp = System.Drawing.Image.FromHbitmap(pBits); 

1 Comment

I don't think this is right -- you're passing in a pointer to array of bytes where it instead expected a Win32 Bitmap Handle. -- Thanks for pointing out that this function exists though, that's neat.
1

Here a code to set transparent background to any bitmap resource within a Resource Dictionary (not Resources.resx often used in Windows.Forms age). I call this methode before InitializeComponent() - methode. The methodes 'ConvertBitmap(Bitmap source)' and BitmapFromSource(BitmapSource bitmapsource) are mentioned in post from melvas above.

private void SetBitmapResourcesTransparent() { Image img; BitmapSource bmpSource; System.Drawing.Bitmap bmp; foreach (ResourceDictionary resdict in Application.Current.Resources.MergedDictionaries) { foreach (DictionaryEntry dictEntry in resdict) { // search for bitmap resource if ((img = dictEntry.Value as Image) is Image && (bmpSource = img.Source as BitmapSource) is BitmapSource && (bmp = BitmapFromSource(bmpSource)) != null) { // make bitmap transparent and assign it back to ressource bmp.MakeTransparent(System.Drawing.Color.Magenta); bmpSource = ConvertBitmap(bmp); img.Source = bmpSource; } } } } 

Comments

1

This is neat and faster than light:

 return Imaging.CreateBitmapSourceFromHBitmap( bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions() ); 

Comments

0

You can share the pixeldata between both namespaces. You don't have to convert.

Use the SharedBitmapSource. https://stackoverflow.com/a/32841840/690656

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.