diff --git a/src/blue_noise.cpp b/src/blue_noise.cpp index 4fe6056..e2404d8 100644 --- a/src/blue_noise.cpp +++ b/src/blue_noise.cpp @@ -9,9 +9,9 @@ #endif void dither::internal::recursive_apply_radius( - std::size_t idx, std::size_t width, std::size_t height, - std::size_t radius, const std::function& fn) { - std::unordered_set visited; + int idx, int width, int height, + int radius, const std::function& fn) { + std::unordered_set visited; #ifndef NDEBUG if(recursive_apply_radius_impl(idx, width, height, radius, fn, visited)) { puts("recursive_apply_radius_impl found result"); @@ -24,13 +24,13 @@ void dither::internal::recursive_apply_radius( } bool dither::internal::recursive_apply_radius_impl( - std::size_t idx, std::size_t width, std::size_t height, - std::size_t radius, const std::function& fn, - std::unordered_set& visited) { + int idx, int width, int height, + int radius, const std::function& fn, + std::unordered_set& visited) { if(fn(idx)) { return true; } - std::size_t x, y, temp; + int x, y, temp; std::tie(x, y) = oneToTwo(idx, width); if(x + 1 < width) { @@ -117,21 +117,21 @@ bool dither::internal::recursive_apply_radius_impl( } -std::vector dither::blue_noise(std::size_t width, std::size_t height, std::size_t threads) { - std::size_t count = width * height; - std::vector filter_out; +std::vector dither::blue_noise(int width, int height, int threads) { + int count = width * height; + std::vector filter_out; filter_out.resize(count); std::vector pbp; // Prototype Binary Pattern pbp.resize(count); std::default_random_engine re(std::random_device{}()); - std::uniform_int_distribution dist(0, count - 1); + std::uniform_int_distribution dist(0, count - 1); - const std::size_t pixel_count = count * 4 / 10; + const int pixel_count = count * 4 / 10; // initialize pbp - for(std::size_t i = 0; i < count; ++i) { + for(int i = 0; i < count; ++i) { if(i < pixel_count) { pbp[i] = true; } else { @@ -139,21 +139,21 @@ std::vector dither::blue_noise(std::size_t width, std::size_t height, std: } } // randomize pbp - for(std::size_t i = 0; i < count-1; ++i) { + for(int i = 0; i < count-1; ++i) { decltype(dist)::param_type range{i+1, count-1}; - std::size_t ridx = dist(re, range); + int ridx = dist(re, range); // probably can't use std::swap since using std::vector bool temp = pbp[i]; pbp[i] = pbp[ridx]; pbp[ridx] = temp; } //#ifndef NDEBUG - printf("Inserting %ld pixels into image of max count %ld\n", pixel_count, count); + printf("Inserting %d pixels into image of max count %d\n", pixel_count, count); // generate image from randomized pbp FILE *random_noise_image = fopen("random_noise.pbm", "w"); - fprintf(random_noise_image, "P1\n%ld %ld\n", width, height); - for(std::size_t y = 0; y < height; ++y) { - for(std::size_t x = 0; x < width; ++x) { + fprintf(random_noise_image, "P1\n%d %d\n", width, height); + for(int y = 0; y < height; ++y) { + for(int x = 0; x < width; ++x) { fprintf(random_noise_image, "%d ", pbp[internal::twoToOne(x, y, width)] ? 1 : 0); } fputc('\n', random_noise_image); @@ -162,15 +162,15 @@ std::vector dither::blue_noise(std::size_t width, std::size_t height, std: //#endif //#ifndef NDEBUG - std::size_t iterations = 0; + int iterations = 0; //#endif - std::size_t filter_size = (width + height) / 2; + int filter_size = (width + height) / 2; while(true) { //#ifndef NDEBUG // if(++iterations % 10 == 0) { - printf("Iteration %ld\n", ++iterations); + printf("Iteration %d\n", ++iterations); // } //#endif // get filter values @@ -178,14 +178,14 @@ std::vector dither::blue_noise(std::size_t width, std::size_t height, std: filter_out, threads); #ifndef NDEBUG -// for(std::size_t i = 0; i < count; ++i) { -// std::size_t x, y; +// for(int i = 0; i < count; ++i) { +// int x, y; // std::tie(x, y) = internal::oneToTwo(i, width); -// printf("%ld (%ld, %ld): %f\n", i, x, y, filter_out[i]); +// printf("%d (%d, %d): %f\n", i, x, y, filter_out[i]); // } #endif - std::size_t min, max, min_zero, max_one; + int min, max, min_zero, max_one; std::tie(min, max) = internal::filter_minmax(filter_out); if(!pbp[max]) { max_one = internal::get_one_or_zero(pbp, true, max, width, height); @@ -221,7 +221,7 @@ std::vector dither::blue_noise(std::size_t width, std::size_t height, std: filter_out, threads); // get second buffer's min - std::size_t second_min; + int second_min; std::tie(second_min, std::ignore) = internal::filter_minmax(filter_out); if(pbp[second_min]) { second_min = internal::get_one_or_zero(pbp, false, second_min, width, height); @@ -242,9 +242,9 @@ std::vector dither::blue_noise(std::size_t width, std::size_t height, std: //#ifndef NDEBUG // generate blue_noise image from pbp FILE *blue_noise_image = fopen("blue_noise.pbm", "w"); - fprintf(blue_noise_image, "P1\n%ld %ld\n", width, height); - for(std::size_t y = 0; y < height; ++y) { - for(std::size_t x = 0; x < width; ++x) { + fprintf(blue_noise_image, "P1\n%d %d\n", width, height); + for(int y = 0; y < height; ++y) { + for(int x = 0; x < width; ++x) { fprintf(blue_noise_image, "%d ", pbp[internal::twoToOne(x, y, width)] ? 1 : 0); } fputc('\n', blue_noise_image); diff --git a/src/blue_noise.hpp b/src/blue_noise.hpp index 15f5ef8..d2d0e13 100644 --- a/src/blue_noise.hpp +++ b/src/blue_noise.hpp @@ -13,40 +13,40 @@ namespace dither { -std::vector blue_noise(std::size_t width, std::size_t height, std::size_t threads = 1); +std::vector blue_noise(int width, int height, int threads = 1); namespace internal { - inline std::size_t twoToOne(std::size_t x, std::size_t y, std::size_t width) { + inline int twoToOne(int x, int y, int width) { return x + y * width; } - inline std::tuple oneToTwo(std::size_t i, std::size_t width) { + inline std::tuple oneToTwo(int i, int width) { return {i % width, i / width}; } - constexpr double mu_squared = 1.5 * 1.5; + constexpr float mu_squared = 1.5 * 1.5; - inline double gaussian(double x, double y) { + inline float gaussian(float x, float y) { return std::exp(-(x*x + y*y)/(2*mu_squared)); } - inline double filter( + inline float filter( const std::vector& pbp, - std::size_t x, std::size_t y, - std::size_t width, std::size_t height, std::size_t filter_size) { - double sum = 0.0; + int x, int y, + int width, int height, int filter_size) { + float 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 < 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; + for(int q = 0; q < filter_size; ++q) { + int q_prime = (height + filter_size / 2 + y - q) % height; + for(int p = 0; p < filter_size; ++p) { + int 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 - filter_size/2.0, (double)q - filter_size/2.0); + sum += gaussian((float)p - filter_size/2.0, (float)q - filter_size/2.0); } } } @@ -55,12 +55,12 @@ namespace internal { } inline void compute_filter( - const std::vector &pbp, std::size_t width, std::size_t height, - std::size_t count, std::size_t filter_size, std::vector &filter_out, - std::size_t threads = 1) { + const std::vector &pbp, int width, int height, + int count, int filter_size, std::vector &filter_out, + int threads = 1) { if(threads == 1) { - for(std::size_t y = 0; y < height; ++y) { - for(std::size_t x = 0; x < width; ++x) { + for(int y = 0; y < height; ++y) { + for(int x = 0; x < width; ++x) { filter_out[internal::twoToOne(x, y, width)] = internal::filter(pbp, x, y, width, height, filter_size); } @@ -69,20 +69,20 @@ namespace internal { if(threads == 0) { threads = 10; } - std::size_t active_count = 0; + int active_count = 0; std::mutex cv_mutex; std::condition_variable cv; - for(std::size_t i = 0; i < count; ++i) { + for(int 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 *pbp, std::size_t width, - std::size_t height, std::size_t filter_size, - std::vector *fout) { - std::size_t x, y; + std::thread t([] (int *ac, std::mutex *cvm, + std::condition_variable *cv, int i, + const std::vector *pbp, int width, + int height, int filter_size, + std::vector *fout) { + int x, y; std::tie(x, y) = internal::oneToTwo(i, width); (*fout)[i] = internal::filter( *pbp, x, y, width, height, filter_size); @@ -115,13 +115,13 @@ namespace internal { } - inline std::tuple filter_minmax(const std::vector& filter) { - double min = std::numeric_limits::infinity(); - double max = 0.0; - std::size_t min_index = 0; - std::size_t max_index = 0; + inline std::tuple filter_minmax(const std::vector& filter) { + float min = std::numeric_limits::infinity(); + float max = 0.0; + int min_index = 0; + int max_index = 0; - for(std::vector::size_type i = 0; i < filter.size(); ++i) { + for(std::vector::size_type i = 0; i < filter.size(); ++i) { if(filter[i] < min) { min_index = i; min = filter[i]; @@ -136,25 +136,25 @@ namespace internal { } void recursive_apply_radius( - std::size_t idx, std::size_t width, - std::size_t height, std::size_t radius, - const std::function& fn); + int idx, int width, + int height, int radius, + const std::function& fn); bool recursive_apply_radius_impl( - std::size_t idx, std::size_t width, - std::size_t height, std::size_t radius, - const std::function& fn, - std::unordered_set& visited); + int idx, int width, + int height, int radius, + const std::function& fn, + std::unordered_set& visited); - inline std::size_t get_one_or_zero( + inline int get_one_or_zero( const std::vector& pbp, bool get_one, - std::size_t idx, std::size_t width, std::size_t height) { - std::size_t found_idx; + int idx, int width, int height) { + int found_idx; bool found = false; - for(std::size_t radius = 1; radius <= 12; ++radius) { + for(int radius = 1; radius <= 12; ++radius) { recursive_apply_radius( idx, width, height, radius, - [&found_idx, &found, &pbp, &get_one] (std::size_t idx) { + [&found_idx, &found, &pbp, &get_one] (int idx) { if((get_one && pbp[idx]) || (!get_one && !pbp[idx])) { found_idx = idx; found = true;