Comparing screen capturing using GDI+ and OpenCV on Windows in C++#


To follow up on my last two blogs (Capturing the screen on Windows in C++ using OpenCV & 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.

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 :

 1#include <chrono>
 2#include <iostream>
 3
 4/*
 5 * Timer class to measure the run-times in seconds of code snippets.
 6 */
 7class Timer
 8{
 9public:
10    Timer() : beg_(clock_::now()) {}
11    void reset() { beg_ = clock_::now(); }
12    double elapsed() const { return std::chrono::duration_cast<second_> (clock_::now() - beg_).count();}
13
14private:
15    typedef std::chrono::high_resolution_clock clock_;
16    typedef std::chrono::duration<double, std::ratio<1> > second_;
17    std::chrono::time_point<clock_> beg_;
18};

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.

 1int main()
 2{
 3    // initializations
 4    Timer tmr;
 5    int repetitions = 50;
 6    HWND hWnd = GetDesktopWindow();
 7
 8    tmr.reset();
 9    double t = tmr.elapsed();
10
11    // Initialize GDI+.
12    GdiplusStartupInput gdiplusStartupInput;
13    ULONG_PTR gdiplusToken;
14    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
15
16    std::wcout << "Benchmarks for GDI+ variant of the screenshooter" << std::endl;
17    std::wcout << "***********************************************************" << std::endl;
18    // benchmarks for GDI+
19    tmr.reset();
20    for (int i = 0; i < repetitions; i++)
21    {
22        // capture and encode screenshot
23        std::vector<BYTE> data;
24        HBITMAP hBmp = GdiPlusScreenCapture(hWnd);
25        saveToMemory(&hBmp, data, "png");
26        data.clear();
27    }
28    GdiplusShutdown(gdiplusToken);
29    t = tmr.elapsed();
30    std::wcout << " | Number of Runs       [#] = " << repetitions << std::endl;
31    std::wcout << " | Run duration         [s] = " << t << std::endl;
32    std::wcout << " | Average Run duration [ms] = " << t / repetitions << std::endl;
33    std::wcout << "***********************************************************" << std::endl;
34
35    std::wcout << "Benchmarks for OpenCV variant of the screenshooter" << std::endl;
36    std::wcout << "***********************************************************" << std::endl;
37    // benchmarks for OpenCV
38    tmr.reset();
39    for (int i = 0; i < repetitions; i++)
40    {
41        // capture and encode screenshot
42        std::vector<uchar> buf;
43        Mat src = captureScreenMat(hWnd);
44        cv::imencode(".png", src, buf);
45        buf.clear();
46        src.release();
47    }
48    t = tmr.elapsed();
49    std::wcout << " | Number of Runs       [#] = " << repetitions << std::endl;
50    std::wcout << " | Run duration         [s] = " << t << std::endl;
51    std::wcout << " | Average Run duration [ms] = " << t / repetitions << std::endl;
52    std::wcout << "***********************************************************" << std::endl;
53    return 0;
54}

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
*********************************************************

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.

Share this blog#

Updated on 08 April 2022

👨‍💻 edited and review were on 08.04.2022

References and Further readings#