diff --git a/src/image.cpp b/src/image.cpp new file mode 100644 index 0000000..e763a65 --- /dev/null +++ b/src/image.cpp @@ -0,0 +1,114 @@ +#include "image.hpp" + +#include +#include + +image::Bl::Bl(int width, int height) : +data(width * height), +width(width), +height(height) +{} + +image::Bl::Bl(const std::vector &data, int width) : +data(data), +width(width), +height(data.size() / width) +{} + +image::Bl::Bl(std::vector &&data, int width) : +data(std::move(data)), +width(width), +height(data.size() / width) +{} + +void image::Bl::randomize() { + std::default_random_engine re(std::random_device{}()); + std::uniform_int_distribution dist; + + for(unsigned int i = 0; i < data.size(); ++i) { + data[i] = i < data.size() / 2 ? 255 : 0; + } + + for(unsigned int i = 0; i < data.size() - 1; ++i) { + int ridx = dist(re, decltype(dist)::param_type{i+1, (unsigned int)data.size()-1}); + uint8_t temp = data[i]; + data[i] = data[ridx]; + data[ridx] = temp; + } +} + +int image::Bl::getSize() { + return data.size(); +} + +uint8_t* image::Bl::getData() { + return &data[0]; +} + +bool image::Bl::canWriteFile(file_type type) { + switch(type) { + case file_type::PBM: + case file_type::PGM: + case file_type::PPM: + return true; + default: + return false; + } +} + +bool image::Bl::writeToFile(file_type type, bool canOverwrite, const char *filename) { + if(!canWriteFile(type)) { + return false; + } + + FILE *file = fopen(filename, "r"); + if(file && !canOverwrite) { + fclose(file); + return false; + } + fclose(file); + + switch(type) { + case file_type::PBM: + file = fopen(filename, "w"); + fprintf(file, "P1\n%d %d", width, height); + break; + case file_type::PGM: + file = fopen(filename, "wb"); + fprintf(file, "P5\n%d %d\n255", width, height); + break; + case file_type::PPM: + file = fopen(filename, "wb"); + fprintf(file, "P6\n%d %d\n255", width, height); + break; + default: + fclose(file); + return false; + } + for(unsigned int i = 0; i < data.size(); ++i) { + if(i % width == 0) { + fprintf(file, "\n"); + } + switch(type) { + case file_type::PBM: + fprintf(file, "%d ", data[i] == 0 ? 0 : 1); + break; + case file_type::PGM: + fprintf(file, "%c ", data[i]); + break; + case file_type::PPM: + fprintf(file, "%c %c %c ", data[i], data[i], data[i]); + break; + default: + fclose(file); + return false; + } + } + + fclose(file); + return true; +} + +bool image::Bl::writeToFile(file_type type, bool canOverwrite, const std::string &filename) { + return writeToFile(type, canOverwrite, filename.c_str()); +} diff --git a/src/image.hpp b/src/image.hpp new file mode 100644 index 0000000..81fbbde --- /dev/null +++ b/src/image.hpp @@ -0,0 +1,82 @@ +#ifndef DITHERING_IMAGE_HPP +#define DITHERING_IMAGE_HPP + +#include +#include +#include + +namespace image { + enum class color_type { + Black, + Red, + Green, + Blue, + Alpha, + }; + + enum class file_type { + PBM, + PGM, + PPM, + // TODO PNG support + }; + + class base { + public: + base() = default; + virtual ~base() {} + + base(const base &other) = default; + base(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 int getTypesCount() = 0; + virtual std::vector getTypes() = 0; + virtual int getTypeStride(color_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 std::string &filename) = 0; + }; + + class Bl : public base { + public: + Bl(int width, int height); + Bl(const std::vector &data, int width); + Bl(std::vector &&data, int width); + virtual ~Bl() {} + + Bl(const Bl &other) = default; + Bl(Bl &&other) = default; + + Bl& operator=(const Bl &other) = default; + Bl& operator=(Bl &&other) = default; + + virtual void randomize() override; + + virtual int getSize() override; + virtual uint8_t* getData() override; + + virtual int getTypesCount() override { return 1; } + virtual std::vector getTypes() override { return { color_type::Black }; } + virtual int getTypeStride(color_type) override { return 0; } + + 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; + private: + std::vector data; + int width; + int height; + }; +} + +#endif