views:

62

answers:

1

I'm building an application that captures video frames from a camera (30fps @ 640x480), processes them, and then displays them on a Windows Form. I was initially using DrawImage (see code below) but the performance was terrible. Even with the processing step disabled the best I can get is 20fps on a 2.8GHz Core 2 Duo machine. Double buffering is enabled on the Windows form otherwise I get tearing.

Note: The image used is a Bitmap of format Format24bppRgb. I know that DrawImage is supposed to be faster with a Format32bppArgb formatted image but I am restricted by the format that comes out of the frame grabber.

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);
}

I tried using Managed DirectX 9 with Textures and Spites (see below) but the performance was even worse. I'm very new to DirectX programming so this may not be the best DirectX code.

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();
}

I need this to work on XP, Vista and Windows 7. I don't know if it's worth trying XNA or OpenGL. This seems like it should be a very simple thing to accomplish.

A: 

Is CameraViewForm your entire viewer window? If so, then on Paint, the entire window is redrawn, including all buttons, progress bars, etc. This will be more or less expensive depending on the number of controls on your form, and the visual doo-dads you have enabled for desktop elements in various OSes (e.g. window bar transparency).

Try single-buffering the entire form, but giving the Panel (from which I assume you get displayRectangle) its own BufferedGraphicsContext, by declaring a new one when you call GreateGraphics() or before calling Invalidate() on the Panel. This allows the Panel to be double-buffered separately from the Form.

KeithS