将System.Windows.Media.ImageSource转换为System.Drawing.Bitmap

13

如何在C#中将System.Windows.Media.ImageSource转换为System.Drawing.Bitmap?

2个回答

15

虽然这是一个旧的问题,但它仍然对其他人有用,因为花费了一些时间才能找到没有dll交互或剪贴板黑客的更干净的解决方案。

对我来说,这个方法有效,你可以使用png编码器在保存到文件或rtf流之前缩小图像尺寸。

private System.Drawing.Image ImageWpfToGDI(System.Windows.Media.ImageSource image) {
  MemoryStream ms = new MemoryStream();
  var encoder = new System.Windows.Media.Imaging.BmpBitmapEncoder();
  encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(image as System.Windows.Media.Imaging.BitmapSource));
  encoder.Save(ms);
  ms.Flush();      
  return System.Drawing.Image.FromStream(ms);
}

如果您需要转换带有 alpha 通道(透明部分)的图像,请使用 System.Windows.Media.Imaging.PngBitmapEncoder() 而不是 System.Windows.Media.Imaging.BmpBitmapEncoder()。 - Dariusz Wasacz
@DariuszWasacz 我无法让这个答案工作。它抱怨 image.Source 不起作用:**'System.Drawing.Image' 不包含 'Source' 的定义,也没有接受类型为 'System.Drawing.Image' 的第一个参数的扩展方法 'Source' 可以找到。**我查看了 MSDN,发现 Image 没有 Source 属性。你有什么想法需要修复吗? - kayleeFrye_onDeck
1
@kayleeFrye_onDeck:请注意,System.Drawing和System.Windows.Media命名空间都包含名为“Image”的类。看起来您在参数“System.Windows.Media.Image image”中省略了命名空间,并且使用语句中采用了“System.Drawing.Image”。请检查您的代码是否与上面完全相同。 - Dariusz Wasacz
我感觉我在这里遗漏了一些东西,@DariuszWasacz。 你是对的,它使用System.Drawing.Image,所以谢谢你,但我找不到System.Windows.Media中名为“Image”的成员。 我能找到的最接近的是System.Windows.Media.ImageSource。 因为你上面的代码使用了Image的.Source属性,所以这似乎是合乎逻辑的跳跃。 - kayleeFrye_onDeck
1
@kayleeFrye_onDeck:上面的代码原本不是我的 :-)。 我的代码是这样的: public static System.Drawing.Image ImageWpfToGdi2(this ImageSource image) { var ms = new MemoryStream(); var encoder = new System.Windows.Media.Imaging.PngBitmapEncoder(); encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create((System.Windows.Media.Imaging.BitmapSource)image)); encoder.Save(ms); ms.Flush(); var btm = (System.Drawing.Bitmap)System.Drawing.Image.FromStream(ms); return btm; } - Dariusz Wasacz

0
请查看如何在WinForms中使用ImageSource(无处理程序)作为System.Drawing.Bitmap(HBITMAP)

从本文中学习了如何轻松将WinForms System.Drawing.Bitmap转换为WPF ImageSource。今天,我将解释如何相反地做到这一点。实际上,我们所要做的就是从BitmapSource中提取处理程序,但是这种方法不受支持,因此我们唯一能做的就是将BitmapSource(或BitmapFrame)的像素复制到字节数组中,然后将它们复制到HBitmap的指针中。


这篇文章和之前的文章都是相同的方法:将位图扫描行复制到一个字节数组中,然后从内存块创建位图。位图假定内存块在位图生命周期内包含扫描行。然而,在离开 fixed(byte* pB = bits) 代码后,内存可以被 .net 内存管理器覆盖,导致位图损坏。解决方案是使用 Marshal.AllocHGlobal,但在这种情况下,内存块必须由用户代码维护(也就是说,在使用后必须通过 Marshal.FreeHGlobal 进行释放)。 - Dariusz Wasacz
链接已失效,这就是为什么我们要求人们发布答案而不是链接的原因。 - Dour High Arch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接