#include "frei0r.hpp"
#include <algorithm>
#include <vector>
#include <utility>
#include <cassert>
#include <iostream>
class twolay0r : public frei0r::filter
{
static unsigned char grey(unsigned int value)
{
unsigned char* rgba = reinterpret_cast<unsigned char*>(&value);
unsigned char gw= (rgba[0] + rgba[1] + 2*rgba[2])/4;
return gw;
}
struct histogram
{
histogram()
: hist(256)
{
std::fill(hist.begin(),hist.end(),0);
}
void operator()(uint32_t value)
{
++hist[grey(value)];
}
std::vector<unsigned int> hist;
};
public:
twolay0r(unsigned int width, unsigned int height)
{
}
virtual void update(double time,
uint32_t* out,
const uint32_t* in)
{
histogram h;
// create histogramm
for (const unsigned int* i=in; i != in + (width*height);++i)
h(*i);
// calc th
int th=127;
int th_old=0;
while (th!=th_old)
{
th_old=th;
// calc low
double num = 0;
double val = 0;
for (int i= (int)(th-1); i!= -1; --i)
{
num += h.hist[i];
val += h.hist[i]*i;
}
unsigned char low = static_cast<unsigned char>(val/num);
// clac hi
num = 0;
val = 0;
for (unsigned int i=th;i!=256;++i)
{
num += h.hist[i];
val += h.hist[i]*i;
}
unsigned char hi = static_cast<unsigned char>(val/num);
th = (low + hi) / 2;
}
// create b/w image with the th value
{
uint32_t* outpixel= out;
const uint32_t* pixel=in;
while(pixel != in+(width*height))
{
if ( grey(*pixel)<th )
*outpixel=0xFF000000;
else
*outpixel=0xFFFFFFFF;
++outpixel;
++pixel;
}
}
}
};
frei0r::construct<twolay0r> plugin("Twolay0r",
"dynamic thresholding",
"Martin Bayer",
0,2);