C# 使用C绘制一系列位图的最快方法#
我正在构建一个应用程序,它可以从摄像头(640x480,每秒30帧)捕获视频帧,对其进行处理,然后将其显示在Windows窗体上。我最初使用的是DrawImage(见下面的代码),但性能很差。即使在禁用处理步骤的情况下,在2.8GHz Core 2 Duo机器上,我能获得的最佳速度也是20fps。在Windows窗体上启用了双缓冲,否则我会崩溃 注意:使用的图像是格式为24bpprgb的位图。我知道使用格式化32bppargb格式的图像,DrawImage应该会更快,但我受到来自帧捕获器的格式的限制C# 使用C绘制一系列位图的最快方法#,c#,.net,video,directx,drawimage,C#,.net,Video,Directx,Drawimage,我正在构建一个应用程序,它可以从摄像头(640x480,每秒30帧)捕获视频帧,对其进行处理,然后将其显示在Windows窗体上。我最初使用的是DrawImage(见下面的代码),但性能很差。即使在禁用处理步骤的情况下,在2.8GHz Core 2 Duo机器上,我能获得的最佳速度也是20fps。在Windows窗体上启用了双缓冲,否则我会崩溃 注意:使用的图像是格式为24bpprgb的位图。我知道使用格式化32bppargb格式的图像,DrawImage应该会更快,但我受到来自帧捕获器的格式的
private void CameraViewForm_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
// Maximize performance
g.CompositingMode = CompositingMode.SourceOver;
g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
g.CompositingQuality = CompositingQuality.HighSpeed;
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.SmoothingMode = SmoothingMode.None;
g.DrawImage(currentFrame, displayRectangle);
}
我尝试将托管DirectX 9与纹理和Spit一起使用(见下文),但性能更差。我对DirectX编程非常陌生,所以这可能不是最好的DirectX代码
private void CameraViewForm_Paint(object sender, PaintEventArgs e)
{
device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
device.BeginScene();
Texture texture = new Texture(device, currentFrame, Usage.None, Pool.Managed);
Rectangle textureSize;
using (Surface surface = texture.GetSurfaceLevel(0))
{
SurfaceDescription surfaceDescription = surface.Description;
textureSize = new Rectangle(0, 0, surfaceDescription.Width, surfaceDescription.Height);
}
Sprite sprite = new Sprite(device);
sprite.Begin(SpriteFlags.None);
sprite.Draw(texture, textureSize, new Vector3(0, 0, 0), new Vector3(0, 0, 0), Color.White);
sprite.End();
device.EndScene();
device.Present();
sprite.Dispose();
texture.Dispose();
}
我需要这个在XP、Vista和Windows7上工作。我不知道是否值得尝试XNA或OpenGL。这似乎应该是一件非常简单的事情。摄影机是否构成了整个查看器窗口?如果是这样,则在绘制时,将重新绘制整个窗口,包括所有按钮、进度条等。这将根据窗体上控件的数量以及在各种操作系统中为桌面元素启用的可视doo DAD(例如,窗口条透明度)的不同而不同
尝试对整个表单进行单缓冲,但在调用GreateGraphics()或在面板上调用Invalidate()之前,通过声明一个新的缓冲区,为面板(我假设您从中获得displayRectangle)提供自己的BufferedGraphicsContext。这允许面板与窗体分开进行双缓冲。答案就在您面前。这是一个老问题的迟来答案,但可能有人需要答案,所以 与其在绘制循环中声明新的纹理和矩形(这在资源中非常重要),为什么不在范围之外创建纹理呢?例如,请尝试以下方法,而不是您的方法:
Texture texture;
Rectangle textureSize;
private void InitiateTexture()
{
texture = new Texture(device, new Bitmap("CAR.jpg"), Usage.None, Pool.Managed);
using (Surface surface = texture.GetSurfaceLevel(0))
{
SurfaceDescription surfaceDescription = surface.Description;
textureSize = new Rectangle(0, 0,
surfaceDescription.Width,
surfaceDescription.Height);
}
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
device.Clear(ClearFlags.Target, Color.DarkSlateBlue, 1.0f, 0);
device.BeginScene();
Sprite sprite = new Sprite(device);
sprite.Begin(SpriteFlags.None);
sprite.Draw(texture, textureSize,
new Vector3(0, 0, 0),
new Vector3(0, 0, 0), Color.White);
sprite.End();
device.EndScene();
device.Present();
}
然后,如果需要启动多个纹理,请将其放入列表中,然后从该列表中绘制。它省去了使用资源然后释放资源的麻烦。大多数捕获界面都具有“预览”功能,可直接连接到窗口句柄,然后轻松绘制。如果你没有这个选择,你能进入DirectShow吗?如果可以,我可能会给你一个答案。