170 lines
3.5 KiB
C++
170 lines
3.5 KiB
C++
#include "libImg.h"
|
|
|
|
#define ASSERT_MSG(cond, msg) \
|
|
do { if (!(cond)) { std::cerr << msg << std::endl; assert(cond); } } while (0)
|
|
|
|
// Salva un immagine in formato ppm P6 255
|
|
bool save(const std::string& path, const image& matrix){
|
|
std::ofstream f(path, std::ios::binary);
|
|
if(!f){
|
|
std::cerr<<"Errore in save"<<std::endl;
|
|
return false;
|
|
}
|
|
int w = matrix[0].size();
|
|
int h = matrix.size();
|
|
f << "P6\n" << w << " " << h <<"\n255\n";
|
|
|
|
for (int y = 0; y < h; y++) {
|
|
for(int x = 0; x < w; x++){
|
|
f.write(reinterpret_cast<const char*>(&matrix[y][x]), 3);
|
|
}
|
|
}
|
|
|
|
f.close();
|
|
std::cout << "Fine salvato"<<std::endl;
|
|
return true;
|
|
}
|
|
|
|
//Carica un immagine in formato ppm P6 255
|
|
image load(const std::string& path, int& w, int& h){
|
|
std::ifstream f(path, std::ios::binary);
|
|
if (!f) {
|
|
std::cerr << "File non aperto" <<std::endl;
|
|
w = 1;
|
|
h = 1;
|
|
return errore;
|
|
}
|
|
std::string magic;
|
|
int val;
|
|
f >> magic >> w >> h >> val;
|
|
if(magic != "P6"){
|
|
std::cerr << " Magic Sbagliato"<<std::endl;
|
|
w = 1;
|
|
h = 1;
|
|
return errore;
|
|
}
|
|
if(val != 255){
|
|
std::cerr << "Dimensione sbagliata dei colori "<<val<<std::endl;
|
|
w = 1;
|
|
h = 1;
|
|
return errore;
|
|
}
|
|
|
|
char sep;
|
|
f.get(sep);
|
|
|
|
image matrix(h, std::vector<pixel>(w));
|
|
for(int y = 0; y < h; y++){
|
|
for(int x = 0; x < w; x++){
|
|
f.read(reinterpret_cast<char*>(&matrix[y][x]), 3);
|
|
if(f.gcount() != 3){
|
|
std::cerr << "Distanza sbagliata" <<std::endl;
|
|
w = 1;
|
|
h = 1;
|
|
std::cerr << "Strano, mancano i pixel"<<std::endl;
|
|
return errore;
|
|
}
|
|
}
|
|
}
|
|
return matrix;
|
|
}
|
|
|
|
//Controlla l'ugualianza di 2 immagini
|
|
// usa tutte le tecniche che sono standard + comparatore tra pixel
|
|
bool images_equal(const image& a, const image& b) {
|
|
if (a.size() != b.size() || a[0].size() != b[0].size()) return false;
|
|
return a == b;
|
|
}
|
|
|
|
//Genera rumore pseudo-casuale
|
|
image randomImage(int w, int h){
|
|
image matrix(h, std::vector<pixel>(w));
|
|
|
|
for(int y = 0; y < h; ++y){
|
|
for(int x = 0; x < w; ++x){
|
|
matrix[y][x] = {
|
|
static_cast<unsigned char>(dist(rng)),
|
|
static_cast<unsigned char>(dist(rng)),
|
|
static_cast<unsigned char>(dist(rng))
|
|
};
|
|
}
|
|
}
|
|
return matrix;
|
|
}
|
|
|
|
//converte un immagini in bianco e nero
|
|
void BWimage(image &matrix, float lim){
|
|
ASSERT_MSG(lim >= 0 && lim <= 1, "Il valore limite deve essere tra 0-1");
|
|
|
|
const pixel t = {
|
|
static_cast<unsigned char>(lim*255),
|
|
static_cast<unsigned char>(lim*255),
|
|
static_cast<unsigned char>(lim*255)
|
|
};
|
|
|
|
for(auto &i: matrix){
|
|
for(auto &p: i){
|
|
if(p >= t)
|
|
p = {255,255,255};
|
|
else
|
|
p = {0, 0, 0};
|
|
}
|
|
}
|
|
}
|
|
|
|
//converte un immagine in scala di grigi
|
|
void Grayimage(image &matrix){
|
|
for(auto &i: matrix){
|
|
for(auto &p: i){
|
|
short s = (short) p.lum();
|
|
p = {
|
|
static_cast<unsigned char>(s),
|
|
static_cast<unsigned char>(s),
|
|
static_cast<unsigned char>(s)
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned long long countW(image &matrix){
|
|
int ans = 0;
|
|
pixel max = {255, 255, 255};
|
|
for(const auto &y:matrix){
|
|
for(const auto &p: y){
|
|
if(p == max)ans++;
|
|
}
|
|
}
|
|
return ans;
|
|
}
|
|
// +- 0,25 0,125 ...
|
|
float BWAimage(image &matrix){
|
|
image test;
|
|
float lim = 0.5f;
|
|
unsigned long long avg = matrix.size() * matrix[0].size() / 2;
|
|
for(int i = 4; i <= 1<<6; i = i<<1){
|
|
test = matrix;
|
|
BWimage(test, lim);
|
|
if(countW(test) < avg){
|
|
lim -= 1.0f/i;
|
|
}
|
|
else{
|
|
lim += 1.0f/i;
|
|
}
|
|
// Ez debug
|
|
// std::cout<<"Il lim è: "<<lim<<std::endl;
|
|
}
|
|
matrix = test;
|
|
return lim;
|
|
}
|
|
|
|
void invertImage(image &matrix){
|
|
for(auto &y:matrix){
|
|
for(auto &p:y){
|
|
p.r ^= 0xFF;
|
|
p.g ^= 0xFF;
|
|
p.b ^= 0xFF;
|
|
}
|
|
}
|
|
}
|
|
|