]> git.seodisparate.com - blue_noise_generation/commitdiff
Fix image::Bl write, use image::Bl as result for blue_noise
authorStephen Seo <seo.disparate@gmail.com>
Thu, 11 Feb 2021 02:33:14 +0000 (11:33 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Thu, 11 Feb 2021 02:33:14 +0000 (11:33 +0900)
Makefile
src/blue_noise.cpp
src/blue_noise.hpp
src/image.cpp
src/image.hpp
src/main.cpp

index 7eb90139f0a1b00a1ad64a2b876a5fb6d765d196..d4e60a163766d0bde8b48ec0cd8d42ada82b5d5f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,8 @@ endif
 
 SOURCES= \
        src/main.cpp \
-       src/blue_noise.cpp
+       src/blue_noise.cpp \
+       src/image.cpp
 OBJECTS=${subst .cpp,.o,${SOURCES}}
 
 all: Dithering
index bbf25b5645fc570bc210cf3f8c818438f8233a8f..5e7ff74950a038bbf8dddbc73919be0bbe190305 100644 (file)
 # include <cstdio>
 #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;
 
-    // try to use OpenCL
-    do {
-        cl_device_id device;
-        cl_context context;
-        cl_program program;
-        cl_int err;
+    if(use_opencl) {
+        // try to use OpenCL
+        do {
+            cl_device_id device;
+            cl_context context;
+            cl_program program;
+            cl_int err;
 
-        cl_platform_id platform;
+            cl_platform_id platform;
 
-        int filter_size = (width + height) / 2;
+            int filter_size = (width + height) / 2;
 
-        err = clGetPlatformIDs(1, &platform, nullptr);
-        if(err != CL_SUCCESS) {
-            std::cerr << "OpenCL: Failed to identify a platform\n";
-            break;
-        }
-
-        err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, nullptr);
-        if(err != CL_SUCCESS) {
-            std::cerr << "OpenCL: Failed to get a device\n";
-            break;
-        }
-
-        context = clCreateContext(nullptr, 1, &device, nullptr, nullptr, &err);
-
-        {
-            char buf[1024];
-            std::ifstream program_file("src/blue_noise.cl");
-            std::string program_string;
-            while(program_file.good()) {
-                program_file.read(buf, 1024);
-                if(int read_count = program_file.gcount(); read_count > 0) {
-                    program_string.append(buf, read_count);
-                }
+            err = clGetPlatformIDs(1, &platform, nullptr);
+            if(err != CL_SUCCESS) {
+                std::cerr << "OpenCL: Failed to identify a platform\n";
+                break;
             }
 
-            const char *string_ptr = program_string.c_str();
-            std::size_t program_size = program_string.size();
-            program = clCreateProgramWithSource(context, 1, (const char**)&string_ptr, &program_size, &err);
+            err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, nullptr);
             if(err != CL_SUCCESS) {
-                std::cerr << "OpenCL: Failed to create the program\n";
-                clReleaseContext(context);
+                std::cerr << "OpenCL: Failed to get a device\n";
                 break;
             }
 
-            err = clBuildProgram(program, 1, &device, nullptr, nullptr, nullptr);
-            if(err != CL_SUCCESS) {
-                std::cerr << "OpenCL: Failed to build the program\n";
+            context = clCreateContext(nullptr, 1, &device, nullptr, nullptr, &err);
+
+            {
+                char buf[1024];
+                std::ifstream program_file("src/blue_noise.cl");
+                std::string program_string;
+                while(program_file.good()) {
+                    program_file.read(buf, 1024);
+                    if(int read_count = program_file.gcount(); read_count > 0) {
+                        program_string.append(buf, read_count);
+                    }
+                }
 
-                std::size_t log_size;
-                clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, nullptr, &log_size);
-                std::unique_ptr<char[]> log = std::make_unique<char[]>(log_size + 1);
-                log[log_size] = 0;
-                clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size, log.get(), nullptr);
-                std::cerr << log.get() << std::endl;
+                const char *string_ptr = program_string.c_str();
+                std::size_t program_size = program_string.size();
+                program = clCreateProgramWithSource(context, 1, (const char**)&string_ptr, &program_size, &err);
+                if(err != CL_SUCCESS) {
+                    std::cerr << "OpenCL: Failed to create the program\n";
+                    clReleaseContext(context);
+                    break;
+                }
 
-                clReleaseProgram(program);
-                clReleaseContext(context);
-                break;
+                err = clBuildProgram(program, 1, &device, nullptr, nullptr, nullptr);
+                if(err != CL_SUCCESS) {
+                    std::cerr << "OpenCL: Failed to build the program\n";
+
+                    std::size_t log_size;
+                    clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, nullptr, &log_size);
+                    std::unique_ptr<char[]> log = std::make_unique<char[]>(log_size + 1);
+                    log[log_size] = 0;
+                    clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size, log.get(), nullptr);
+                    std::cerr << log.get() << std::endl;
+
+                    clReleaseProgram(program);
+                    clReleaseContext(context);
+                    break;
+                }
             }
-        }
 
