]> git.seodisparate.com - blue_noise_generation/commitdiff
Some refactoring
authorStephen Seo <seo.disparate@gmail.com>
Fri, 22 Jan 2021 13:53:31 +0000 (22:53 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Fri, 22 Jan 2021 13:53:31 +0000 (22:53 +0900)
src/blue_noise.cpp
src/blue_noise.hpp

index 8c8dbcb58e030ecbcb51cd569fad529e9584eef8..4fe6056f0a3bae695f85fd4660d4c4df27ff9d63 100644 (file)
@@ -3,10 +3,6 @@
 #include <random>
 #include <cassert>
 #include <iostream>
-#include <condition_variable>
-#include <mutex>
-#include <thread>
-#include <chrono>
 
 #ifndef NDEBUG
 # include <cstdio>
@@ -169,6 +165,8 @@ std::vector<bool> dither::blue_noise(std::size_t width, std::size_t height, std:
     std::size_t iterations = 0;
 //#endif
 
+    std::size_t filter_size = (width + height) / 2;
+
     while(true) {
 //#ifndef NDEBUG
 //        if(++iterations % 10 == 0) {
@@ -176,57 +174,8 @@ std::vector<bool> dither::blue_noise(std::size_t width, std::size_t height, std:
 //        }
 //#endif
         // get filter values
-        if(threads == 1) {
-            for(std::size_t y = 0; y < height; ++y) {
-                for(std::size_t x = 0; x < width; ++x) {
-                    filter_out[internal::twoToOne(x, y, width)] =
-                        internal::filter(pbp, x, y, width, height);
-                }
-            }
-        } else {
-            if(threads == 0) {
-                threads = 10;
-            }
-            std::size_t active_count = 0;
-            std::mutex cv_mutex;
-            std::condition_variable cv;
-            for(std::size_t i = 0; i < count; ++i) {
-                {
-                    std::unique_lock lock(cv_mutex);
-                    active_count += 1;
-                }
-                std::thread t([] (std::size_t *ac, std::mutex *cvm,
-                            std::condition_variable *cv, std::size_t i,
-                            const std::vector<bool> *pbp, std::size_t width,
-                            std::size_t height, std::vector<double> *fout) {
-                        std::size_t x, y;
-                        std::tie(x, y) = internal::oneToTwo(i, width);
-                        (*fout)[i] = internal::filter(*pbp, x, y, width, height);
-                        std::unique_lock lock(*cvm);
-                        *ac -= 1;
-                        cv->notify_all();
-                    },
-                    &active_count, &cv_mutex, &cv, i, &pbp, width, height, &filter_out);
-                t.detach();
-
-                std::unique_lock lock(cv_mutex);
-                while(active_count >= threads) {
-#ifndef NDEBUG
-//                    std::cout << "0, active_count = " << active_count
-//                        << ", pre wait_for" << std::endl;
-#endif
-                    cv.wait_for(lock, std::chrono::seconds(1));
-#ifndef NDEBUG
-//                    std::cout << "0, active_count = " << active_count
-//                        << ", post wait_for" << std::endl;
-#endif
-                }
-            }
-            std::unique_lock lock(cv_mutex);
-            while(active_count > 0) {
-                cv.wait_for(lock, std::chrono::seconds(1));
-            }
-        }
+        internal::compute_filter(pbp, width, height, count, filter_size,
+                filter_out, threads);
 
 #ifndef NDEBUG
 //        for(std::size_t i = 0; i < count; ++i) {
@@ -268,54 +217,8 @@ std::vector<bool> dither::blue_noise(std::size_t width, std::size_t height, std:
         pbp[max_one] = false;
 
         // get filter values again
-        if(threads == 1) {
-            for(std::size_t y = 0; y < height; ++y) {
-                for(std::size_t x = 0; x < width; ++x) {
-                    filter_out[internal::twoToOne(x, y, width)] =
-                        internal::filter(pbp, x, y, width, height);
-                }
-            }
-        } else {
-            std::size_t active_count = 0;
-            std::mutex cv_mutex;
-            std::condition_variable cv;
-            for(std::size_t i = 0; i < count; ++i) {
-                {
-                    std::unique_lock lock(cv_mutex);
-                    active_count += 1;
-                }
-                std::thread t([] (std::size_t *ac, std::mutex *cvm,
-                            std::condition_variable *cv, std::size_t i,
-                            const std::vector<bool> *pbp, std::size_t width,
-                            std::size_t height, std::vector<double> *fout) {
-                        std::size_t x, y;
-                        std::tie(x, y) = internal::oneToTwo(i, width);
-                        (*fout)[i] = internal::filter(*pbp, x, y, width, height);
-                        std::unique_lock lock(*cvm);
-                        *ac -= 1;
-                        cv->notify_all();
-                    },
-                    &active_count, &cv_mutex, &cv, i, &pbp, width, height, &filter_out);
-                t.detach();
-
-                std::unique_lock lock(cv_mutex);
-                while(active_count >= threads) {
-#ifndef NDEBUG
-//                    std::cout << "1, active_count = " << active_count
-//                        << ", pre wait_for" << std::endl;
-#endif
-                    cv.wait_for(lock, std::chrono::seconds(1));
-#ifndef NDEBUG
-//                    std::cout << "1, active_count = " << active_count
-//                        << ", post wait_for" << std::endl;
-#endif
-                }
-            }
-            std::unique_lock lock(cv_mutex);
-            while(active_count > 0) {
-                cv.wait_for(lock, std::chrono::seconds(1));
-            }
-        }
+        internal::compute_filter(pbp, width, height, count, filter_size,
+                filter_out, threads);
 
         // get second buffer's min
         std::size_t second_min;
index acaba0bba80b1bd5a2d632c24f05195467298f8a..dadacf37a68a358dc4cbbb9e471abf6775248b3b 100644 (file)
@@ -6,6 +6,10 @@
 #include <cmath>
 #include <functional>
 #include <unordered_set>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+#include <chrono>
 
 namespace dither {
 
@@ -29,17 +33,17 @@ namespace internal {
     inline double filter(
             const std::vector<bool>& pbp,
             std::size_t x, std::size_t y,
-            std::size_t width, std::size_t height) {
+            std::size_t width, std::size_t height, std::size_t filter_size) {
         double sum = 0.0;
 
         // Should be range -M/2 to M/2, but size_t cannot be negative, so range
         // is 0 to M.
         // p' = (M + x - (p - M/2)) % M = (3M/2 + x - p) % M
         // q' = (N + y - (q - M/2)) % N = (N + M/2 + y - q) % N
-        for(std::size_t q = 0; q < width; ++q) {
-            std::size_t q_prime = (height + width / 2 + y - q) % height;
-            for(std::size_t p = 0; p < width; ++p) {
-                std::size_t p_prime = (3 * width / 2 + x - p) % width;
+        for(std::size_t q = 0; q < filter_size; ++q) {
+            std::size_t q_prime = (height + filter_size / 2 + y - q) % height;
+            for(std::size_t p = 0; p < filter_size; ++p) {
+                std::size_t p_prime = (width + filter_size / 2 + x - p) % width;
                 bool pbp_value = pbp[twoToOne(p_prime, q_prime, width)];
                 if(pbp_value) {
                     sum += gaussian((double)p - width/2.0, (double)q - width/2.0);
@@ -50,13 +54,74 @@ namespace internal {
         return sum;
     }
 
+    inline void compute_filter(
+            const std::vector<bool> &pbp, std::size_t width, std::size_t height,
+            std::size_t count, std::size_t filter_size, std::vector<double> &filter_out,
+            std::size_t threads = 1) {
+        if(threads == 1) {
+            for(std::size_t y = 0; y < height; ++y) {
+                for(std::size_t x = 0; x < width; ++x) {
+                    filter_out[internal::twoToOne(x, y, width)] =
+                        internal::filter(pbp, x, y, width, height, filter_size);
+                }
+            }
+        } else {
+            if(threads == 0) {
+                threads = 10;
+            }
+            std::size_t active_count = 0;
+            std::mutex cv_mutex;
+            std::condition_variable cv;
+            for(std::size_t i = 0; i < count; ++i) {
+                {
+                    std::unique_lock lock(cv_mutex);
+                    active_count += 1;
+                }
+                std::thread t([] (std::size_t *ac, std::mutex *cvm,
+                            std::condition_variable *cv, std::size_t i,
+                            const std::vector<bool> *pbp, std::size_t width,
+                            std::size_t height, std::size_t filter_size,
+                            std::vector<double> *fout) {
+                        std::size_t x, y;
+                        std::tie(x, y) = internal::oneToTwo(i, width);
+                        (*fout)[i] = internal::filter(
+                            *pbp, x, y, width, height, filter_size);
+                        std::unique_lock lock(*cvm);
+                        *ac -= 1;
+                        cv->notify_all();
+                    },
+                    &active_count, &cv_mutex, &cv, i, &pbp, width, height,
+                    filter_size, &filter_out);
+                t.detach();
+
+                std::unique_lock lock(cv_mutex);
+                while(active_count >= threads) {
+#ifndef NDEBUG
+//                    std::cout << "0, active_count = " << active_count
+//                        << ", pre wait_for" << std::endl;
+#endif
+                    cv.wait_for(lock, std::chrono::seconds(1));
+#ifndef NDEBUG
+//                    std::cout << "0, active_count = " << active_count
+//                        << ", post wait_for" << std::endl;
+#endif
+                }
+            }
+            std::unique_lock lock(cv_mutex);
+            while(active_count > 0) {
+                cv.wait_for(lock, std::chrono::seconds(1));
+            }
+        }
+
+    }
+
     inline std::tuple<std::size_t, std::size_t> filter_minmax(const std::vector<double>& filter) {
         double min = std::numeric_limits<double>::infinity();
         double max = 0.0;
         std::size_t min_index = 0;
         std::size_t max_index = 0;
 
-        for(std::size_t i = 0; i < filter.size(); ++i) {
+        for(std::vector<double>::size_type i = 0; i < filter.size(); ++i) {
             if(filter[i] < min) {
                 min_index = i;
                 min = filter[i];