我在C#中有一个BitmapImage。我需要对图像进行操作,比如灰度化、在图像上添加文本等。
我在stackoverflow上找到了一个接受Bitmap并返回Bitmap的函数用于灰度化。
因此我需要将BitmapImage转换为Bitmap,进行操作,然后再转换回来。
我该如何做?这是最佳方法吗?
我在C#中有一个BitmapImage。我需要对图像进行操作,比如灰度化、在图像上添加文本等。
我在stackoverflow上找到了一个接受Bitmap并返回Bitmap的函数用于灰度化。
因此我需要将BitmapImage转换为Bitmap,进行操作,然后再转换回来。
我该如何做?这是最佳方法吗?
不需要使用外部库。
将 BitmapImage 转换为 Bitmap:
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);
}
}
将Bitmap转换回BitmapImage:将Bitmap转换回BitmapImage:
```[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;
}
BitmapImage2Bitmap
函数中,为什么最后一行要写成return new Bitmap(bitmap)
而不是简单地写成return bitmap
? - arnobpl这是一个将 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;
}
}
bitmapImage.EndInit();
之后,调用bitmapImage.Freeze()
可以避免在与GUI不同的线程上执行此操作时出现错误。 - Zachary Canann如果你只需要从BitmapImage转换为Bitmap,那么这很容易实现。
private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
{
return new Bitmap(bitmapImage.StreamSource);
}
使用System.Windows.Interop;
private BitmapImage Bitmap2BitmapImage(Bitmap bitmap)
{
BitmapSource i = Imaging.CreateBitmapSourceFromHBitmap(
bitmap.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
return (BitmapImage)i;
}
我刚刚尝试在我的代码中使用上述功能,我认为Bitmap2BitmapImage函数存在问题(可能还有其他函数)。
using (MemoryStream ms = new MemoryStream())
上述代码会导致流被处理掉,这意味着返回的BitmapImage将失去其内容。
由于我是WPF新手,不确定这是否是正确的技术解释,但在我的应用程序中,直到我删除了using指令,代码才能正常工作。
这里是异步版本。
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;
}
});
}
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();
这将 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();