-        std::cout << "OpenCL: Initialized, trying cl_impl..." << std::endl;
-        std::vector<bool> result = internal::blue_noise_cl_impl(
-            width, height, filter_size, context, device, program);
+            std::cout << "OpenCL: Initialized, trying cl_impl..." << std::endl;
+            std::vector<bool> result = internal::blue_noise_cl_impl(
+                width, height, filter_size, context, device, program);
 
-        clReleaseProgram(program);
-        clReleaseContext(context);
+            clReleaseProgram(program);
+            clReleaseContext(context);
 
-        if(!result.empty()) {
-            return result;
-        }
-    } while (false);
+            if(!result.empty()) {
+                return internal::toBl(result, width);
+            }
+        } while (false);
+    }
 
-    if(!use_opencl) {
-        std::cout << "OpenCL: Failed to setup/use, using regular impl..." << std::endl;
-        return internal::blue_noise_impl(width, height, threads);
+    if(!using_opencl) {
+        std::cout << "OpenCL: Failed to setup/use or is not enabled, using regular impl..."
+            << std::endl;
+        return internal::toBl(internal::blue_noise_impl(width, height, threads), width);
     }
 
     return {};
index f5ad4d5747967c5a32503deb0a8e9cb977b25db4..cb9fc530d2f300ef8250b6dfdf52327db1113adb 100644 (file)
 #include <cstdio>
 #include <queue>
 #include <random>
+#include <cassert>
 
 #include <CL/opencl.h>
 
 #include "utility.hpp"
+#include "image.hpp"
 
 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 {
     std::vector<bool> blue_noise_impl(int width, int height, int threads = 1);
@@ -311,6 +313,18 @@ namespace internal {
         }
         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
index e763a65f7f1e75dc0168f3644667ce6b173f0826..ed8e41c9d0dacf2bb9c3e8abd1f26ee22224a155 100644 (file)
@@ -3,6 +3,12 @@
 #include <cstdio>
 #include <random>
 
+image::Bl::Bl() :
+data(),
+width(0),
+height(0)
+{}
+
 image::Bl::Bl(int width, int height) :
 data(width * height),
 width(width),
@@ -22,6 +28,10 @@ height(data.size() / width)
 {}
 
 void image::Bl::randomize() {
+    if(!isValid()) {
+        return;
+    }
+
     std::default_random_engine re(std::random_device{}());
     std::uniform_int_distribution<unsigned int> dist;
 
@@ -42,10 +52,23 @@ int image::Bl::getSize() {
 }
 
 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];
 }
 
 bool image::Bl::canWriteFile(file_type type) {
+    if(!isValid()) {
+        return false;
+    }
     switch(type) {
     case file_type::PBM:
     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) {
-    if(!canWriteFile(type)) {
+    if(!isValid() || !canWriteFile(type)) {
         return false;
     }
 
@@ -66,7 +89,10 @@ bool image::Bl::writeToFile(file_type type, bool canOverwrite, const char *filen
         fclose(file);
         return false;
     }
-    fclose(file);
+
+    if(file) {
+        fclose(file);
+    }
 
     switch(type) {
     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) {
     return writeToFile(type, canOverwrite, filename.c_str());
 }
+
+bool image::Bl::isValid() const {
+    return width > 0 && height > 0 && data.size() > 0;
+}
index 81fbbde8f843ff8fde543986379de0bf767eefc3..fb478e0774fd8a23c9af0124763d39eea7eb3266 100644 (file)
@@ -21,22 +21,22 @@ namespace image {
         // TODO PNG support
     };
 
-    class base {
+    class Base {
     public:
-        base() = default;
-        virtual ~base() {}
+        Base() = default;
+        virtual ~Base() {}
 
-        base(const base &other) = default;
-        base(base &&other) = default;
+        Base(const Base &other) = default;
+        Base(Base &&other) = default;
 
-        base& operator=(const base &other) = default;
-        base& operator=(base &&other) = default;
+        Base& operator=(const Base &other) = default;
+        Base& operator=(Base &&other) = default;
 
         virtual void randomize() = 0;
 
         virtual int getSize() = 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 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;
     };
 
-    class Bl : public base {
+    class Bl : public Base {
     public:
+        Bl();
         Bl(int width, int height);
         Bl(const 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 uint8_t* getData() override;
+        virtual const uint8_t* getDataC() const override;
 
         virtual int getTypesCount() override { return 1; }
         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 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 isValid() const;
     private:
         std::vector<uint8_t> data;
         int width;
index 51e17aa840ec50a2f76f2b5321cfbf173ddd719c..0b6786a149894b7183a6ec2d38da0c0074d9450c 100644 (file)
@@ -5,7 +5,8 @@
 int main(int argc, char **argv) {
 //#ifndef NDEBUG
     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
 
     return 0;