mirror of https://github.com/KLayout/klayout.git
WIP: HSV support in lay::Color
This commit is contained in:
parent
a6f2528aff
commit
7048dde7b3
|
|
@ -45,12 +45,12 @@ static void clear_colormap (img::DataMapping *dm)
|
|||
|
||||
static void add_colormap (img::DataMapping *dm, double value, lay::color_t color)
|
||||
{
|
||||
dm->false_color_nodes.push_back (std::make_pair (value, std::make_pair (QColor (color), QColor (color))));
|
||||
dm->false_color_nodes.push_back (std::make_pair (value, std::make_pair (lay::Color (color), lay::Color (color))));
|
||||
}
|
||||
|
||||
static void add_colormap2 (img::DataMapping *dm, double value, lay::color_t lcolor, lay::color_t rcolor)
|
||||
{
|
||||
dm->false_color_nodes.push_back (std::make_pair (value, std::make_pair (QColor (lcolor), QColor (rcolor))));
|
||||
dm->false_color_nodes.push_back (std::make_pair (value, std::make_pair (lay::Color (lcolor), lay::Color (rcolor))));
|
||||
}
|
||||
|
||||
static size_t num_colormap_entries (const img::DataMapping *dm)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "dbPolygonTools.h"
|
||||
#include "tlFileUtils.h"
|
||||
#include "tlUri.h"
|
||||
#include "tlThreads.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
|
@ -40,7 +41,6 @@
|
|||
#include <memory.h>
|
||||
|
||||
#include <QImage>
|
||||
#include <QMutex>
|
||||
|
||||
namespace img
|
||||
{
|
||||
|
|
@ -51,8 +51,8 @@ namespace img
|
|||
DataMapping::DataMapping ()
|
||||
: brightness (0.0), contrast (0.0), gamma (1.0), red_gain (1.0), green_gain (1.0), blue_gain (1.0)
|
||||
{
|
||||
false_color_nodes.push_back (std::make_pair (0.0, std::make_pair (QColor (0, 0, 0), QColor (0, 0, 0))));
|
||||
false_color_nodes.push_back (std::make_pair (1.0, std::make_pair (QColor (255, 255, 255), QColor (255, 255, 255))));
|
||||
false_color_nodes.push_back (std::make_pair (0.0, std::make_pair (lay::Color (0, 0, 0), lay::Color (0, 0, 0))));
|
||||
false_color_nodes.push_back (std::make_pair (1.0, std::make_pair (lay::Color (255, 255, 255), lay::Color (255, 255, 255))));
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -192,11 +192,11 @@ DataMapping::create_data_mapping (bool monochrome, double xmin, double xmax, uns
|
|||
|
||||
for (unsigned int i = 1; i < false_color_nodes.size (); ++i) {
|
||||
|
||||
int h1, s1, v1;
|
||||
false_color_nodes [i - 1].second.second.getHsv (&h1, &s1, &v1);
|
||||
unsigned int h1, s1, v1;
|
||||
false_color_nodes [i - 1].second.second.get_hsv (h1, s1, v1);
|
||||
|
||||
int h2, s2, v2;
|
||||
false_color_nodes [i].second.first.getHsv (&h2, &s2, &v2);
|
||||
unsigned int h2, s2, v2;
|
||||
false_color_nodes [i].second.first.get_hsv (h2, s2, v2);
|
||||
|
||||
// The number of steps is chosen such that the full HSV band divides into approximately 200 steps
|
||||
double nsteps = 0.5 * sqrt (double (h1 - h2) * double (h1 - h2) + double (s1 - s2) * double (s1 - s2) + double (v1 - v2) * double (v1 - v2));
|
||||
|
|
@ -206,7 +206,7 @@ DataMapping::create_data_mapping (bool monochrome, double xmin, double xmax, uns
|
|||
|
||||
for (int j = 0; j < n; ++j) {
|
||||
|
||||
QColor c = interpolated_color (false_color_nodes, x);
|
||||
lay::Color c = interpolated_color (false_color_nodes, x);
|
||||
|
||||
double y = 0.0;
|
||||
if (channel == 0) {
|
||||
|
|
@ -260,6 +260,57 @@ DataMapping::create_data_mapping (bool monochrome, double xmin, double xmax, uns
|
|||
return dm;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct compare_first_of_node
|
||||
{
|
||||
bool operator() (const std::pair <double, std::pair<lay::Color, lay::Color> > &a, const std::pair <double, std::pair<lay::Color, lay::Color> > &b) const
|
||||
{
|
||||
return a.first < b.first;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
lay::Color
|
||||
interpolated_color (const DataMapping::false_color_nodes_type &nodes, double x)
|
||||
{
|
||||
if (nodes.size () < 1) {
|
||||
return lay::Color ();
|
||||
} else if (nodes.size () < 2) {
|
||||
return x < nodes[0].first ? nodes[0].second.first : nodes[0].second.second;
|
||||
} else {
|
||||
|
||||
std::vector<std::pair<double, std::pair<lay::Color, lay::Color> > >::const_iterator p = std::lower_bound (nodes.begin (), nodes.end (), std::make_pair (x, std::make_pair (lay::Color (), lay::Color ())), compare_first_of_node ());
|
||||
if (p == nodes.end ()) {
|
||||
return nodes.back ().second.second;
|
||||
} else if (p == nodes.begin ()) {
|
||||
return nodes.front ().second.first;
|
||||
} else {
|
||||
|
||||
double x1 = p[-1].first;
|
||||
double x2 = p->first;
|
||||
|
||||
unsigned int h1 = 0, s1 = 0, v1 = 0;
|
||||
p[-1].second.second.get_hsv (h1, s1, v1);
|
||||
|
||||
unsigned int h2 = 0, s2 = 0, v2 = 0;
|
||||
p->second.first.get_hsv (h2, s2, v2);
|
||||
|
||||
int h = int (0.5 + h1 + double(x - x1) * double (h2 - h1) / double(x2 - x1));
|
||||
int s = int (0.5 + s1 + double(x - x1) * double (s2 - s1) / double(x2 - x1));
|
||||
int v = int (0.5 + v1 + double(x - x1) * double (v2 - v1) / double(x2 - x1));
|
||||
|
||||
return lay::Color::from_hsv ((unsigned int) h, (unsigned int) s, (unsigned int) v);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// img::DataHeader definition and implementation
|
||||
|
||||
|
|
@ -690,7 +741,7 @@ private:
|
|||
|
||||
static size_t make_id ()
|
||||
{
|
||||
static QMutex id_lock;
|
||||
static tl::Mutex id_lock;
|
||||
static size_t s_id_counter = 1;
|
||||
|
||||
// Get a new Id for the object. Id == 0 is reserved.
|
||||
|
|
@ -1283,7 +1334,7 @@ Object::from_string (const char *str, const char *base_dir)
|
|||
|
||||
double x = 0.0;
|
||||
lay::ColorConverter cc;
|
||||
QColor cl, cr;
|
||||
lay::Color cl, cr;
|
||||
std::string s;
|
||||
|
||||
m_data_mapping.false_color_nodes.clear ();
|
||||
|
|
@ -1654,7 +1705,7 @@ Object::to_string () const
|
|||
for (unsigned int i = 0; i < data_mapping ().false_color_nodes.size (); ++i) {
|
||||
os << data_mapping ().false_color_nodes[i].first;
|
||||
os << ",";
|
||||
const std::pair<QColor, QColor> &clr = data_mapping ().false_color_nodes[i].second;
|
||||
const std::pair<lay::Color, lay::Color> &clr = data_mapping ().false_color_nodes[i].second;
|
||||
os << tl::to_word_or_quoted_string (cc.to_string (clr.first));
|
||||
if (clr.first != clr.second) {
|
||||
os << ",";
|
||||
|
|
|
|||
|
|
@ -33,13 +33,11 @@
|
|||
#include "dbMatrix.h"
|
||||
#include "dbPolygon.h"
|
||||
#include "tlDataMapping.h"
|
||||
#include "layViewOp.h"
|
||||
#include "layColor.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <QColor>
|
||||
|
||||
namespace img {
|
||||
|
||||
class DataHeader;
|
||||
|
|
@ -52,7 +50,7 @@ class DataHeader;
|
|||
struct IMG_PUBLIC DataMapping
|
||||
{
|
||||
public:
|
||||
typedef std::vector< std::pair<double, std::pair<QColor, QColor> > > false_color_nodes_type;
|
||||
typedef std::vector< std::pair<double, std::pair<lay::Color, lay::Color> > > false_color_nodes_type;
|
||||
|
||||
/**
|
||||
* @brief The constructor
|
||||
|
|
@ -139,6 +137,11 @@ public:
|
|||
tl::DataMappingBase *create_data_mapping (bool monochrome, double xmin, double xmax, unsigned int channel) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A helper function to interpolate a color in the color bar at a given x
|
||||
*/
|
||||
lay::Color interpolated_color (const DataMapping::false_color_nodes_type &nodes, double x);
|
||||
|
||||
/**
|
||||
* @brief A image object
|
||||
*
|
||||
|
|
|
|||
|
|
@ -735,9 +735,9 @@ PropertiesPage::blue_spinbox_changed (double value)
|
|||
void
|
||||
PropertiesPage::black_to_white ()
|
||||
{
|
||||
std::vector <std::pair <double, std::pair<QColor, QColor> > > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, std::make_pair (QColor (0, 0, 0), QColor (0, 0, 0))));
|
||||
nodes.push_back (std::make_pair (1.0, std::make_pair (QColor (255, 255, 255), QColor (255, 255, 255))));
|
||||
std::vector <std::pair <double, std::pair<lay::Color, lay::Color> > > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, std::make_pair (lay::Color (0, 0, 0), lay::Color (0, 0, 0))));
|
||||
nodes.push_back (std::make_pair (1.0, std::make_pair (lay::Color (255, 255, 255), lay::Color (255, 255, 255))));
|
||||
false_color_control->set_nodes (nodes);
|
||||
emit edited ();
|
||||
}
|
||||
|
|
@ -745,9 +745,9 @@ PropertiesPage::black_to_white ()
|
|||
void
|
||||
PropertiesPage::white_to_black ()
|
||||
{
|
||||
std::vector <std::pair <double, std::pair<QColor, QColor> > > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, std::make_pair (QColor (255, 255, 255), QColor (255, 255, 255))));
|
||||
nodes.push_back (std::make_pair (1.0, std::make_pair (QColor (0, 0, 0), QColor (0, 0, 0))));
|
||||
std::vector <std::pair <double, std::pair<lay::Color, lay::Color> > > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, std::make_pair (lay::Color (255, 255, 255), lay::Color (255, 255, 255))));
|
||||
nodes.push_back (std::make_pair (1.0, std::make_pair (lay::Color (0, 0, 0), lay::Color (0, 0, 0))));
|
||||
false_color_control->set_nodes (nodes);
|
||||
emit edited ();
|
||||
}
|
||||
|
|
@ -755,9 +755,9 @@ PropertiesPage::white_to_black ()
|
|||
void
|
||||
PropertiesPage::red_to_blue ()
|
||||
{
|
||||
std::vector <std::pair <double, std::pair<QColor, QColor> > > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, std::make_pair (QColor (255, 0, 0), QColor (255, 0, 0))));
|
||||
nodes.push_back (std::make_pair (1.0, std::make_pair (QColor (0, 0, 255), QColor (0, 0, 255))));
|
||||
std::vector <std::pair <double, std::pair<lay::Color, lay::Color> > > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, std::make_pair (lay::Color (255, 0, 0), lay::Color (255, 0, 0))));
|
||||
nodes.push_back (std::make_pair (1.0, std::make_pair (lay::Color (0, 0, 255), lay::Color (0, 0, 255))));
|
||||
false_color_control->set_nodes (nodes);
|
||||
emit edited ();
|
||||
}
|
||||
|
|
@ -765,9 +765,9 @@ PropertiesPage::red_to_blue ()
|
|||
void
|
||||
PropertiesPage::blue_to_red ()
|
||||
{
|
||||
std::vector <std::pair <double, std::pair<QColor, QColor> > > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, std::make_pair (QColor (0, 0, 255), QColor (0, 0, 255))));
|
||||
nodes.push_back (std::make_pair (1.0, std::make_pair (QColor (255, 0, 0), QColor (255, 0, 0))));
|
||||
std::vector <std::pair <double, std::pair<lay::Color, lay::Color> > > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, std::make_pair (lay::Color (0, 0, 255), lay::Color (0, 0, 255))));
|
||||
nodes.push_back (std::make_pair (1.0, std::make_pair (lay::Color (255, 0, 0), lay::Color (255, 0, 0))));
|
||||
false_color_control->set_nodes (nodes);
|
||||
emit edited ();
|
||||
}
|
||||
|
|
@ -775,7 +775,7 @@ PropertiesPage::blue_to_red ()
|
|||
void
|
||||
PropertiesPage::reverse_color_order ()
|
||||
{
|
||||
std::vector <std::pair <double, std::pair<QColor, QColor> > > nodes (false_color_control->nodes ());
|
||||
std::vector <std::pair <double, std::pair<lay::Color, lay::Color> > > nodes (false_color_control->nodes ());
|
||||
for (size_t i = 0; i < nodes.size () / 2; ++i) {
|
||||
std::swap (nodes [i].second.second, nodes [nodes.size () - 1 - i].second.first);
|
||||
std::swap (nodes [i].second.first, nodes [nodes.size () - 1 - i].second.second);
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ namespace {
|
|||
|
||||
struct ColorMapConverter
|
||||
{
|
||||
std::string to_string (const std::pair<double, std::pair<QColor, QColor> > &cm) const
|
||||
std::string to_string (const std::pair<double, std::pair<lay::Color, lay::Color> > &cm) const
|
||||
{
|
||||
std::string s;
|
||||
s = tl::to_string (cm.first);
|
||||
|
|
@ -389,7 +389,7 @@ namespace {
|
|||
return s;
|
||||
}
|
||||
|
||||
void from_string (const std::string &s, std::pair<double, std::pair<QColor, QColor> > &cm) const
|
||||
void from_string (const std::string &s, std::pair<double, std::pair<lay::Color, lay::Color> > &cm) const
|
||||
{
|
||||
tl::Extractor ex (s.c_str ());
|
||||
|
||||
|
|
@ -427,7 +427,7 @@ tl::XMLStruct<ImageProxy> s_img_structure ("image-data",
|
|||
tl::make_member (&ImageProxy::max_value, &ImageProxy::set_max_value, "max-value") +
|
||||
tl::make_element (&ImageProxy::data_mapping, &ImageProxy::set_data_mapping, "data-mapping",
|
||||
tl::make_element (&img::DataMapping::false_color_nodes, "color-map",
|
||||
tl::make_member<std::pair<double, std::pair<QColor, QColor> >, img::DataMapping::false_color_nodes_type::const_iterator, img::DataMapping::false_color_nodes_type, ColorMapConverter> (&img::DataMapping::false_color_nodes_type::begin, &img::DataMapping::false_color_nodes_type::end, &img::DataMapping::false_color_nodes_type::push_back, "color-map-entry", ColorMapConverter ())
|
||||
tl::make_member<std::pair<double, std::pair<lay::Color, lay::Color> >, img::DataMapping::false_color_nodes_type::const_iterator, img::DataMapping::false_color_nodes_type, ColorMapConverter> (&img::DataMapping::false_color_nodes_type::begin, &img::DataMapping::false_color_nodes_type::end, &img::DataMapping::false_color_nodes_type::push_back, "color-map-entry", ColorMapConverter ())
|
||||
) +
|
||||
tl::make_member (&img::DataMapping::brightness, "brightness") +
|
||||
tl::make_member (&img::DataMapping::contrast, "contrast") +
|
||||
|
|
|
|||
|
|
@ -44,52 +44,6 @@ const int min_bar_height = 4;
|
|||
const double min_value_interval = 1e-3;
|
||||
const double epsilon = 1e-6;
|
||||
|
||||
struct compare_first_of_node
|
||||
{
|
||||
bool operator() (const std::pair <double, std::pair<QColor, QColor> > &a, const std::pair <double, std::pair<QColor, QColor> > &b) const
|
||||
{
|
||||
return a.first < b.first;
|
||||
}
|
||||
};
|
||||
|
||||
QColor
|
||||
interpolated_color (const std::vector<std::pair <double, std::pair<QColor, QColor> > > &nodes, double x)
|
||||
{
|
||||
if (nodes.size () < 1) {
|
||||
return QColor ();
|
||||
} else if (nodes.size () < 2) {
|
||||
return x < nodes[0].first ? nodes[0].second.first : nodes[0].second.second;
|
||||
} else {
|
||||
|
||||
std::vector<std::pair<double, std::pair<QColor, QColor> > >::const_iterator p = std::lower_bound (nodes.begin (), nodes.end (), std::make_pair (x, std::make_pair (QColor (), QColor ())), compare_first_of_node ());
|
||||
if (p == nodes.end ()) {
|
||||
return nodes.back ().second.second;
|
||||
} else if (p == nodes.begin ()) {
|
||||
return nodes.front ().second.first;
|
||||
} else {
|
||||
|
||||
double x1 = p[-1].first;
|
||||
double x2 = p->first;
|
||||
|
||||
int h1 = 0, s1 = 0, v1 = 0;
|
||||
p[-1].second.second.getHsv (&h1, &s1, &v1);
|
||||
|
||||
int h2 = 0, s2 = 0, v2 = 0;
|
||||
p->second.first.getHsv (&h2, &s2, &v2);
|
||||
|
||||
int h = int (0.5 + h1 + double(x - x1) * double (h2 - h1) / double(x2 - x1));
|
||||
int s = int (0.5 + s1 + double(x - x1) * double (s2 - s1) / double(x2 - x1));
|
||||
int v = int (0.5 + v1 + double(x - x1) * double (v2 - v1) / double(x2 - x1));
|
||||
|
||||
QColor r;
|
||||
r.setHsv (h, s, v);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
TwoColorWidget::TwoColorWidget (QWidget *parent)
|
||||
|
|
@ -173,8 +127,8 @@ TwoColorWidget::lock_changed (bool checked)
|
|||
ColorBar::ColorBar (QWidget *parent)
|
||||
: QWidget (parent), m_dragging (false), m_selected (-1)
|
||||
{
|
||||
m_nodes.push_back (std::make_pair (0.0, std::make_pair (QColor (0, 0, 0), QColor (0, 0, 0))));
|
||||
m_nodes.push_back (std::make_pair (1.0, std::make_pair (QColor (255, 255, 255), QColor (255, 255, 255))));
|
||||
m_nodes.push_back (std::make_pair (0.0, std::make_pair (lay::Color (0, 0, 0), lay::Color (0, 0, 0))));
|
||||
m_nodes.push_back (std::make_pair (1.0, std::make_pair (lay::Color (255, 255, 255), lay::Color (255, 255, 255))));
|
||||
}
|
||||
|
||||
ColorBar::~ColorBar ()
|
||||
|
|
@ -206,7 +160,7 @@ void
|
|||
ColorBar::set_current_color (std::pair<QColor, QColor> c)
|
||||
{
|
||||
if (has_selection ()) {
|
||||
m_nodes [m_selected].second = c;
|
||||
m_nodes [m_selected].second = std::make_pair (lay::Color (c.first.rgb ()), lay::Color (c.second.rgb ()));
|
||||
emit color_mapping_changed ();
|
||||
update ();
|
||||
}
|
||||
|
|
@ -260,22 +214,35 @@ ColorBar::keyPressEvent (QKeyEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct compare_first_of_node
|
||||
{
|
||||
bool operator() (const std::pair <double, std::pair<lay::Color, lay::Color> > &a, const std::pair <double, std::pair<lay::Color, lay::Color> > &b) const
|
||||
{
|
||||
return a.first < b.first;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ColorBar::set_nodes (const std::vector<std::pair<double, std::pair<QColor, QColor> > > &nodes)
|
||||
ColorBar::set_nodes (const std::vector<std::pair<double, std::pair<lay::Color, lay::Color> > > &nodes)
|
||||
{
|
||||
m_nodes = nodes;
|
||||
|
||||
std::sort (m_nodes.begin (), m_nodes.end (), compare_first_of_node ());
|
||||
|
||||
if (m_nodes.size () == 0 || fabs (m_nodes[0].first) > epsilon) {
|
||||
m_nodes.insert (m_nodes.begin (), std::make_pair (0.0, std::make_pair (QColor (0, 0, 0), QColor (0, 0, 0))));
|
||||
m_nodes.insert (m_nodes.begin (), std::make_pair (0.0, std::make_pair (lay::Color (0, 0, 0), lay::Color (0, 0, 0))));
|
||||
} else {
|
||||
m_nodes[0].first = 0.0;
|
||||
}
|
||||
|
||||
std::vector <std::pair <double, std::pair<QColor, QColor> > >::iterator w = m_nodes.begin ();
|
||||
std::vector <std::pair <double, std::pair<QColor, QColor> > >::const_iterator nn = m_nodes.begin ();
|
||||
for (std::vector <std::pair <double, std::pair<QColor, QColor> > >::const_iterator n = m_nodes.begin () + 1; n != m_nodes.end (); ++n) {
|
||||
std::vector <std::pair <double, std::pair<lay::Color, lay::Color> > >::iterator w = m_nodes.begin ();
|
||||
std::vector <std::pair <double, std::pair<lay::Color, lay::Color> > >::const_iterator nn = m_nodes.begin ();
|
||||
for (std::vector <std::pair <double, std::pair<lay::Color, lay::Color> > >::const_iterator n = m_nodes.begin () + 1; n != m_nodes.end (); ++n) {
|
||||
if (fabs (nn->first - n->first) > min_value_interval) {
|
||||
*w++ = *nn;
|
||||
nn = n;
|
||||
|
|
@ -288,7 +255,7 @@ ColorBar::set_nodes (const std::vector<std::pair<double, std::pair<QColor, QColo
|
|||
if (m_nodes.back ().first > 1.0 - min_value_interval) {
|
||||
m_nodes.back ().first = 1.0;
|
||||
} else {
|
||||
m_nodes.push_back (std::make_pair (1.0, std::make_pair (QColor (255, 255, 255), QColor (255, 255, 255))));
|
||||
m_nodes.push_back (std::make_pair (1.0, std::make_pair (lay::Color (255, 255, 255), lay::Color (255, 255, 255))));
|
||||
}
|
||||
|
||||
m_selected = -1;
|
||||
|
|
@ -313,8 +280,8 @@ ColorBar::mousePressEvent (QMouseEvent *event)
|
|||
double xx = double (event->x () - xl) / double (xr - xl);
|
||||
|
||||
double dmin = 100.0;
|
||||
std::vector<std::pair<double, std::pair<QColor, QColor> > >::const_iterator pmin = m_nodes.end ();
|
||||
for (std::vector<std::pair<double, std::pair<QColor, QColor> > >::const_iterator p = m_nodes.begin (); p != m_nodes.end (); ++p) {
|
||||
std::vector<std::pair<double, std::pair<lay::Color, lay::Color> > >::const_iterator pmin = m_nodes.end ();
|
||||
for (std::vector<std::pair<double, std::pair<lay::Color, lay::Color> > >::const_iterator p = m_nodes.begin (); p != m_nodes.end (); ++p) {
|
||||
double d = fabs (p->first - xx);
|
||||
if (d < 0.05 && d < dmin) {
|
||||
dmin = d;
|
||||
|
|
@ -323,9 +290,10 @@ ColorBar::mousePressEvent (QMouseEvent *event)
|
|||
}
|
||||
|
||||
if (pmin != m_nodes.end ()) {
|
||||
m_selected = int (std::distance (std::vector<std::pair<double, std::pair<QColor, QColor> > >::const_iterator (m_nodes.begin ()), pmin));
|
||||
m_selected = int (std::distance (std::vector<std::pair<double, std::pair<lay::Color, lay::Color> > >::const_iterator (m_nodes.begin ()), pmin));
|
||||
emit selection_changed ();
|
||||
emit selection_changed (m_nodes [m_selected].second);
|
||||
std::pair<lay::Color, lay::Color> cp = m_nodes [m_selected].second;
|
||||
emit selection_changed (std::make_pair (QColor (cp.first.rgb ()), QColor (cp.second.rgb ())));
|
||||
m_dragging = true;
|
||||
update ();
|
||||
} else {
|
||||
|
|
@ -359,13 +327,14 @@ ColorBar::mouseDoubleClickEvent (QMouseEvent *event)
|
|||
|
||||
double xx = double (event->x () - xl) / double (xr - xl);
|
||||
|
||||
std::vector<std::pair<double, std::pair<QColor, QColor> > >::iterator p = std::lower_bound (m_nodes.begin (), m_nodes.end (), std::make_pair (xx, std::make_pair (QColor (), QColor ())), compare_first_of_node ());
|
||||
std::vector<std::pair<double, std::pair<lay::Color, lay::Color> > >::iterator p = std::lower_bound (m_nodes.begin (), m_nodes.end (), std::make_pair (xx, std::make_pair (lay::Color (), lay::Color ())), compare_first_of_node ());
|
||||
if (p != m_nodes.begin () && p != m_nodes.end ()) {
|
||||
m_selected = int (std::distance (m_nodes.begin (), p));
|
||||
QColor ci = interpolated_color (m_nodes, xx);
|
||||
lay::Color ci = interpolated_color (m_nodes, xx);
|
||||
m_nodes.insert (p, std::make_pair (xx, std::make_pair (ci, ci)));
|
||||
emit selection_changed ();
|
||||
emit selection_changed (m_nodes [m_selected].second);
|
||||
std::pair<lay::Color, lay::Color> cp = m_nodes [m_selected].second;
|
||||
emit selection_changed (std::make_pair (QColor (cp.first.rgb ()), QColor (cp.second.rgb ())));
|
||||
emit color_mapping_changed ();
|
||||
update ();
|
||||
}
|
||||
|
|
@ -440,9 +409,9 @@ ColorBar::paintEvent (QPaintEvent *)
|
|||
if (xr != xl) {
|
||||
xx = double (x - xl) / double (xr - xl);
|
||||
}
|
||||
QColor c = interpolated_color (m_nodes, xx);
|
||||
lay::Color c = interpolated_color (m_nodes, xx);
|
||||
|
||||
painter.fillRect (x, yb - hbar, 1, hbar + 1, QBrush (c));
|
||||
painter.fillRect (x, yb - hbar, 1, hbar + 1, QBrush (QColor (c.rgb ())));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#define HDR_imgWidgets
|
||||
|
||||
#include "layWidgets.h"
|
||||
#include "layColor.h"
|
||||
#include "imgObject.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
|
|
@ -38,13 +40,6 @@ class QPaintEvent;
|
|||
namespace img
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A helper function to interpolate a color in the color bar at a given x
|
||||
*
|
||||
* TODO: move this somewhere else.
|
||||
*/
|
||||
QColor interpolated_color (const std::vector<std::pair <double, std::pair<QColor, QColor> > > &nodes, double x);
|
||||
|
||||
/**
|
||||
* @brief A two-color widget
|
||||
*
|
||||
|
|
@ -114,9 +109,9 @@ public:
|
|||
return m_selected >= 0;
|
||||
}
|
||||
|
||||
void set_nodes (const std::vector <std::pair <double, std::pair<QColor, QColor> > > &nodes);
|
||||
void set_nodes (const std::vector <std::pair <double, std::pair<lay::Color, lay::Color> > > &nodes);
|
||||
|
||||
const std::vector <std::pair <double, std::pair<QColor, QColor> > > &nodes () const
|
||||
const std::vector <std::pair <double, std::pair<lay::Color, lay::Color> > > &nodes () const
|
||||
{
|
||||
return m_nodes;
|
||||
}
|
||||
|
|
@ -135,7 +130,7 @@ signals:
|
|||
private:
|
||||
bool m_dragging;
|
||||
int m_selected;
|
||||
std::vector <std::pair <double, std::pair<QColor, QColor> > > m_nodes;
|
||||
std::vector <std::pair <double, std::pair<lay::Color, lay::Color> > > m_nodes;
|
||||
std::vector <size_t> m_histogram;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ TEST(1_FloatMono)
|
|||
dm.gamma = 1.5;
|
||||
dm.brightness = 1.25;
|
||||
dm.false_color_nodes.clear ();
|
||||
dm.false_color_nodes.push_back (std::make_pair (0.0, std::make_pair (QColor (0, 0, 0), QColor (0, 0, 0))));
|
||||
dm.false_color_nodes.push_back (std::make_pair (0.5, std::make_pair (QColor (255, 0, 0), QColor (0, 255, 0))));
|
||||
dm.false_color_nodes.push_back (std::make_pair (1.0, std::make_pair (QColor (255, 255, 255), QColor (255, 255, 255))));
|
||||
dm.false_color_nodes.push_back (std::make_pair (0.0, std::make_pair (lay::Color (0, 0, 0), lay::Color (0, 0, 0))));
|
||||
dm.false_color_nodes.push_back (std::make_pair (0.5, std::make_pair (lay::Color (255, 0, 0), lay::Color (0, 255, 0))));
|
||||
dm.false_color_nodes.push_back (std::make_pair (1.0, std::make_pair (lay::Color (255, 255, 255), lay::Color (255, 255, 255))));
|
||||
image.set_data_mapping (dm);
|
||||
|
||||
image.set_pixel (0, 0, 0.25);
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ TEST(1)
|
|||
dm.red_gain = 1.25;
|
||||
dm.green_gain = 0.75;
|
||||
dm.blue_gain = 2.5;
|
||||
QColor c (128, 255, 64);
|
||||
QColor c2 (64, 32, 192);
|
||||
lay::Color c (128, 255, 64);
|
||||
lay::Color c2 (64, 32, 192);
|
||||
dm.false_color_nodes.insert (dm.false_color_nodes.begin () + 1, std::make_pair (0.5, std::make_pair (c, c)));
|
||||
image.set_data_mapping (dm);
|
||||
EXPECT_EQ (copy1.equals (&image), false);
|
||||
|
|
@ -226,7 +226,7 @@ TEST(2)
|
|||
dm.red_gain = 1.25;
|
||||
dm.green_gain = 0.75;
|
||||
dm.blue_gain = 2.5;
|
||||
QColor c (128, 255, 64);
|
||||
lay::Color c (128, 255, 64);
|
||||
dm.false_color_nodes.insert (dm.false_color_nodes.begin () + 1, std::make_pair (0.5, std::make_pair (c, c)));
|
||||
image.set_data_mapping (dm);
|
||||
EXPECT_EQ (copy1.equals (&image), false);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "layColor.h"
|
||||
#include "tlString.h"
|
||||
#include "tlMath.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
|
@ -116,4 +117,82 @@ Color::is_valid () const
|
|||
return (m_color & 0xff000000) != 0;
|
||||
}
|
||||
|
||||
void
|
||||
Color::get_hsv (unsigned int &hue, unsigned int &saturation, unsigned int &value) const
|
||||
{
|
||||
double r = double (red ()) / 255.0;
|
||||
double g = double (green ()) / 255.0;
|
||||
double b = double (blue ()) / 255.0;
|
||||
|
||||
double max = std::max (r, std::max (g, b));
|
||||
double min = std::min (r, std::min (g, b));
|
||||
double delta = max - min;
|
||||
|
||||
value = (unsigned int) tl::round (255.0 * max, 1);
|
||||
hue = 0;
|
||||
saturation = 0;
|
||||
|
||||
if (! tl::equal (delta, 0.0)) {
|
||||
|
||||
saturation = (unsigned int) tl::round (255.0 * delta / max, 1);
|
||||
double h = 0.0;
|
||||
if (tl::equal (r, max)) {
|
||||
h = (g - b) / delta;
|
||||
} else if (tl::equal (g, max)) {
|
||||
h = 2.0f + (b - r) / delta;
|
||||
} else if (tl::equal (b, max)) {
|
||||
h = 4.0f + (r - g) / delta;
|
||||
}
|
||||
h *= 60.0;
|
||||
if (tl::less (h, 0.0)) {
|
||||
h += 360.0;
|
||||
}
|
||||
|
||||
hue = (unsigned int) tl::round (h, 1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static lay::Color color_d (double r, double g, double b)
|
||||
{
|
||||
return lay::Color (tl::round (r * 255.0, 1), tl::round (g * 255.0, 1), tl::round (b * 255.0, 1));
|
||||
}
|
||||
|
||||
lay::Color
|
||||
Color::from_hsv (unsigned int hue, unsigned int saturation, unsigned int value)
|
||||
{
|
||||
if (saturation == 0) {
|
||||
return lay::Color (value, value, value);
|
||||
}
|
||||
|
||||
hue = (hue + 360) % 360;
|
||||
|
||||
double h = double (hue) / 60.0;
|
||||
double s = double (saturation) / 255.0;
|
||||
double v = double (value) / 255.0;
|
||||
|
||||
int i = int (tl::round_down (h, 1));
|
||||
double f = (i & 1) != 0 ? h - i : 1.0 - h + i;
|
||||
double p = v * (1.0 - s);
|
||||
double q = v * (1.0 - s * f);
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
return color_d (v, q, p);
|
||||
case 1:
|
||||
return color_d (q, v, p);
|
||||
case 2:
|
||||
return color_d (p, v, q);
|
||||
case 3:
|
||||
return color_d (p, q, v);
|
||||
case 4:
|
||||
return color_d (q, p, v);
|
||||
case 5:
|
||||
return color_d (v, p, q);
|
||||
default:
|
||||
return lay::Color ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,6 +142,19 @@ public:
|
|||
return (m_color & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the HSV color components
|
||||
* hue: 0..359
|
||||
* saturation: 0..255
|
||||
* value: 0..255
|
||||
*/
|
||||
void get_hsv (unsigned int &hue, unsigned int &saturation, unsigned int &value) const;
|
||||
|
||||
/**
|
||||
* @brief Creates the color from a HSV color
|
||||
*/
|
||||
static lay::Color from_hsv (unsigned int hue, unsigned int saturation, unsigned int value);
|
||||
|
||||
private:
|
||||
color_t m_color;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -116,3 +116,104 @@ TEST(7)
|
|||
EXPECT_EQ (QColor (16, 32, 48, 128).rgb (), 0xff102030);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(8)
|
||||
{
|
||||
unsigned int h, s, v;
|
||||
int ih, is, iv;
|
||||
lay::Color c = lay::Color (16, 32, 48);
|
||||
c.get_hsv (h, s, v);
|
||||
EXPECT_EQ (h, 210);
|
||||
EXPECT_EQ (s, 170);
|
||||
EXPECT_EQ (v, 48);
|
||||
|
||||
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#102030");
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
QColor qc = QColor (16, 32, 48);
|
||||
qc.getHsv (&ih, &is, &iv);
|
||||
EXPECT_EQ (ih, 210);
|
||||
EXPECT_EQ (is, 170);
|
||||
EXPECT_EQ (iv, 48);
|
||||
#endif
|
||||
|
||||
c = lay::Color (32, 16, 48);
|
||||
c.get_hsv (h, s, v);
|
||||
EXPECT_EQ (h, 270);
|
||||
EXPECT_EQ (s, 170);
|
||||
EXPECT_EQ (v, 48);
|
||||
|
||||
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#201030");
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
qc = QColor (32, 16, 48);
|
||||
qc.getHsv (&ih, &is, &iv);
|
||||
EXPECT_EQ (ih, 270);
|
||||
EXPECT_EQ (is, 170);
|
||||
EXPECT_EQ (iv, 48);
|
||||
#endif
|
||||
|
||||
c = lay::Color (32, 48, 16);
|
||||
c.get_hsv (h, s, v);
|
||||
EXPECT_EQ (h, 90);
|
||||
EXPECT_EQ (s, 170);
|
||||
EXPECT_EQ (v, 48);
|
||||
|
||||
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#203010");
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
qc = QColor (32, 48, 16);
|
||||
qc.getHsv (&ih, &is, &iv);
|
||||
EXPECT_EQ (ih, 90);
|
||||
EXPECT_EQ (is, 170);
|
||||
EXPECT_EQ (iv, 48);
|
||||
#endif
|
||||
|
||||
c = lay::Color (48, 32, 16);
|
||||
c.get_hsv (h, s, v);
|
||||
EXPECT_EQ (h, 30);
|
||||
EXPECT_EQ (s, 170);
|
||||
EXPECT_EQ (v, 48);
|
||||
|
||||
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#302010");
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
qc = QColor (48, 32, 16);
|
||||
qc.getHsv (&ih, &is, &iv);
|
||||
EXPECT_EQ (ih, 30);
|
||||
EXPECT_EQ (is, 170);
|
||||
EXPECT_EQ (iv, 48);
|
||||
#endif
|
||||
|
||||
c = lay::Color (48, 16, 32);
|
||||
c.get_hsv (h, s, v);
|
||||
EXPECT_EQ (h, 330);
|
||||
EXPECT_EQ (s, 170);
|
||||
EXPECT_EQ (v, 48);
|
||||
|
||||
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#301020");
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
qc = QColor (48, 16, 32);
|
||||
qc.getHsv (&ih, &is, &iv);
|
||||
EXPECT_EQ (ih, 330);
|
||||
EXPECT_EQ (is, 170);
|
||||
EXPECT_EQ (iv, 48);
|
||||
#endif
|
||||
|
||||
c = lay::Color (16, 48, 32);
|
||||
c.get_hsv (h, s, v);
|
||||
EXPECT_EQ (h, 150);
|
||||
EXPECT_EQ (s, 170);
|
||||
EXPECT_EQ (v, 48);
|
||||
|
||||
EXPECT_EQ (lay::Color::from_hsv (h, s, v).to_string (), "#103020");
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
qc = QColor (16, 48, 32);
|
||||
qc.getHsv (&ih, &is, &iv);
|
||||
EXPECT_EQ (ih, 150);
|
||||
EXPECT_EQ (is, 170);
|
||||
EXPECT_EQ (iv, 48);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue