Is there a good way to convert between BitmapSource and Bitmap?

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.


Solution 1:

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;
}

Solution 2:

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.

Solution 3:

Is this what your looking for?

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