196 lines
4.1 KiB
C++
196 lines
4.1 KiB
C++
#include "colour_extractor.h"
|
|
|
|
#include <math.h>
|
|
#include <string.h>
|
|
|
|
// CONSTRUCTORS
|
|
ColourExtractor::ColourExtractor(size_t h_levels, size_t s_levels,
|
|
size_t l_levels)
|
|
:m_pixels(NULL), m_max_colour_count(0), m_h_levels(h_levels),
|
|
m_s_levels(s_levels), m_l_levels(l_levels)
|
|
{
|
|
m_pixels = new size_t[m_h_levels * m_s_levels * m_l_levels];
|
|
memset(m_pixels, 0, m_h_levels * m_s_levels * m_l_levels * sizeof(size_t));
|
|
}
|
|
|
|
// PROTECTED FUNCS
|
|
size_t ColourExtractor::quantize(struct ColourHSL hsl) const
|
|
{
|
|
size_t result = 0;
|
|
|
|
size_t h_quant = 0;
|
|
size_t s_quant = 0;
|
|
size_t l_quant = 0;
|
|
|
|
l_quant = static_cast<size_t>(round(hsl.l * (m_l_levels - 1)));
|
|
if (0 == l_quant)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
s_quant = static_cast<size_t>(round(hsl.s * (m_s_levels - 1)));
|
|
if (0 == s_quant)
|
|
{
|
|
goto end;
|
|
}
|
|
|
|
h_quant = static_cast<size_t>(round(hsl.h / 360.0 * (m_h_levels - 1)));
|
|
|
|
end:
|
|
result += h_quant;
|
|
|
|
result *= m_s_levels;
|
|
result += s_quant;
|
|
|
|
result *= m_l_levels;
|
|
result += l_quant;
|
|
|
|
return result;
|
|
}
|
|
|
|
struct ColourHSL ColourExtractor::dequantize(size_t colour) const
|
|
{
|
|
struct ColourHSL result;
|
|
size_t h_quant;
|
|
size_t s_quant;
|
|
size_t l_quant;
|
|
|
|
l_quant = colour % m_l_levels;
|
|
colour /= m_l_levels;
|
|
|
|
s_quant = colour % m_s_levels;
|
|
colour /= m_s_levels;
|
|
|
|
h_quant = colour % m_h_levels;
|
|
|
|
result.h = static_cast<double>(h_quant) * 360.0 / (m_h_levels - 1);
|
|
result.s = static_cast<double>(s_quant) / (m_s_levels - 1);
|
|
result.l = static_cast<double>(l_quant) / (m_l_levels - 1);
|
|
|
|
return result;
|
|
}
|
|
|
|
// PUBLIC FUNCS
|
|
void ColourExtractor::get_quantization_levels(size_t& h_levels,
|
|
size_t& s_levels, size_t& l_levels) const
|
|
{
|
|
h_levels = m_h_levels;
|
|
s_levels = m_s_levels;
|
|
l_levels = m_l_levels;
|
|
}
|
|
|
|
void ColourExtractor::set_quantization_levels(size_t h_levels, size_t s_levels,
|
|
size_t l_levels)
|
|
{
|
|
delete[] m_pixels;
|
|
|
|
m_h_levels = h_levels;
|
|
m_s_levels = s_levels;
|
|
m_l_levels = l_levels;
|
|
|
|
m_pixels = new size_t[m_h_levels * m_s_levels * m_l_levels];
|
|
memset(m_pixels, 0, m_h_levels * m_s_levels * m_l_levels * sizeof(size_t));
|
|
}
|
|
|
|
size_t ColourExtractor::get_h_quantization_levels() const
|
|
{
|
|
return m_h_levels;
|
|
}
|
|
|
|
void ColourExtractor::set_h_quantization_levels(size_t h_levels)
|
|
{
|
|
delete[] m_pixels;
|
|
|
|
m_h_levels = h_levels;
|
|
|
|
m_pixels = new size_t[m_h_levels * m_s_levels * m_l_levels];
|
|
memset(m_pixels, 0, m_h_levels * m_s_levels * m_l_levels * sizeof(size_t));
|
|
}
|
|
|
|
size_t ColourExtractor::get_s_quantization_levels() const
|
|
{
|
|
return m_s_levels;
|
|
}
|
|
|
|
void ColourExtractor::set_s_quantization_levels(size_t s_levels)
|
|
{
|
|
delete[] m_pixels;
|
|
|
|
m_s_levels = s_levels;
|
|
|
|
m_pixels = new size_t[m_h_levels * m_s_levels * m_l_levels];
|
|
memset(m_pixels, 0, m_h_levels * m_s_levels * m_l_levels * sizeof(size_t));
|
|
}
|
|
|
|
size_t ColourExtractor::get_v_quantization_levels() const
|
|
{
|
|
return m_l_levels;
|
|
}
|
|
|
|
void ColourExtractor::set_v_quantization_levels(size_t l_levels)
|
|
{
|
|
delete[] m_pixels;
|
|
|
|
m_l_levels = l_levels;
|
|
|
|
m_pixels = new size_t[m_h_levels * m_s_levels * m_l_levels];
|
|
memset(m_pixels, 0, m_h_levels * m_s_levels * m_l_levels * sizeof(size_t));
|
|
}
|
|
|
|
void ColourExtractor::add_pixel(struct ColourHSL hsl)
|
|
{
|
|
size_t colour_quant;
|
|
|
|
colour_quant = quantize(hsl);
|
|
m_pixels[colour_quant] += 1;
|
|
|
|
if (m_max_colour_count < m_pixels[colour_quant])
|
|
{
|
|
m_max_colour_count = m_pixels[colour_quant];
|
|
}
|
|
}
|
|
|
|
void ColourExtractor::clear_pixels()
|
|
{
|
|
for (size_t i = 0; i < m_h_levels * m_s_levels * m_l_levels; ++i)
|
|
{
|
|
m_pixels[i] = 0;
|
|
}
|
|
m_max_colour_count = 0;
|
|
}
|
|
|
|
struct ColourHSL ColourExtractor::extract_colour() const
|
|
{
|
|
struct ColourHSL result = {0.0, 0.0, 0.0};
|
|
struct ColourHSL temp_colour;
|
|
size_t max_colour_value = 0;
|
|
size_t temp_colour_value;
|
|
double temp_colour_weight;
|
|
|
|
for (size_t i = 0; i < m_h_levels * m_s_levels * m_l_levels; ++i)
|
|
{
|
|
if (0 == m_pixels[i])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
temp_colour = dequantize(i);
|
|
temp_colour_weight = static_cast<double>(m_pixels[i]);
|
|
temp_colour_weight /= m_max_colour_count;
|
|
|
|
temp_colour_value = evaluate_colour(temp_colour, temp_colour_weight);
|
|
if (temp_colour_value > max_colour_value)
|
|
{
|
|
result = temp_colour;
|
|
max_colour_value = temp_colour_value;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
ColourExtractor::~ColourExtractor()
|
|
{
|
|
delete[] m_pixels;
|
|
}
|