我想在BitmapSource上绘图。
“我的相框”来源来自位图类型的网络摄像头。我将其转换为BitmapSource,绘制一个rect并设置为具有数据绑定的Image控制源。
//convert Bitmap to BitmapSource:
//WinForms -> WPF
public BitmapSource BitmapToBitmapSource(System.Drawing.Bitmap bitmap)
{
var bitmapData = bitmap.LockBits(
new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);
var bitmapSource = BitmapSource.Create(
bitmapData.Width, bitmapData.Height,
bitmap.HorizontalResolution, bitmap.VerticalResolution,
PixelFormats.Bgr24, null,
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
bitmap.UnlockBits(bitmapData);
return bitmapSource;
}
//Drawing code:
public static BitmapSource DrawRect(BitmapSource frame)
{
RenderTargetBitmap rtb = new RenderTargetBitmap(frame.PixelWidth, frame.PixelHeight, frame.DpiX, frame.DpiY, PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
dc.DrawImage(frame, new Rect(0, 0, frame.Width, frame.Height));
//dc.DrawLine(new Pen(Brushes.White, 1), new Point(0, 0), new Point(frame.Width, frame.Height));
dc.DrawRectangle(null, new Pen(Brushes.Red, 1), new Rect(50, 50, 100, 100));
}
rtb.Render(dv);
rtb.Freeze();
return rtb;
}
我的硬件使用结果:
CPU:24% GPU:5.4%
在Intel Core i7-4900MQ @ 2.8Ghz上; 4核; 8线程 / NVIDIA Quadro K2100M
结果视频不流畅,有点慢。
有人知道我该如何最快吗?
答案 0 :(得分:1)
将System.Drawing.Bitmap转换为System.Windows.Media.Imaging.BitmapSource或System.Windows.Media.ImageSource(基类) 很简单,但是您要小心。
首先,每当您使用完System.Drawing.Bitmap时就需要处理它。这样,您就可以在内存中腾出可用空间
可以通过两种方式完成转换。使用GDI或内存流。 我个人更喜欢GDI方式。此外,GDI还允许您使用GPU而不是CPU。如果要渲染视觉效果,那是想要的。
记忆流向
public static System.Windows.Media.ImageSource ToImageSource2(this Bitmap bitmap)
{
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Bmp);
stream.Position = 0;
System.Windows.Media.Imaging.BitmapImage result = new System.Windows.Media.Imaging.BitmapImage();
result.BeginInit();
result.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
result.StreamSource = stream;
result.EndInit();
result.Freeze();
return result;
}
}
GDI方式
[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteObject([In] IntPtr hObject);
public static System.Windows.Media.ImageSource ToImageSource(this Bitmap bitmap)
{
System.Windows.Media.ImageSource image;
IntPtr handle = bitmap.GetHbitmap();
try
{
image = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, System.Windows.Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
image.Freeze();
}
finally
{
DeleteObject(handle);
}
return image;
}
测试样本
public static void Test()
{
System.Windows.Media.ImageSource img;
System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(@"filepath");
//From GDI
img = bmp.ToImageSource();
//From MemoryStream
img = bmp.ToImageSource2();
//Dispose from memory
bmp.Dispose();
}
答案 1 :(得分:0)
如果您只需要在图像周围绘制边框,则可以对BitmapSource
不做任何事情,然后在您的UI中,用适当的Image
包装Border
:< / p>
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Border BorderBrush="Red" BorderThickness="1">
<Image x:Name="Image1" />
</Border>
</Grid>
</Window>
然后查看它是否以某种方式有所改进,否则您将需要检查调用方法的方式和频率。