--- /dev/null
+#include "image.hpp"
+
+#include <cstdio>
+#include <random>
+
+image::Bl::Bl(int width, int height) :
+data(width * height),
+width(width),
+height(height)
+{}
+
+image::Bl::Bl(const std::vector<uint8_t> &data, int width) :
+data(data),
+width(width),
+height(data.size() / width)
+{}
+
+image::Bl::Bl(std::vector<uint8_t> &&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<unsigned int> 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());
+}
--- /dev/null
+#ifndef DITHERING_IMAGE_HPP
+#define DITHERING_IMAGE_HPP
+
+#include <cstdint>
+#include <vector>
+#include <string>
+
+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<color_type> 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<uint8_t> &data, int width);
+ Bl(std::vector<uint8_t> &&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<color_type> 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<uint8_t> data;
+ int width;
+ int height;
+ };
+}
+
+#endif