Fix image::Bl write, use image::Bl as result for blue_noise

This commit is contained in:
Stephen Seo 2021-02-11 11:33:14 +09:00
parent 5155b847ca
commit 5826c3677c
6 changed files with 134 additions and 82 deletions

View file

@ -9,7 +9,8 @@ endif
SOURCES= \ SOURCES= \
src/main.cpp \ src/main.cpp \
src/blue_noise.cpp src/blue_noise.cpp \
src/image.cpp
OBJECTS=${subst .cpp,.o,${SOURCES}} OBJECTS=${subst .cpp,.o,${SOURCES}}
all: Dithering all: Dithering

View file

@ -12,10 +12,11 @@
# include <cstdio> # include <cstdio>
#endif #endif
std::vector<bool> dither::blue_noise(int width, int height, int threads) { image::Bl dither::blue_noise(int width, int height, int threads, bool use_opencl) {
bool use_opencl = false; bool using_opencl = false;
if(use_opencl) {
// try to use OpenCL // try to use OpenCL
do { do {
cl_device_id device; cl_device_id device;
@ -86,13 +87,15 @@ std::vector<bool> dither::blue_noise(int width, int height, int threads) {
clReleaseContext(context); clReleaseContext(context);
if(!result.empty()) { if(!result.empty()) {
return result; return internal::toBl(result, width);
} }
} while (false); } while (false);
}
if(!use_opencl) { if(!using_opencl) {
std::cout << "OpenCL: Failed to setup/use, using regular impl..." << std::endl; std::cout << "OpenCL: Failed to setup/use or is not enabled, using regular impl..."
return internal::blue_noise_impl(width, height, threads); << std::endl;
return internal::toBl(internal::blue_noise_impl(width, height, threads), width);
} }
return {}; return {};

View file

@ -11,14 +11,16 @@
#include <cstdio> #include <cstdio>
#include <queue> #include <queue>
#include <random> #include <random>
#include <cassert>
#include <CL/opencl.h> #include <CL/opencl.h>
#include "utility.hpp" #include "utility.hpp"
#include "image.hpp"
namespace dither { namespace dither {
std::vector<bool> blue_noise(int width, int height, int threads = 1); image::Bl blue_noise(int width, int height, int threads = 1, bool use_opencl = true);
namespace internal { namespace internal {
std::vector<bool> blue_noise_impl(int width, int height, int threads = 1); std::vector<bool> blue_noise_impl(int width, int height, int threads = 1);
@ -311,6 +313,18 @@ namespace internal {
} }
fclose(filter_image); fclose(filter_image);
} }
inline image::Bl toBl(const std::vector<bool>& pbp, int width) {
image::Bl bwImage(width, pbp.size() / width);
assert((unsigned long)bwImage.getSize() >= pbp.size()
&& "New image::Bl size too small (pbp's size is not a multiple of width)");
for(unsigned int i = 0; i < pbp.size(); ++i) {
bwImage.getData()[i] = pbp[i] ? 1 : 0;
}
return bwImage;
}
} // namespace dither::internal } // namespace dither::internal
} // namespace dither } // namespace dither

View file

@ -3,6 +3,12 @@
#include <cstdio> #include <cstdio>
#include <random> #include <random>
image::Bl::Bl() :
data(),
width(0),
height(0)
{}
image::Bl::Bl(int width, int height) : image::Bl::Bl(int width, int height) :
data(width * height), data(width * height),
width(width), width(width),
@ -22,6 +28,10 @@ height(data.size() / width)
{} {}
void image::Bl::randomize() { void image::Bl::randomize() {
if(!isValid()) {
return;
}
std::default_random_engine re(std::random_device{}()); std::default_random_engine re(std::random_device{}());
std::uniform_int_distribution<unsigned int> dist; std::uniform_int_distribution<unsigned int> dist;
@ -42,10 +52,23 @@ int image::Bl::getSize() {
} }
uint8_t* image::Bl::getData() { uint8_t* image::Bl::getData() {
if(!isValid()) {
return nullptr;
}
return &data[0];
}
const uint8_t* image::Bl::getDataC() const {
if(!isValid()) {
return nullptr;
}
return &data[0]; return &data[0];
} }
bool image::Bl::canWriteFile(file_type type) { bool image::Bl::canWriteFile(file_type type) {
if(!isValid()) {
return false;
}
switch(type) { switch(type) {
case file_type::PBM: case file_type::PBM:
case file_type::PGM: case file_type::PGM:
@ -57,7 +80,7 @@ bool image::Bl::canWriteFile(file_type type) {
} }
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(!canWriteFile(type)) { if(!isValid() || !canWriteFile(type)) {
return false; return false;
} }
@ -66,7 +89,10 @@ bool image::Bl::writeToFile(file_type type, bool canOverwrite, const char *filen
fclose(file); fclose(file);
return false; return false;
} }
if(file) {
fclose(file); fclose(file);
}
switch(type) { switch(type) {
case file_type::PBM: case file_type::PBM:
@ -112,3 +138,7 @@ 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;
}

View file

@ -21,22 +21,22 @@ namespace image {
// TODO PNG support // TODO PNG support
}; };
class base { class Base {
public: public:
base() = default; Base() = default;
virtual ~base() {} virtual ~Base() {}
base(const base &other) = default; Base(const Base &other) = default;
base(base &&other) = default; Base(Base &&other) = default;
base& operator=(const base &other) = default; Base& operator=(const Base &other) = default;
base& operator=(base &&other) = default; Base& operator=(Base &&other) = default;
virtual void randomize() = 0; virtual void randomize() = 0;
virtual int getSize() = 0; virtual int getSize() = 0;
virtual uint8_t* getData() = 0; virtual uint8_t* getData() = 0;
virtual const uint8_t* getDataC() { return getData(); } virtual const uint8_t* getDataC() const = 0;
virtual int getTypesCount() = 0; virtual int getTypesCount() = 0;
virtual std::vector<color_type> getTypes() = 0; virtual std::vector<color_type> getTypes() = 0;
@ -47,8 +47,9 @@ namespace image {
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;
}; };
class Bl : public base { class Bl : public Base {
public: public:
Bl();
Bl(int width, int height); Bl(int width, int height);
Bl(const std::vector<uint8_t> &data, int width); Bl(const std::vector<uint8_t> &data, int width);
Bl(std::vector<uint8_t> &&data, int width); Bl(std::vector<uint8_t> &&data, int width);
@ -64,6 +65,7 @@ namespace image {
virtual int getSize() override; virtual int getSize() override;
virtual uint8_t* getData() override; virtual uint8_t* getData() override;
virtual const uint8_t* getDataC() const override;
virtual int getTypesCount() override { return 1; } virtual int getTypesCount() override { return 1; }
virtual std::vector<color_type> getTypes() override { return { color_type::Black }; } virtual std::vector<color_type> getTypes() override { return { color_type::Black }; }
@ -72,6 +74,7 @@ namespace image {
virtual bool canWriteFile(file_type type) override; virtual bool canWriteFile(file_type type) override;
virtual bool writeToFile(file_type type, bool canOverwrite, const char *filename) override; virtual bool writeToFile(file_type type, bool canOverwrite, const char *filename) override;
virtual bool writeToFile(file_type type, bool canOverwrite, const std::string &filename) override; virtual bool writeToFile(file_type type, bool canOverwrite, const std::string &filename) override;
virtual bool isValid() const;
private: private:
std::vector<uint8_t> data; std::vector<uint8_t> data;
int width; int width;

View file

@ -5,7 +5,8 @@
int main(int argc, char **argv) { int main(int argc, char **argv) {
//#ifndef NDEBUG //#ifndef NDEBUG
std::cout << "Trying blue_noise..." << std::endl; std::cout << "Trying blue_noise..." << std::endl;
dither::blue_noise(100, 100, 8); image::Bl bl = dither::blue_noise(100, 100, 8, true);
bl.writeToFile(image::file_type::PBM, true, "blueNoiseOut.pbm");
//#endif //#endif
return 0; return 0;