Search code examples
c#.netwpfbitmapbitmapsource

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

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