image-colours/colour_extractor.cpp
2022-12-07 14:50:26 +02:00

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;
}