Fastest Screen Capture using C# – VISTA vs WIN7

Update: I recently installed Windows Version 7 RC and perceived a performance increase (more frames per second) in the Remote Desktop Viewer. I thought I would recapture the performance numbers and compare Vista to Win 7 (both Ultimate versions).

To ensure the Remote Desktop Viewer that I am building has the best performance, I thought that I would gather some timing data for two different ways of collecting screenshots.

Method 1: Drop down to the WIN32 API to capture the screenshot. Again, I am using the code written by Rashid Mahmood which you can find here along with additional details.

public long Method1(int numAttempts)
{
    Stopwatch stopWatch = new Stopwatch()
    stopWatch.Start();
    for (int i = 0; i < numAttempts; i++)
    {
        SIZE size;
        IntPtr hBitmap;
        IntPtr hDC = Win32Stuff.GetDC(Win32Stuff.GetDesktopWindow());
        IntPtr hMemDC = GDIStuff.CreateCompatibleDC(hDC);

        size.cx = Win32Stuff.GetSystemMetrics
                  (Win32Stuff.SM_CXSCREEN);

        size.cy = Win32Stuff.GetSystemMetrics
                  (Win32Stuff.SM_CYSCREEN);

        hBitmap = GDIStuff.CreateCompatibleBitmap(hDC, size.cx / 2, size.cy);

        if (hBitmap != IntPtr.Zero)
        {
            IntPtr hOld = (IntPtr)GDIStuff.SelectObject
                                   (hMemDC, hBitmap);

            GDIStuff.BitBlt(hMemDC, 0, 0, size.cx / 2, size.cy, hDC,
                                           0, 0, GDIStuff.SRCCOPY);

            GDIStuff.SelectObject(hMemDC, hOld);
            GDIStuff.DeleteDC(hMemDC);
            Win32Stuff.ReleaseDC(Win32Stuff.GetDesktopWindow(), hDC);
            Bitmap bmp = System.Drawing.Image.FromHbitmap(hBitmap);
            GDIStuff.DeleteObject(hBitmap);
            GC.Collect();
            return bmp;
        }
        return null;
    }
    stopWatch.Stop();
    return stopWatch.ElapsedMilliseconds;
}

Method 2: Utilize the convenient wrappers that .NET provides.

public long Method2(int numAttempts)
{
    Stopwatch stopWatch = new Stopwatch()
    stopWatch.Start();
    for (int i = 0; i < numAttempts; i++)
    {
        Bitmap desktopBMP = new Bitmap(
            System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
            System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height);

        Graphics g = Graphics.FromImage(desktopBMP);

        g.CopyFromScreen(0, 0, 0, 0,
           new Size(
           System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
           System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height));
        g.Dispose();
    }
    stopWatch.Stop();
    return stopWatch.ElapsedMilliseconds;
}

I utilized the Stopwatch class that can be found in the System.Diagnostics namespace for the timer. I ran each method 100 times. The results are:

  • Method 1 – 100 attempts = 5366 milliseconds.
  • Method 2 – 100 attempts = 11210 milliseconds.
Method VISTA (milliseconds) WIN7 (milliseconds)
1 5366 6350
2 11210 6565

Dropping down to closer to the Operating System results in a screen capture that is more than twice as fast. (Update: The Win7 team has done a bang up job making the .NET version of the screen capture much faster…almost twice as fast. So if you were only deploying to Win7 machines, the difference may not matter.) The code is a bit more complex. Applications that require high capture rates will benefit from the added complexity.

53.66 milliseconds per capture = 18.6 frames per second

Not movie quality, but decent enough for many purposes.

Tags:, , ,
Comments
  1. Alexander
  2. Batman
  3. Batman
  4. Lennart Denninger
  5. absk

Leave a Reply to Lennart Denninger Cancel reply

Your email address will not be published. Required fields are marked *

*