Some work on image objects
This commit is contained in:
parent
6ca0db1e57
commit
5155b847ca
2 changed files with 196 additions and 0 deletions
114
src/image.cpp
Normal file
114
src/image.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
#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());
|
||||
}
|
82
src/image.hpp
Normal file
82
src/image.hpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
#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
|
Loading…
Reference in a new issue