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.
Good article, but I don’t understand one moment
why do you copy only a half of screen in method1? (size.cx / 2) Isn’t it a keypoint to a better performance?
Dual monitors is why. The .NET version specifies “PrimaryScreen”. While the API version does not. My guess is he has dual monitors set to the same resolution on both. This would not work on mine as I have two different type of monitors working on different resolutions.
Now to the OP. What in the hell is Win32Stuff and GDIStuff? How did you make those objects?
Dual monitors is why. The .NET version specifies “PrimaryScreen”. While the Win32 API version does not. My guess is he has dual monitors set to the same resolution on both. This would not work on mine as I have two different type of monitors working on different resolutions.
Now to the OP. What in the hell is Win32Stuff and GDIStuff? How did you make those objects?
Taking into account that method 1 actually returns after the 1st screenshot is made while method 2 actually takes screenshots I’m not surprised that method 1 is faster 😉
Senin Ben tipini sikim