Fix blue-noise when not using OpenCL
This commit is contained in:
parent
e715c18a4d
commit
2357fd9c05
5 changed files with 87 additions and 33 deletions
|
@ -7,14 +7,12 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#include <CL/opencl.h>
|
#include <CL/opencl.h>
|
||||||
|
|
||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
# include <cstdio>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
image::Bl dither::blue_noise(int width, int height, int threads, bool use_opencl) {
|
image::Bl dither::blue_noise(int width, int height, int threads, bool use_opencl) {
|
||||||
|
|
||||||
|
@ -93,6 +91,7 @@ image::Bl dither::blue_noise(int width, int height, int threads, bool use_opencl
|
||||||
if(!result.empty()) {
|
if(!result.empty()) {
|
||||||
return internal::rangeToBl(result, width);
|
return internal::rangeToBl(result, width);
|
||||||
}
|
}
|
||||||
|
std::cout << "ERROR: Empty result\n";
|
||||||
} while (false);
|
} while (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +101,7 @@ image::Bl dither::blue_noise(int width, int height, int threads, bool use_opencl
|
||||||
return internal::rangeToBl(internal::blue_noise_impl(width, height, threads), width);
|
return internal::rangeToBl(internal::blue_noise_impl(width, height, threads), width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "ERROR: Invalid state (end of blue_noise fn)\n";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ std::vector<unsigned int> dither::internal::blue_noise_impl(int width, int heigh
|
||||||
std::vector<bool> pbp = random_noise(count, count * 4 / 10);
|
std::vector<bool> pbp = random_noise(count, count * 4 / 10);
|
||||||
pbp.resize(count);
|
pbp.resize(count);
|
||||||
|
|
||||||
//#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
printf("Inserting %d pixels into image of max count %d\n", pixel_count, count);
|
printf("Inserting %d pixels into image of max count %d\n", pixel_count, count);
|
||||||
// generate image from randomized pbp
|
// generate image from randomized pbp
|
||||||
FILE *random_noise_image = fopen("random_noise.pbm", "w");
|
FILE *random_noise_image = fopen("random_noise.pbm", "w");
|
||||||
|
@ -126,7 +126,7 @@ std::vector<unsigned int> dither::internal::blue_noise_impl(int width, int heigh
|
||||||
fputc('\n', random_noise_image);
|
fputc('\n', random_noise_image);
|
||||||
}
|
}
|
||||||
fclose(random_noise_image);
|
fclose(random_noise_image);
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
//#ifndef NDEBUG
|
//#ifndef NDEBUG
|
||||||
int iterations = 0;
|
int iterations = 0;
|
||||||
|
@ -138,7 +138,9 @@ std::vector<unsigned int> dither::internal::blue_noise_impl(int width, int heigh
|
||||||
|
|
||||||
internal::compute_filter(pbp, width, height, count, filter_size,
|
internal::compute_filter(pbp, width, height, count, filter_size,
|
||||||
filter_out, precomputed.get(), threads);
|
filter_out, precomputed.get(), threads);
|
||||||
|
#ifndef NDEBUG
|
||||||
internal::write_filter(filter_out, width, "filter_out_start.pgm");
|
internal::write_filter(filter_out, width, "filter_out_start.pgm");
|
||||||
|
#endif
|
||||||
while(true) {
|
while(true) {
|
||||||
//#ifndef NDEBUG
|
//#ifndef NDEBUG
|
||||||
// if(++iterations % 10 == 0) {
|
// if(++iterations % 10 == 0) {
|
||||||
|
@ -149,13 +151,13 @@ std::vector<unsigned int> dither::internal::blue_noise_impl(int width, int heigh
|
||||||
internal::compute_filter(pbp, width, height, count, filter_size,
|
internal::compute_filter(pbp, width, height, count, filter_size,
|
||||||
filter_out, precomputed.get(), threads);
|
filter_out, precomputed.get(), threads);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
//#ifndef NDEBUG
|
||||||
// for(int i = 0; i < count; ++i) {
|
// for(int i = 0; i < count; ++i) {
|
||||||
// int x, y;
|
// int x, y;
|
||||||
// std::tie(x, y) = internal::oneToTwo(i, width);
|
// std::tie(x, y) = internal::oneToTwo(i, width);
|
||||||
// printf("%d (%d, %d): %f\n", i, x, y, filter_out[i]);
|
// printf("%d (%d, %d): %f\n", i, x, y, filter_out[i]);
|
||||||
// }
|
// }
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
int min, max;
|
int min, max;
|
||||||
std::tie(min, max) = internal::filter_minmax(filter_out, pbp);
|
std::tie(min, max) = internal::filter_minmax(filter_out, pbp);
|
||||||
|
@ -180,6 +182,7 @@ std::vector<unsigned int> dither::internal::blue_noise_impl(int width, int heigh
|
||||||
|
|
||||||
if(iterations % 100 == 0) {
|
if(iterations % 100 == 0) {
|
||||||
// generate blue_noise image from pbp
|
// generate blue_noise image from pbp
|
||||||
|
#ifndef NDEBUG
|
||||||
FILE *blue_noise_image = fopen("blue_noise.pbm", "w");
|
FILE *blue_noise_image = fopen("blue_noise.pbm", "w");
|
||||||
fprintf(blue_noise_image, "P1\n%d %d\n", width, height);
|
fprintf(blue_noise_image, "P1\n%d %d\n", width, height);
|
||||||
for(int y = 0; y < height; ++y) {
|
for(int y = 0; y < height; ++y) {
|
||||||
|
@ -189,13 +192,16 @@ std::vector<unsigned int> dither::internal::blue_noise_impl(int width, int heigh
|
||||||
fputc('\n', blue_noise_image);
|
fputc('\n', blue_noise_image);
|
||||||
}
|
}
|
||||||
fclose(blue_noise_image);
|
fclose(blue_noise_image);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal::compute_filter(pbp, width, height, count, filter_size,
|
internal::compute_filter(pbp, width, height, count, filter_size,
|
||||||
filter_out, precomputed.get(), threads);
|
filter_out, precomputed.get(), threads);
|
||||||
|
#ifndef NDEBUG
|
||||||
internal::write_filter(filter_out, width, "filter_out_final.pgm");
|
internal::write_filter(filter_out, width, "filter_out_final.pgm");
|
||||||
|
#endif
|
||||||
|
|
||||||
//#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// generate blue_noise image from pbp
|
// generate blue_noise image from pbp
|
||||||
FILE *blue_noise_image = fopen("blue_noise.pbm", "w");
|
FILE *blue_noise_image = fopen("blue_noise.pbm", "w");
|
||||||
fprintf(blue_noise_image, "P1\n%d %d\n", width, height);
|
fprintf(blue_noise_image, "P1\n%d %d\n", width, height);
|
||||||
|
@ -206,7 +212,7 @@ std::vector<unsigned int> dither::internal::blue_noise_impl(int width, int heigh
|
||||||
fputc('\n', blue_noise_image);
|
fputc('\n', blue_noise_image);
|
||||||
}
|
}
|
||||||
fclose(blue_noise_image);
|
fclose(blue_noise_image);
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
std::cout << "Generating dither_array...\n";
|
std::cout << "Generating dither_array...\n";
|
||||||
std::vector<unsigned int> dither_array(count);
|
std::vector<unsigned int> dither_array(count);
|
||||||
|
@ -234,9 +240,13 @@ std::vector<unsigned int> dither::internal::blue_noise_impl(int width, int heigh
|
||||||
dither_array[min] = i;
|
dither_array[min] = i;
|
||||||
}
|
}
|
||||||
std::cout << "\nRanking last half of pixels...\n";
|
std::cout << "\nRanking last half of pixels...\n";
|
||||||
|
std::vector<bool> reversed_pbp(pbp);
|
||||||
for (unsigned int i = (count + 1) / 2; i < (unsigned int)count; ++i) {
|
for (unsigned int i = (count + 1) / 2; i < (unsigned int)count; ++i) {
|
||||||
std::cout << i << ' ';
|
std::cout << i << ' ';
|
||||||
internal::compute_filter(pbp, width, height, count, filter_size,
|
for(unsigned int i = 0; i < pbp.size(); ++i) {
|
||||||
|
reversed_pbp[i] = !pbp[i];
|
||||||
|
}
|
||||||
|
internal::compute_filter(reversed_pbp, width, height, count, filter_size,
|
||||||
filter_out, precomputed.get(), threads);
|
filter_out, precomputed.get(), threads);
|
||||||
std::tie(std::ignore, max) = internal::filter_minmax(filter_out, pbp);
|
std::tie(std::ignore, max) = internal::filter_minmax(filter_out, pbp);
|
||||||
pbp[max] = true;
|
pbp[max] = true;
|
||||||
|
@ -468,6 +478,7 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
|
||||||
{
|
{
|
||||||
printf("Inserting %d pixels into image of max count %d\n", pixel_count, count);
|
printf("Inserting %d pixels into image of max count %d\n", pixel_count, count);
|
||||||
// generate image from randomized pbp
|
// generate image from randomized pbp
|
||||||
|
#ifndef NDEBUG
|
||||||
FILE *random_noise_image = fopen("random_noise.pbm", "w");
|
FILE *random_noise_image = fopen("random_noise.pbm", "w");
|
||||||
fprintf(random_noise_image, "P1\n%d %d\n", width, height);
|
fprintf(random_noise_image, "P1\n%d %d\n", width, height);
|
||||||
for(int y = 0; y < height; ++y) {
|
for(int y = 0; y < height; ++y) {
|
||||||
|
@ -477,6 +488,7 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
|
||||||
fputc('\n', random_noise_image);
|
fputc('\n', random_noise_image);
|
||||||
}
|
}
|
||||||
fclose(random_noise_image);
|
fclose(random_noise_image);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!get_filter()) {
|
if(!get_filter()) {
|
||||||
|
@ -488,7 +500,9 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
|
||||||
clReleaseCommandQueue(queue);
|
clReleaseCommandQueue(queue);
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
|
#ifndef NDEBUG
|
||||||
internal::write_filter(filter, width, "filter_out_start.pgm");
|
internal::write_filter(filter, width, "filter_out_start.pgm");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int iterations = 0;
|
int iterations = 0;
|
||||||
|
@ -526,6 +540,7 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
|
||||||
std::cout << "max was " << max << ", second_min is " << second_min
|
std::cout << "max was " << max << ", second_min is " << second_min
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
// generate blue_noise image from pbp
|
// generate blue_noise image from pbp
|
||||||
|
#ifndef NDEBUG
|
||||||
FILE *blue_noise_image = fopen("blue_noise.pbm", "w");
|
FILE *blue_noise_image = fopen("blue_noise.pbm", "w");
|
||||||
fprintf(blue_noise_image, "P1\n%d %d\n", width, height);
|
fprintf(blue_noise_image, "P1\n%d %d\n", width, height);
|
||||||
for(int y = 0; y < height; ++y) {
|
for(int y = 0; y < height; ++y) {
|
||||||
|
@ -535,12 +550,14 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
|
||||||
fputc('\n', blue_noise_image);
|
fputc('\n', blue_noise_image);
|
||||||
}
|
}
|
||||||
fclose(blue_noise_image);
|
fclose(blue_noise_image);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!get_filter()) {
|
if(!get_filter()) {
|
||||||
std::cerr << "OpenCL: Failed to execute do_filter (at end)\n";
|
std::cerr << "OpenCL: Failed to execute do_filter (at end)\n";
|
||||||
} else {
|
} else {
|
||||||
|
#ifndef NDEBUG
|
||||||
internal::write_filter(filter, width, "filter_out_final.pgm");
|
internal::write_filter(filter, width, "filter_out_final.pgm");
|
||||||
FILE *blue_noise_image = fopen("blue_noise.pbm", "w");
|
FILE *blue_noise_image = fopen("blue_noise.pbm", "w");
|
||||||
fprintf(blue_noise_image, "P1\n%d %d\n", width, height);
|
fprintf(blue_noise_image, "P1\n%d %d\n", width, height);
|
||||||
|
@ -551,6 +568,7 @@ std::vector<unsigned int> dither::internal::blue_noise_cl_impl(
|
||||||
fputc('\n', blue_noise_image);
|
fputc('\n', blue_noise_image);
|
||||||
}
|
}
|
||||||
fclose(blue_noise_image);
|
fclose(blue_noise_image);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
|
@ -90,6 +90,10 @@ namespace internal {
|
||||||
int width, int height, int filter_size) {
|
int width, int height, int filter_size) {
|
||||||
float sum = 0.0f;
|
float sum = 0.0f;
|
||||||
|
|
||||||
|
if (filter_size % 2 == 0) {
|
||||||
|
++filter_size;
|
||||||
|
}
|
||||||
|
|
||||||
// Should be range -M/2 to M/2, but size_t cannot be negative, so range
|
// Should be range -M/2 to M/2, but size_t cannot be negative, so range
|
||||||
// is 0 to M.
|
// is 0 to M.
|
||||||
// p' = (M + x - (p - M/2)) % M = (3M/2 + x - p) % M
|
// p' = (M + x - (p - M/2)) % M = (3M/2 + x - p) % M
|
||||||
|
@ -99,8 +103,8 @@ namespace internal {
|
||||||
for(int p = 0; p < filter_size; ++p) {
|
for(int p = 0; p < filter_size; ++p) {
|
||||||
int p_prime = (width - filter_size / 2 + x + p) % width;
|
int p_prime = (width - filter_size / 2 + x + p) % width;
|
||||||
if(pbp[utility::twoToOne(p_prime, q_prime, width, height)]) {
|
if(pbp[utility::twoToOne(p_prime, q_prime, width, height)]) {
|
||||||
sum += gaussian((float)p - filter_size/2.0F + 0.5F,
|
sum += gaussian(p - filter_size/2,
|
||||||
(float)q - filter_size/2.0F + 0.5F);
|
q - filter_size/2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,6 +119,10 @@ namespace internal {
|
||||||
const std::vector<float> &precomputed) {
|
const std::vector<float> &precomputed) {
|
||||||
float sum = 0.0f;
|
float sum = 0.0f;
|
||||||
|
|
||||||
|
if (filter_size % 2 == 0) {
|
||||||
|
++filter_size;
|
||||||
|
}
|
||||||
|
|
||||||
for(int q = 0; q < filter_size; ++q) {
|
for(int q = 0; q < filter_size; ++q) {
|
||||||
int q_prime = (height - filter_size / 2 + y + q) % height;
|
int q_prime = (height - filter_size / 2 + y + q) % height;
|
||||||
for(int p = 0; p < filter_size; ++p) {
|
for(int p = 0; p < filter_size; ++p) {
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
|
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
|
|
||||||
|
bool image::Base::isValid() const {
|
||||||
|
return getWidth() > 0 && getHeight() > 0 && getSize() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
image::Bl::Bl() :
|
image::Bl::Bl() :
|
||||||
data(),
|
data(),
|
||||||
width(0),
|
width(0),
|
||||||
|
@ -60,7 +64,7 @@ void image::Bl::randomize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int image::Bl::getSize() {
|
unsigned int image::Bl::getSize() const {
|
||||||
return data.size();
|
return data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,8 +82,17 @@ const uint8_t* image::Bl::getDataC() const {
|
||||||
return &data[0];
|
return &data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int image::Bl::getWidth() const {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int image::Bl::getHeight() const {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
bool image::Bl::canWriteFile(file_type type) {
|
bool image::Bl::canWriteFile(file_type type) {
|
||||||
if(!isValid()) {
|
if(!isValid()) {
|
||||||
|
std::cout << "Cannot write image because isValid() is false\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
@ -89,18 +102,22 @@ bool image::Bl::canWriteFile(file_type type) {
|
||||||
case file_type::PNG:
|
case file_type::PNG:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
std::cout << "Cannot write image because received invalid file_type\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool image::Bl::writeToFile(file_type type, bool canOverwrite, const char *filename) {
|
bool image::Bl::writeToFile(file_type type, bool canOverwrite, const char *filename) {
|
||||||
if(!isValid() || !canWriteFile(type)) {
|
if(!isValid() || !canWriteFile(type)) {
|
||||||
|
std::cout << "ERROR: Image is not valid or cannot write file type\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *file = fopen(filename, "r");
|
FILE *file = fopen(filename, "r");
|
||||||
if(file && !canOverwrite) {
|
if(file && !canOverwrite) {
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
std::cout << "ERROR: Will not overwite existing file \"" << filename
|
||||||
|
<< "\"" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +128,7 @@ bool image::Bl::writeToFile(file_type type, bool canOverwrite, const char *filen
|
||||||
if(type == file_type::PNG) {
|
if(type == file_type::PNG) {
|
||||||
FILE *outfile = fopen(filename, "wb");
|
FILE *outfile = fopen(filename, "wb");
|
||||||
if (outfile == nullptr) {
|
if (outfile == nullptr) {
|
||||||
|
std::cout << "ERROR: Failed to open file for writing (png)\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const static auto pngErrorLFn = [] (png_structp /* unused */,
|
const static auto pngErrorLFn = [] (png_structp /* unused */,
|
||||||
|
@ -129,6 +147,7 @@ bool image::Bl::writeToFile(file_type type, bool canOverwrite, const char *filen
|
||||||
|
|
||||||
if (png_ptr == nullptr) {
|
if (png_ptr == nullptr) {
|
||||||
fclose(outfile);
|
fclose(outfile);
|
||||||
|
std::cout << "ERROR: Failed to set up writing png file (png_ptr)\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,12 +155,14 @@ bool image::Bl::writeToFile(file_type type, bool canOverwrite, const char *filen
|
||||||
if (info_ptr == nullptr) {
|
if (info_ptr == nullptr) {
|
||||||
png_destroy_write_struct(&png_ptr, nullptr);
|
png_destroy_write_struct(&png_ptr, nullptr);
|
||||||
fclose(outfile);
|
fclose(outfile);
|
||||||
|
std::cout << "ERROR: Failed to set up writing png file (png_infop)\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
fclose(outfile);
|
fclose(outfile);
|
||||||
|
std::cout << "ERROR: Failed to write image file (png error)\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +204,7 @@ bool image::Bl::writeToFile(file_type type, bool canOverwrite, const char *filen
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
std::cout << "ERROR: Cannot write image file, invalid type\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for(unsigned int i = 0; i < data.size(); ++i) {
|
for(unsigned int i = 0; i < data.size(); ++i) {
|
||||||
|
@ -205,6 +227,7 @@ bool image::Bl::writeToFile(file_type type, bool canOverwrite, const char *filen
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
std::cout << "ERROR: Cannot write image file, invalid type\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,7 +239,3 @@ bool image::Bl::writeToFile(file_type type, bool canOverwrite, const char *filen
|
||||||
bool image::Bl::writeToFile(file_type type, bool canOverwrite, const std::string &filename) {
|
bool image::Bl::writeToFile(file_type type, bool canOverwrite, const std::string &filename) {
|
||||||
return writeToFile(type, canOverwrite, filename.c_str());
|
return writeToFile(type, canOverwrite, filename.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool image::Bl::isValid() const {
|
|
||||||
return width > 0 && height > 0 && data.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,10 +34,13 @@ namespace image {
|
||||||
|
|
||||||
virtual void randomize() = 0;
|
virtual void randomize() = 0;
|
||||||
|
|
||||||
virtual int getSize() = 0;
|
virtual unsigned int getSize() const = 0;
|
||||||
virtual uint8_t* getData() = 0;
|
virtual uint8_t* getData() = 0;
|
||||||
virtual const uint8_t* getDataC() const = 0;
|
virtual const uint8_t* getDataC() const = 0;
|
||||||
|
|
||||||
|
virtual unsigned int getWidth() const = 0;
|
||||||
|
virtual unsigned int getHeight() const = 0;
|
||||||
|
|
||||||
virtual int getTypesCount() = 0;
|
virtual int getTypesCount() = 0;
|
||||||
virtual std::vector<color_type> getTypes() = 0;
|
virtual std::vector<color_type> getTypes() = 0;
|
||||||
virtual int getTypeStride(color_type type) = 0;
|
virtual int getTypeStride(color_type type) = 0;
|
||||||
|
@ -45,6 +48,7 @@ namespace image {
|
||||||
virtual bool canWriteFile(file_type type) = 0;
|
virtual bool canWriteFile(file_type type) = 0;
|
||||||
virtual bool writeToFile(file_type type, bool canOverwrite, const char *filename) = 0;
|
virtual bool writeToFile(file_type type, bool canOverwrite, const char *filename) = 0;
|
||||||
virtual bool writeToFile(file_type type, bool canOverwrite, const std::string &filename) = 0;
|
virtual bool writeToFile(file_type type, bool canOverwrite, const std::string &filename) = 0;
|
||||||
|
bool isValid() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Bl : public Base {
|
class Bl : public Base {
|
||||||
|
@ -62,20 +66,22 @@ namespace image {
|
||||||
Bl& operator=(const Bl &other) = default;
|
Bl& operator=(const Bl &other) = default;
|
||||||
Bl& operator=(Bl &&other) = default;
|
Bl& operator=(Bl &&other) = default;
|
||||||
|
|
||||||
virtual void randomize() override;
|
void randomize() override;
|
||||||
|
|
||||||
virtual int getSize() override;
|
unsigned int getSize() const override;
|
||||||
virtual uint8_t* getData() override;
|
uint8_t* getData() override;
|
||||||
virtual const uint8_t* getDataC() const override;
|
const uint8_t* getDataC() const override;
|
||||||
|
|
||||||
virtual int getTypesCount() override { return 1; }
|
unsigned int getWidth() const override;
|
||||||
virtual std::vector<color_type> getTypes() override { return { color_type::Black }; }
|
unsigned int getHeight() const override;
|
||||||
virtual int getTypeStride(color_type) override { return 0; }
|
|
||||||
|
|
||||||
virtual bool canWriteFile(file_type type) override;
|
int getTypesCount() override { return 1; }
|
||||||
virtual bool writeToFile(file_type type, bool canOverwrite, const char *filename) override;
|
std::vector<color_type> getTypes() override { return { color_type::Black }; }
|
||||||
virtual bool writeToFile(file_type type, bool canOverwrite, const std::string &filename) override;
|
int getTypeStride(color_type) override { return 0; }
|
||||||
virtual bool isValid() const;
|
|
||||||
|
bool canWriteFile(file_type type) override;
|
||||||
|
bool writeToFile(file_type type, bool canOverwrite, const char *filename) override;
|
||||||
|
bool writeToFile(file_type type, bool canOverwrite, const std::string &filename) override;
|
||||||
private:
|
private:
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
int width;
|
int width;
|
||||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -3,11 +3,14 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
//#ifndef NDEBUG
|
|
||||||
std::cout << "Trying blue_noise..." << std::endl;
|
std::cout << "Trying blue_noise..." << std::endl;
|
||||||
image::Bl bl = dither::blue_noise(64, 64, 15, true);
|
image::Bl bl = dither::blue_noise(32, 32, 15, false);
|
||||||
bl.writeToFile(image::file_type::PNG, true, "blueNoiseOut.png");
|
if(!bl.writeToFile(image::file_type::PNG, true, "blueNoiseOut.png")) {
|
||||||
//#endif
|
std::cout << "ERROR: Failed to write result to file\n";
|
||||||
|
std::cout << "size is " << bl.getSize() << ", width is "
|
||||||
|
<< bl.getWidth() << ", height is " << bl.getHeight()
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue