将 BitmapImage 转换为 Bitmap,反之亦然

我在 C # 中有 BitmapImage,我需要对图像进行操作,例如灰度调整,在图像上添加文本等等。

我在 stackoverflow 中找到了一个用于灰度缩放的函数,它接受 Bitmap 并返回 Bitmap。

所以我需要转换位图图像位图,做操作和转换回来。

我怎么能这么做,这是最好的办法吗?

129074 次浏览

没有必要使用外国图书馆。

将位图图像转换为位图:

private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
{
// BitmapImage bitmapImage = new BitmapImage(new Uri("../Images/test.png", UriKind.Relative));


using(MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapImage));
enc.Save(outStream);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);


return new Bitmap(bitmap);
}
}

将位图转换回位图图片来源:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);


private BitmapImage Bitmap2BitmapImage(Bitmap bitmap)
{
IntPtr hBitmap = bitmap.GetHbitmap();
BitmapImage retval;


try
{
retval = (BitmapImage)Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
}
finally
{
DeleteObject(hBitmap);
}


return retval;
}

我一直在尝试在我的代码中使用上面的代码,我相信 Bitmap2BitmapImage 函数有一个问题(可能还有另一个问题)。

using (MemoryStream ms = new MemoryStream())

上面的行是否导致流被丢弃? 这意味着返回的 BitmapImage 丢失了它的内容。

作为一个 WPF 新手,我不确定这是否是正确的技术解释,但是代码在我的应用程序中不起作用,直到我删除了 using 指令。

使用 System.Windows.Interop; ...

 private BitmapImage Bitmap2BitmapImage(Bitmap bitmap)
{
BitmapSource i = Imaging.CreateBitmapSourceFromHBitmap(
bitmap.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
return (BitmapImage)i;
}

下面是一个将 Bitmap 转换为 BitmapImage 的扩展方法。

    public static BitmapImage ToBitmapImage(this Bitmap bitmap)
{
using (var memory = new MemoryStream())
{
bitmap.Save(memory, ImageFormat.Png);
memory.Position = 0;


var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
bitmapImage.Freeze();


return bitmapImage;
}
}

这可以从 System.Drawing.Bitmap 转换为 BitmapImage:

MemoryStream ms = new MemoryStream();
YOURBITMAP.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
BitmapImage image = new BitmapImage();
image.BeginInit();
ms.Seek(0, SeekOrigin.Begin);
image.StreamSource = ms;
image.EndInit();

如果你只需要从 BitmapImage 转换到 Bitmap,这很简单,

private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
{
return new Bitmap(bitmapImage.StreamSource);
}

这里是异步版本。

public static Task<BitmapSource> ToBitmapSourceAsync(this Bitmap bitmap)
{
return Task.Run(() =>
{
using (System.IO.MemoryStream memory = new System.IO.MemoryStream())
{
bitmap.Save(memory, ImageFormat.Png);
memory.Position = 0;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
bitmapImage.Freeze();
return bitmapImage as BitmapSource;
}
});


}

谢谢 Guillermo Hernandez 我创建了一个可以工作的代码变体。我在这段代码中添加了名称空间以供参考。

System.Reflection.Assembly theAsm = Assembly.LoadFrom("My.dll");
// Get a stream to the embedded resource
System.IO.Stream stream = theAsm.GetManifestResourceStream(@"picture.png");


// Here is the most important part:
System.Windows.Media.Imaging.BitmapImage bmi = new BitmapImage();
bmi.BeginInit();
bmi.StreamSource = stream;
bmi.EndInit();