26 #include <opencv2/imgcodecs.hpp>
27 #include <opencv2/imgproc.hpp>
41 int main(
int argc,
char *argv[]) {
45 return argc == 1 ? EXIT_SUCCESS : EXIT_FAILURE;
47 std::string bg_fname = argv[1];
48 std::string fg_fname = argv[2];
49 int x = argc > 3 ? std::stoi(argv[3]) : 0;
50 int y = argc > 4 ? std::stoi(argv[4]) : 0;
51 int repeat = argc > 5 ? std::stoi(argv[5]) : 1;
54 cv::Mat
bg_img = imread(bg_fname, cv::IMREAD_UNCHANGED);
55 cv::Mat
fg_img = imread(fg_fname, cv::IMREAD_UNCHANGED);
57 throw std::runtime_error(
"unable to load " + bg_fname);
59 throw std::runtime_error(
"unable to load " + fg_fname);
62 if (
bg_img.channels() == 3)
64 if (
bg_img.channels() != 4)
65 throw std::runtime_error(
"incorrect background image color format");
66 if (
fg_img.channels() != 4)
67 throw std::runtime_error(
"foreground image without alpha channel");
71 throw std::runtime_error(
"x coordinate out of bounds");
73 throw std::runtime_error(
"y coordinate out of bounds");
76 int fg_x = std::max(0, -x);
77 int fg_y = std::max(0, -y);
78 int bg_x = std::max(0, x);
79 int bg_y = std::max(0, y);
80 int fg_width = std::min(
fg_img.cols - fg_x,
bg_img.cols - x);
81 int fg_height = std::min(
fg_img.rows - fg_y,
bg_img.rows - y);
84 auto start = std::chrono::high_resolution_clock::now();
85 for (
int r = 0; r < repeat; ++r) {
87 fg_img.at<uint8_t[4]>(fg_y, fg_x),
88 bg_img.at<uint8_t[4]>(bg_y, bg_x),
93 auto finish = std::chrono::high_resolution_clock::now();
96 long fg_pixels = 1L * fg_width * fg_height;
100 cv::imwrite(
"output.png",
bg_img);
104 cout <<
"Usage: " << cmd <<
" <background> <overlay> <x> <y>" << endl;
109 using namespace std::chrono_literals;
110 std::cout << std::fixed << std::setprecision(3);
111 if (duration < 1000ns) {
112 return std::cout << duration.count() * 1e9 <<
" ns";
113 }
else if (duration < 1000us) {
114 return std::cout << duration.count() * 1e6 <<
" µs";
115 }
else if (duration < 1000ms) {
116 return std::cout << duration.count() * 1e3 <<
" ms";
118 return std::cout << duration.count() * 1e0 <<
" s";
124 auto duration_s = std::chrono::duration_cast<float_seconds>(duration);
126 cout << duration_s <<
" = " << duration_s / double(repeat)
127 <<
"/it = " << duration_s / double(num_pixels * repeat) <<
"/px"