Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <chrono>
- #include <functional>
- #include <iostream>
- #include <string>
- #include <tuple>
- #include <vector>
- constexpr double one_third = 1.0 / 3.0;
- constexpr double two_third = 2.0 / 3.0;
- using std::tuple;
- using std::vector;
- struct image {
- using data_type = double;
- image(size_t rows, size_t cols)
- : rows(rows)
- , cols(cols)
- {
- buffer.resize(rows * cols * channels);
- }
- data_type* at(size_t row, size_t col)
- {
- return &buffer[row * cols * channels + col * channels];
- }
- data_type const* at(size_t row, size_t col) const
- {
- return &buffer[row * cols * channels + col * channels];
- }
- std::vector<data_type> buffer;
- size_t rows;
- size_t cols;
- size_t channels{ 3 };
- };
- using std::chrono::steady_clock;
- using std::chrono::duration;
- using std::chrono::microseconds;
- double wrap(double d)
- {
- d = fmod(d, 1.0);
- return d < 0 ? d + 1.0 : d;
- }
- void fill(image& img, size_t row, size_t col)
- {
- auto* p = img.at(row, col);
- p[0] = double(rand()) / RAND_MAX;
- p[1] = double(rand()) / RAND_MAX;
- p[2] = double(rand()) / RAND_MAX;
- }
- image random_image(size_t height, size_t width) {
- image image(height, width);
- for (size_t y = 0; y < height; y++) {
- for (size_t x = 0; x < width; x++) {
- fill(image, y, x);
- }
- }
- return image;
- }
- tuple<int, double, double> extrema(double a, double b, double c) {
- int i = 2;
- if (b > c) {
- std::swap(b, c);
- i = 1;
- }
- if (a > b) {
- std::swap(a, b);
- }
- if (b > c) {
- std::swap(b, c);
- i = 0;
- }
- return { i, a, c };
- }
- double hue(double b, double g, double r, double d, double i)
- {
- if (i == 2) {
- return wrap((g - b) / (6 * d));
- }
- if (i == 1) {
- return wrap(one_third + (b - r) / (6 * d));
- }
- return wrap(two_third + (r - g) / (6 * d));
- }
- void set_HSL_pixel(double* p, double b, double g, double r)
- {
- auto const [i, x, z] = extrema(b, g, r);
- double const s = x + z;
- double const d = z - x;
- double const avg = s / 2;
- if (d != 0.0) {
- p[0] = hue(b, g, r, d, i);
- p[1] = d / (1 - abs(s - 1));
- p[2] = avg;
- } else {
- p[0] = 0.0;
- p[1] = 0.0;
- p[2] = avg;
- }
- }
- image BGR_to_HSL(image const& img)
- {
- image out(img.rows, img.cols);
- for (size_t y = 0; y < img.rows; ++y) {
- for (size_t x = 0; x < img.cols; ++x) {
- double const* px = img.at(y, x);
- set_HSL_pixel(out.at(y, x), px[0], px[1], px[2]);
- }
- }
- return out;
- }
- double timeit(std::function<image(image const&)> func
- , image img
- , int runs = 256)
- {
- auto const start = steady_clock::now();
- for (int64_t i = 0; i < runs; i++) {
- func(img);
- }
- auto const end = steady_clock::now();
- duration<double, std::nano> time = end - start;
- return time.count() / runs / 1000.0;
- }
- int main()
- {
- image img = random_image(1080, 1920);
- double once = timeit(BGR_to_HSL, img, 16);
- std::cout << "converting 1920x1080 BGR image to HSL vector: " + std::to_string(once) + " microseconds\n";
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement