[28-07-2020] Comparing screen capturing using GDI+ and OpenCV on Windows in C++


To follow up on my last two blogs ([25-07-2020] Capturing the screen on Windows in C++ using OpenCV & [26-07-2020] Capturing the screen on Windows in C++ using GDI+ ), we compare in this post both approaches. In order to compare both approaches, we examines their run-times and CPU usages.

*Keywords*: GDI+, OpenCV, Screen capture, Screenshots, Comparison

Benchmarking Code

To capture the run-times of each approach, we will need to add a Timer, that we will use to capture the start and end times of each approach. For this you can use whatever implementation you deem useful. I personally used the following snippet, which can be found here:

The Testing setup

Now let’s write the main testing code. We already have all the components ready in the last two posts, so all we need is combine the previous screen-shooting codes with the timer calls.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
int main()
{
    // initializations
    Timer tmr;
    int repetitions = 50;
    HWND hWnd = GetDesktopWindow();

    tmr.reset();
    double t = tmr.elapsed();

    // Initialize GDI+.
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    std::wcout << "Benchmarks for GDI+ variant of the screenshooter" << std::endl;
    std::wcout << "***********************************************************" << std::endl;
    // benchmarks for GDI+
    tmr.reset();
    for (int i = 0; i < repetitions; i++)
    {
        // capture and encode screenshot
        std::vector<BYTE> data;
        HBITMAP hBmp = GdiPlusScreenCapture(hWnd);
        saveToMemory(&hBmp, data, "png");
        data.clear();
    }
    GdiplusShutdown(gdiplusToken);
    t = tmr.elapsed();
    std::wcout << " | Number of Runs       [#] = " << repetitions << std::endl;
    std::wcout << " | Run duration         [s] = " << t << std::endl;
    std::wcout << " | Average Run duration [ms] = " << t / repetitions << std::endl;
    std::wcout << "***********************************************************" << std::endl;

    std::wcout << "Benchmarks for OpenCV variant of the screenshooter" << std::endl;
    std::wcout << "***********************************************************" << std::endl;
    // benchmarks for OpenCV
    tmr.reset();
    for (int i = 0; i < repetitions; i++)
    {
        // capture and encode screenshot
        std::vector<uchar> buf;
        Mat src = captureScreenMat(hWnd);
        cv::imencode(".png", src, buf);
        buf.clear();
        src.release();
    }
    t = tmr.elapsed();
    std::wcout << " | Number of Runs       [#] = " << repetitions << std::endl;
    std::wcout << " | Run duration         [s] = " << t << std::endl;
    std::wcout << " | Average Run duration [ms] = " << t / repetitions << std::endl;
    std::wcout << "***********************************************************" << std::endl;
    return 0;
}

Benchmarking results

The testing results confirms the previously mentioned intuition that screen shooting using GDI+ is faster than the OpenCV variant. However, upon examining the results in details, we realize that the right answer to the question of which library is better? is a complex one (as it is the case, almost always).

Benchmarks for GDI+ variant of the screenshooter
*********************************************************
| Number of Runs       [#]  = 50
| Run duration         [s]  = 7.3564
| Average Run duration [ms] = 0.147128
*********************************************************
Benchmarks for OpenCV variant of the screenshooter
*********************************************************
| Number of Runs       [#]  = 50
| Run duration         [s]  = 17.8956
| Average Run duration [ms] = 0.357913
*********************************************************

Edit

This post is still lacking and is subject to future edits that will include code improvements and better suited tests.

Conclusion

To summarize, in this post we compared the previously implemented screen-shooting methods using GDI+ and OpenCV. The test results confirmed the previous intuition about the GDI+ being faster as it uses the native Windows API. However, the OpenCV variant is still a decent option and sometimes even a better one because -unlike GDI+- it supports various operating systems other than Windows.