有没有一种很好的方法来转换BitmapSource和Bitmap?

Joh*_*esH 40 .net c# wpf bitmap bitmapsource

据我所知,从BitmapSource转换为Bitmap的唯一方法是通过不安全的代码...像这样(来自Lesters WPF博客):

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

做反过来:

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

框架中有更简单的方法吗?它不在那里的原因是什么(如果不是)?我认为它相当实用.

我需要它的原因是因为我使用AForge在WPF应用程序中执行某些图像操作.WPF希望显示BitmapSource/ImageSource,但AForge可以在Bitmaps上运行.

小智 63

通过使用Bitmap.LockBits并将像素从BitmapSource直线复制到,可以不使用不安全的代码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;
}
Run Code Online (Sandbox Code Playgroud)

  • 这只有在事先知道像素格式时才有效,它与我的方式非常相似,并且在像素格式之间进行映射的附加功能. (5认同)
  • 如果文件中同时引用了Windows.Media和System.Drawing.Imaging,则应将PixelFormat特别写为System.Drawing.Imaging.PixelFormat。与System.Drawing.Point相同。 (2认同)

mel*_*vas 31

您可以使用以下两种方法:

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;
}
Run Code Online (Sandbox Code Playgroud)

它对我来说很完美.

  • 这是一个强大的解决方案,但请注意,它不如位图复制到内存流那么高效,然后再次复制到新位图的内存中.对于高分辨率图像,这可能是性能问题.接受的答案解决了这个问题 (3认同)