mirror of https://github.com/KLayout/klayout.git
Images: asymmetric color nodes.
This commit is contained in:
parent
6c8d96871b
commit
37299a8edf
File diff suppressed because it is too large
Load Diff
|
|
@ -44,7 +44,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, QColor (color)));
|
||||
dm->false_color_nodes.push_back (std::make_pair (value, std::make_pair (QColor (color), QColor (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))));
|
||||
}
|
||||
|
||||
static size_t num_colormap_entries (const img::DataMapping *dm)
|
||||
|
|
@ -55,7 +60,25 @@ static size_t num_colormap_entries (const img::DataMapping *dm)
|
|||
static lay::color_t colormap_color (const img::DataMapping *dm, size_t i)
|
||||
{
|
||||
if (i < dm->false_color_nodes.size ()) {
|
||||
return dm->false_color_nodes [i].second.rgb ();
|
||||
return dm->false_color_nodes [i].second.first.rgb ();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static lay::color_t colormap_lcolor (const img::DataMapping *dm, size_t i)
|
||||
{
|
||||
if (i < dm->false_color_nodes.size ()) {
|
||||
return dm->false_color_nodes [i].second.first.rgb ();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static lay::color_t colormap_rcolor (const img::DataMapping *dm, size_t i)
|
||||
{
|
||||
if (i < dm->false_color_nodes.size ()) {
|
||||
return dm->false_color_nodes [i].second.second.rgb ();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -147,6 +170,22 @@ gsi::Class<img::DataMapping> decl_ImageDataMapping ("lay", "ImageDataMapping",
|
|||
"blue component (0 to 255), the second byte the green component and the third byte the "
|
||||
"red component, i.e. 0xff0000 is red and 0x0000ff is blue. "
|
||||
) +
|
||||
gsi::method_ext ("add_colormap_entry", &gsi::add_colormap2, gsi::arg ("value"), gsi::arg ("lcolor"), gsi::arg ("rcolor"),
|
||||
"@brief Add a colormap entry for this data mapping object.\n"
|
||||
"@param value The value at which the given color should be applied.\n"
|
||||
"@param lcolor The color to apply left of the value (a 32 bit RGB value).\n"
|
||||
"@param rcolor The color to apply right of the value (a 32 bit RGB value).\n"
|
||||
"\n"
|
||||
"This settings establishes a color mapping for a given value in the monochrome channel. "
|
||||
"The colors must be given as a 32 bit integer, where the lowest order byte describes the "
|
||||
"blue component (0 to 255), the second byte the green component and the third byte the "
|
||||
"red component, i.e. 0xff0000 is red and 0x0000ff is blue.\n"
|
||||
"\n"
|
||||
"In contrast to the version with one color, this version allows specifying a color left and right "
|
||||
"of the value - i.e. a discontinuous step.\n"
|
||||
"\n"
|
||||
"This variant has been introduced in version 0.27.\n"
|
||||
) +
|
||||
gsi::method_ext ("num_colormap_entries", &gsi::num_colormap_entries,
|
||||
"@brief Returns the current number of color map entries.\n"
|
||||
"@return The number of entries.\n"
|
||||
|
|
@ -155,11 +194,23 @@ gsi::Class<img::DataMapping> decl_ImageDataMapping ("lay", "ImageDataMapping",
|
|||
"@brief Returns the color for a given color map entry.\n"
|
||||
"@param n The index of the entry (0..\\num_colormap_entries-1)\n"
|
||||
"@return The color (see \\add_colormap_entry for a description).\n"
|
||||
"\n"
|
||||
"NOTE: this version is deprecated and provided for backward compatibility. For discontinuous nodes "
|
||||
"this method delivers the left-sided color."
|
||||
) +
|
||||
gsi::method_ext ("colormap_value", &gsi::colormap_value, gsi::arg ("n"),
|
||||
"@brief Returns the vlue for a given color map entry.\n"
|
||||
gsi::method_ext ("colormap_lcolor", &gsi::colormap_lcolor, gsi::arg ("n"),
|
||||
"@brief Returns the left-side color for a given color map entry.\n"
|
||||
"@param n The index of the entry (0..\\num_colormap_entries-1)\n"
|
||||
"@return The value (see \\add_colormap_entry for a description).\n"
|
||||
"@return The color (see \\add_colormap_entry for a description).\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27."
|
||||
) +
|
||||
gsi::method_ext ("colormap_rcolor", &gsi::colormap_rcolor, gsi::arg ("n"),
|
||||
"@brief Returns the right-side color for a given color map entry.\n"
|
||||
"@param n The index of the entry (0..\\num_colormap_entries-1)\n"
|
||||
"@return The color (see \\add_colormap_entry for a description).\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.27."
|
||||
) +
|
||||
gsi::method_ext ("brightness=", &gsi::set_brightness, gsi::arg ("brightness"),
|
||||
"@brief Set the brightness\n"
|
||||
|
|
|
|||
|
|
@ -50,8 +50,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, QColor (0, 0, 0)));
|
||||
false_color_nodes.push_back (std::make_pair (1.0, QColor (255, 255, 255)));
|
||||
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))));
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -91,7 +91,10 @@ DataMapping::operator== (const DataMapping &d) const
|
|||
if (fabs (false_color_nodes[i].first - d.false_color_nodes[i].first) > epsilon) {
|
||||
return false;
|
||||
}
|
||||
if (false_color_nodes[i].second != d.false_color_nodes[i].second) {
|
||||
if (false_color_nodes[i].second.first != d.false_color_nodes[i].second.first) {
|
||||
return false;
|
||||
}
|
||||
if (false_color_nodes[i].second.second != d.false_color_nodes[i].second.second) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -136,8 +139,11 @@ DataMapping::operator< (const DataMapping &d) const
|
|||
if (fabs (false_color_nodes[i].first - d.false_color_nodes[i].first) > epsilon) {
|
||||
return false_color_nodes[i].first < d.false_color_nodes[i].first;
|
||||
}
|
||||
if (false_color_nodes[i].second != d.false_color_nodes[i].second) {
|
||||
return false_color_nodes[i].second.rgb () < d.false_color_nodes[i].second.rgb ();
|
||||
if (false_color_nodes[i].second.first != d.false_color_nodes[i].second.first) {
|
||||
return false_color_nodes[i].second.first.rgb () < d.false_color_nodes[i].second.first.rgb ();
|
||||
}
|
||||
if (false_color_nodes[i].second.second != d.false_color_nodes[i].second.second) {
|
||||
return false_color_nodes[i].second.second.rgb () < d.false_color_nodes[i].second.second.rgb ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,10 +192,10 @@ 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.getHsv (&h1, &s1, &v1);
|
||||
false_color_nodes [i - 1].second.second.getHsv (&h1, &s1, &v1);
|
||||
|
||||
int h2, s2, v2;
|
||||
false_color_nodes [i].second.getHsv (&h2, &s2, &v2);
|
||||
false_color_nodes [i].second.first.getHsv (&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));
|
||||
|
|
@ -220,11 +226,11 @@ DataMapping::create_data_mapping (bool monochrome, double xmin, double xmax, uns
|
|||
|
||||
double ylast = 0.0;
|
||||
if (channel == 0) {
|
||||
ylast = false_color_nodes.back ().second.red ();
|
||||
ylast = false_color_nodes.back ().second.second.red ();
|
||||
} else if (channel == 1) {
|
||||
ylast = false_color_nodes.back ().second.green ();
|
||||
ylast = false_color_nodes.back ().second.second.green ();
|
||||
} else if (channel == 2) {
|
||||
ylast = false_color_nodes.back ().second.blue ();
|
||||
ylast = false_color_nodes.back ().second.second.blue ();
|
||||
}
|
||||
|
||||
gray_to_color->push_back (false_color_nodes.back ().first, ylast / 255.0);
|
||||
|
|
@ -1266,18 +1272,33 @@ Object::from_string (const char *str, const char *base_dir)
|
|||
|
||||
double x = 0.0;
|
||||
lay::ColorConverter cc;
|
||||
QColor c;
|
||||
QColor cl, cr;
|
||||
std::string s;
|
||||
|
||||
m_data_mapping.false_color_nodes.clear ();
|
||||
|
||||
while (! ex.at_end () && ! ex.test ("]")) {
|
||||
|
||||
ex.read (x);
|
||||
|
||||
ex.test (",");
|
||||
|
||||
s.clear ();
|
||||
ex.read_word_or_quoted (s);
|
||||
cc.from_string (s, c);
|
||||
m_data_mapping.false_color_nodes.push_back (std::make_pair (x, c));
|
||||
cc.from_string (s, cl);
|
||||
|
||||
if (ex.test (",")) {
|
||||
s.clear ();
|
||||
ex.read_word_or_quoted (s);
|
||||
cc.from_string (s, cr);
|
||||
} else {
|
||||
cr = cl;
|
||||
}
|
||||
|
||||
m_data_mapping.false_color_nodes.push_back (std::make_pair (x, std::make_pair (cl, cr)));
|
||||
|
||||
ex.test (";");
|
||||
|
||||
}
|
||||
|
||||
} else if (ex.test ("width=")) {
|
||||
|
|
@ -1604,7 +1625,12 @@ 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 << ",";
|
||||
os << tl::to_word_or_quoted_string (cc.to_string (data_mapping ().false_color_nodes[i].second));
|
||||
const std::pair<QColor, QColor> &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 << ",";
|
||||
os << tl::to_word_or_quoted_string (cc.to_string (clr.second));
|
||||
}
|
||||
os << ";";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ public:
|
|||
* Each node is a pair or x-value (normalized to a range of 0..1) and a corresponding color.
|
||||
* The list should have an element with x value of 0.0 and one with an x value of 1.0.
|
||||
*/
|
||||
std::vector< std::pair<double, QColor> > false_color_nodes;
|
||||
std::vector< std::pair<double, std::pair<QColor, QColor> > > false_color_nodes;
|
||||
|
||||
/**
|
||||
* @brief The brightness value
|
||||
|
|
|
|||
|
|
@ -100,11 +100,12 @@ PropertiesPage::init ()
|
|||
connect (action, SIGNAL (triggered ()), this, SLOT (reverse_color_order ()));
|
||||
false_color_control->addAction (action);
|
||||
|
||||
color_pb->set_color (QColor ());
|
||||
colors->set_color (std::make_pair (QColor (), QColor ()));
|
||||
colors->setEnabled (false);
|
||||
|
||||
connect (browse_pb, SIGNAL (clicked ()), this, SLOT (browse ()));
|
||||
connect (color_pb, SIGNAL (color_changed (QColor)), false_color_control, SLOT (set_current_color (QColor)));
|
||||
connect (false_color_control, SIGNAL (selection_changed (QColor)), color_pb, SLOT (set_color (QColor)));
|
||||
connect (colors, SIGNAL (color_changed (std::pair<QColor, QColor>)), false_color_control, SLOT (set_current_color (std::pair<QColor, QColor>)));
|
||||
connect (false_color_control, SIGNAL (selection_changed (std::pair<QColor, QColor>)), colors, SLOT (set_color (std::pair<QColor, QColor>)));
|
||||
|
||||
connect (brightness_slider, SIGNAL (valueChanged (int)), this, SLOT (brightness_slider_changed (int)));
|
||||
connect (brightness_sb, SIGNAL (valueChanged (int)), this, SLOT (brightness_spinbox_changed (int)));
|
||||
|
|
@ -206,7 +207,8 @@ BEGIN_PROTECTED
|
|||
value_le->setText (QString ());
|
||||
value_le->setEnabled (false);
|
||||
|
||||
color_pb->setEnabled (false_color_control->has_selection ());
|
||||
colors->setEnabled (false_color_control->has_selection ());
|
||||
colors->set_single_mode (false);
|
||||
|
||||
double xmin, xmax;
|
||||
tl::from_string (tl::to_string (from_le->text ()), xmin);
|
||||
|
|
@ -223,6 +225,10 @@ BEGIN_PROTECTED
|
|||
value_le->setText (tl::to_qstring (tl::sprintf ("%.4g", xx)));
|
||||
value_le->setEnabled (true);
|
||||
|
||||
} else if (false_color_control->has_selection ()) {
|
||||
|
||||
colors->set_single_mode (true);
|
||||
|
||||
}
|
||||
|
||||
recompute_histogram ();
|
||||
|
|
@ -240,7 +246,8 @@ PropertiesPage::color_mapping_changed ()
|
|||
value_le->setText (QString ());
|
||||
value_le->setEnabled (false);
|
||||
|
||||
color_pb->setEnabled (false_color_control->has_selection ());
|
||||
colors->setEnabled (false_color_control->has_selection ());
|
||||
colors->set_single_mode (false);
|
||||
|
||||
try {
|
||||
|
||||
|
|
@ -259,6 +266,10 @@ PropertiesPage::color_mapping_changed ()
|
|||
value_le->setText (tl::to_qstring (tl::sprintf ("%.4g", xx)));
|
||||
value_le->setEnabled (true);
|
||||
|
||||
} else if (false_color_control->has_selection ()) {
|
||||
|
||||
colors->set_single_mode (true);
|
||||
|
||||
}
|
||||
|
||||
} catch (...) { }
|
||||
|
|
@ -668,27 +679,27 @@ PropertiesPage::blue_spinbox_changed (double value)
|
|||
void
|
||||
PropertiesPage::black_to_white ()
|
||||
{
|
||||
std::vector <std::pair <double, QColor> > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, QColor (0, 0, 0)));
|
||||
nodes.push_back (std::make_pair (1.0, QColor (255, 255, 255)));
|
||||
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))));
|
||||
false_color_control->set_nodes (nodes);
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::white_to_black ()
|
||||
{
|
||||
std::vector <std::pair <double, QColor> > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, QColor (255, 255, 255)));
|
||||
nodes.push_back (std::make_pair (1.0, QColor (0, 0, 0)));
|
||||
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))));
|
||||
false_color_control->set_nodes (nodes);
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::red_to_blue ()
|
||||
{
|
||||
std::vector <std::pair <double, QColor> > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, QColor (255, 0, 0)));
|
||||
nodes.push_back (std::make_pair (1.0, QColor (0, 0, 255)));
|
||||
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))));
|
||||
false_color_control->set_nodes (nodes);
|
||||
|
||||
}
|
||||
|
|
@ -696,18 +707,19 @@ PropertiesPage::red_to_blue ()
|
|||
void
|
||||
PropertiesPage::blue_to_red ()
|
||||
{
|
||||
std::vector <std::pair <double, QColor> > nodes;
|
||||
nodes.push_back (std::make_pair (0.0, QColor (0, 0, 255)));
|
||||
nodes.push_back (std::make_pair (1.0, QColor (255, 0, 0)));
|
||||
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))));
|
||||
false_color_control->set_nodes (nodes);
|
||||
}
|
||||
|
||||
void
|
||||
PropertiesPage::reverse_color_order ()
|
||||
{
|
||||
std::vector <std::pair <double, QColor> > nodes (false_color_control->nodes ());
|
||||
std::vector <std::pair <double, std::pair<QColor, QColor> > > nodes (false_color_control->nodes ());
|
||||
for (size_t i = 0; i < nodes.size () / 2; ++i) {
|
||||
std::swap (nodes [i].second, nodes [nodes.size () - 1 - i].second);
|
||||
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);
|
||||
}
|
||||
false_color_control->set_nodes (nodes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
|
|
@ -45,36 +46,36 @@ const double epsilon = 1e-6;
|
|||
|
||||
struct compare_first_of_node
|
||||
{
|
||||
bool operator() (const std::pair <double, QColor> &a, const std::pair <double, QColor> &b) const
|
||||
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, QColor> > &nodes, double x)
|
||||
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 nodes[0].second;
|
||||
return x < nodes[0].first ? nodes[0].second.first : nodes[0].second.second;
|
||||
} else {
|
||||
|
||||
std::vector<std::pair<double, QColor> >::const_iterator p = std::lower_bound (nodes.begin (), nodes.end (), std::make_pair (x, QColor ()), compare_first_of_node ());
|
||||
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;
|
||||
return nodes.back ().second.second;
|
||||
} else if (p == nodes.begin ()) {
|
||||
return nodes.front ().second;
|
||||
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.getHsv (&h1, &s1, &v1);
|
||||
p[-1].second.second.getHsv (&h1, &s1, &v1);
|
||||
|
||||
int h2 = 0, s2 = 0, v2 = 0;
|
||||
p->second.getHsv (&h2, &s2, &v2);
|
||||
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));
|
||||
|
|
@ -89,11 +90,91 @@ interpolated_color (const std::vector<std::pair <double, QColor> > &nodes, doubl
|
|||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
TwoColorWidget::TwoColorWidget (QWidget *parent)
|
||||
: QFrame (parent)
|
||||
{
|
||||
setLayout (new QHBoxLayout (this));
|
||||
|
||||
mp_left = new lay::SimpleColorButton (this);
|
||||
layout ()->addWidget (mp_left);
|
||||
mp_right = new lay::SimpleColorButton (this);
|
||||
layout ()->addWidget (mp_right);
|
||||
mp_lock = new QToolButton (this);
|
||||
layout ()->addWidget (mp_lock);
|
||||
mp_lock->setCheckable (true);
|
||||
mp_lock->setAutoRaise (true);
|
||||
mp_lock->setIconSize (QSize (16, 16));
|
||||
|
||||
QIcon icon;
|
||||
icon.addFile (":/locked_16.png", QSize (), QIcon::Normal, QIcon::On);
|
||||
icon.addFile (":/unlocked_16.png", QSize (), QIcon::Normal, QIcon::Off);
|
||||
mp_lock->setIcon (icon);
|
||||
|
||||
connect (mp_left, SIGNAL (color_changed (QColor)), this, SLOT (lcolor_changed (QColor)));
|
||||
connect (mp_right, SIGNAL (color_changed (QColor)), this, SLOT (rcolor_changed (QColor)));
|
||||
connect (mp_lock, SIGNAL (clicked (bool)), this, SLOT (lock_changed (bool)));
|
||||
}
|
||||
|
||||
void
|
||||
TwoColorWidget::set_color (std::pair<QColor, QColor> c)
|
||||
{
|
||||
mp_left->set_color (c.first);
|
||||
mp_right->set_color (c.second);
|
||||
mp_lock->setChecked (c.first == c.second);
|
||||
mp_right->setVisible (! mp_lock->isChecked ());
|
||||
}
|
||||
|
||||
void
|
||||
TwoColorWidget::set_single_mode (bool f)
|
||||
{
|
||||
mp_lock->setEnabled (! f);
|
||||
}
|
||||
|
||||
void
|
||||
TwoColorWidget::lcolor_changed (QColor)
|
||||
{
|
||||
if (mp_lock->isChecked ()) {
|
||||
mp_right->set_color (mp_left->get_color ());
|
||||
}
|
||||
emit color_changed (std::make_pair (mp_left->get_color (), mp_right->get_color ()));
|
||||
}
|
||||
|
||||
void
|
||||
TwoColorWidget::rcolor_changed (QColor)
|
||||
{
|
||||
if (mp_lock->isChecked ()) {
|
||||
mp_left->set_color (mp_right->get_color ());
|
||||
}
|
||||
emit color_changed (std::make_pair (mp_left->get_color (), mp_right->get_color ()));
|
||||
}
|
||||
|
||||
void
|
||||
TwoColorWidget::lock_changed (bool checked)
|
||||
{
|
||||
if (checked) {
|
||||
|
||||
QColor cl = mp_left->get_color ();
|
||||
QColor cr = mp_right->get_color ();
|
||||
|
||||
QColor ca ((cl.red () + cr.red ()) / 2, (cl.green () + cr.green ()) / 2, (cl.blue () + cr.blue ()) / 2);
|
||||
set_color (std::make_pair (ca, ca));
|
||||
|
||||
emit color_changed (std::make_pair (mp_left->get_color (), mp_right->get_color ()));
|
||||
|
||||
}
|
||||
|
||||
mp_right->setVisible (! mp_lock->isChecked ());
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
ColorBar::ColorBar (QWidget *parent)
|
||||
: QWidget (parent), m_dragging (false), m_selected (-1)
|
||||
{
|
||||
m_nodes.push_back (std::make_pair (0.0, QColor (0, 0, 0)));
|
||||
m_nodes.push_back (std::make_pair (1.0, QColor (255, 255, 255)));
|
||||
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))));
|
||||
}
|
||||
|
||||
ColorBar::~ColorBar ()
|
||||
|
|
@ -122,7 +203,7 @@ ColorBar::mouseMoveEvent (QMouseEvent *event)
|
|||
}
|
||||
|
||||
void
|
||||
ColorBar::set_current_color (QColor c)
|
||||
ColorBar::set_current_color (std::pair<QColor, QColor> c)
|
||||
{
|
||||
if (has_selection ()) {
|
||||
m_nodes [m_selected].second = c;
|
||||
|
|
@ -174,27 +255,27 @@ ColorBar::keyPressEvent (QKeyEvent *event)
|
|||
m_nodes.erase (m_nodes.begin () + m_selected);
|
||||
m_selected = -1;
|
||||
emit selection_changed ();
|
||||
emit selection_changed (QColor ());
|
||||
emit selection_changed (std::make_pair (QColor (), QColor ()));
|
||||
update ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ColorBar::set_nodes (const std::vector <std::pair <double, QColor> > &nodes)
|
||||
ColorBar::set_nodes (const std::vector<std::pair<double, std::pair<QColor, QColor> > > &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, QColor (0, 0, 0)));
|
||||
m_nodes.insert (m_nodes.begin (), std::make_pair (0.0, std::make_pair (QColor (0, 0, 0), QColor (0, 0, 0))));
|
||||
} else {
|
||||
m_nodes[0].first = 0.0;
|
||||
}
|
||||
|
||||
std::vector <std::pair <double, QColor> >::iterator w = m_nodes.begin ();
|
||||
std::vector <std::pair <double, QColor> >::const_iterator nn = m_nodes.begin ();
|
||||
for (std::vector <std::pair <double, QColor> >::const_iterator n = m_nodes.begin () + 1; n != m_nodes.end (); ++n) {
|
||||
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) {
|
||||
if (fabs (nn->first - n->first) > min_value_interval) {
|
||||
*w++ = *nn;
|
||||
nn = n;
|
||||
|
|
@ -207,7 +288,7 @@ ColorBar::set_nodes (const std::vector <std::pair <double, QColor> > &nodes)
|
|||
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, QColor (255, 255, 255)));
|
||||
m_nodes.push_back (std::make_pair (1.0, std::make_pair (QColor (255, 255, 255), QColor (255, 255, 255))));
|
||||
}
|
||||
|
||||
m_selected = -1;
|
||||
|
|
@ -232,8 +313,8 @@ ColorBar::mousePressEvent (QMouseEvent *event)
|
|||
double xx = double (event->x () - xl) / double (xr - xl);
|
||||
|
||||
double dmin = 100.0;
|
||||
std::vector<std::pair<double, QColor> >::const_iterator pmin = m_nodes.end ();
|
||||
for (std::vector<std::pair<double, QColor> >::const_iterator p = m_nodes.begin (); p != m_nodes.end (); ++p) {
|
||||
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) {
|
||||
double d = fabs (p->first - xx);
|
||||
if (d < 0.05 && d < dmin) {
|
||||
dmin = d;
|
||||
|
|
@ -242,7 +323,7 @@ ColorBar::mousePressEvent (QMouseEvent *event)
|
|||
}
|
||||
|
||||
if (pmin != m_nodes.end ()) {
|
||||
m_selected = int (std::distance (std::vector<std::pair<double, QColor> >::const_iterator (m_nodes.begin ()), pmin));
|
||||
m_selected = int (std::distance (std::vector<std::pair<double, std::pair<QColor, QColor> > >::const_iterator (m_nodes.begin ()), pmin));
|
||||
emit selection_changed ();
|
||||
emit selection_changed (m_nodes [m_selected].second);
|
||||
m_dragging = true;
|
||||
|
|
@ -250,7 +331,7 @@ ColorBar::mousePressEvent (QMouseEvent *event)
|
|||
} else {
|
||||
m_selected = -1;
|
||||
emit selection_changed ();
|
||||
emit selection_changed (QColor ());
|
||||
emit selection_changed (std::make_pair (QColor (), QColor ()));
|
||||
update ();
|
||||
}
|
||||
|
||||
|
|
@ -278,10 +359,11 @@ ColorBar::mouseDoubleClickEvent (QMouseEvent *event)
|
|||
|
||||
double xx = double (event->x () - xl) / double (xr - xl);
|
||||
|
||||
std::vector<std::pair<double, QColor> >::iterator p = std::lower_bound (m_nodes.begin (), m_nodes.end (), std::make_pair (xx, QColor ()), compare_first_of_node ());
|
||||
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 ());
|
||||
if (p != m_nodes.begin () && p != m_nodes.end ()) {
|
||||
m_selected = int (std::distance (m_nodes.begin (), p));
|
||||
m_nodes.insert (p, std::make_pair (xx, interpolated_color (m_nodes, xx)));
|
||||
QColor 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);
|
||||
emit color_mapping_changed ();
|
||||
|
|
|
|||
|
|
@ -20,13 +20,15 @@
|
|||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef HDR_imgWidgets
|
||||
#define HDR_imgWidgets
|
||||
|
||||
#include "layWidgets.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QFrame>
|
||||
#include <QToolButton>
|
||||
#include <vector>
|
||||
|
||||
class QMouseEvent;
|
||||
|
|
@ -41,7 +43,37 @@ namespace img
|
|||
*
|
||||
* TODO: move this somewhere else.
|
||||
*/
|
||||
QColor interpolated_color (const std::vector<std::pair <double, QColor> > &nodes, double x);
|
||||
QColor interpolated_color (const std::vector<std::pair <double, std::pair<QColor, QColor> > > &nodes, double x);
|
||||
|
||||
/**
|
||||
* @brief A two-color widget
|
||||
*
|
||||
* This widget has two color buttons and a "lock" checkbox which makes both colors identical
|
||||
*/
|
||||
class TwoColorWidget
|
||||
: public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TwoColorWidget (QWidget *parent);
|
||||
|
||||
signals:
|
||||
void color_changed (std::pair<QColor, QColor> c);
|
||||
|
||||
public slots:
|
||||
void set_color (std::pair<QColor, QColor> c);
|
||||
void set_single_mode (bool f);
|
||||
|
||||
private slots:
|
||||
void lcolor_changed (QColor c);
|
||||
void rcolor_changed (QColor c);
|
||||
void lock_changed (bool checked);
|
||||
|
||||
private:
|
||||
lay::SimpleColorButton *mp_left, *mp_right;
|
||||
QToolButton *mp_lock;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A color bar widget
|
||||
|
|
@ -82,9 +114,9 @@ public:
|
|||
return m_selected >= 0;
|
||||
}
|
||||
|
||||
void set_nodes (const std::vector <std::pair <double, QColor> > &nodes);
|
||||
void set_nodes (const std::vector <std::pair <double, std::pair<QColor, QColor> > > &nodes);
|
||||
|
||||
const std::vector <std::pair <double, QColor> > &nodes () const
|
||||
const std::vector <std::pair <double, std::pair<QColor, QColor> > > &nodes () const
|
||||
{
|
||||
return m_nodes;
|
||||
}
|
||||
|
|
@ -92,18 +124,18 @@ public:
|
|||
void set_histogram (const std::vector <size_t> &histogram);
|
||||
|
||||
public slots:
|
||||
void set_current_color (QColor c);
|
||||
void set_current_color (std::pair<QColor, QColor> c);
|
||||
void set_current_position (double x);
|
||||
|
||||
signals:
|
||||
void color_mapping_changed ();
|
||||
void selection_changed ();
|
||||
void selection_changed (QColor c);
|
||||
void selection_changed (std::pair<QColor, QColor> c);
|
||||
|
||||
private:
|
||||
bool m_dragging;
|
||||
int m_selected;
|
||||
std::vector <std::pair <double, QColor> > m_nodes;
|
||||
std::vector <std::pair <double, std::pair<QColor, QColor> > > m_nodes;
|
||||
std::vector <size_t> m_histogram;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@
|
|||
#include "imgObject.h"
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
static img::Object from_s (const std::string &s)
|
||||
{
|
||||
img::Object img;
|
||||
img.from_string (s.c_str ());
|
||||
return img;
|
||||
}
|
||||
|
||||
TEST(1)
|
||||
{
|
||||
img::Object image (12, 8, db::DCplxTrans (), false);
|
||||
|
|
@ -95,23 +102,32 @@ TEST(1)
|
|||
dm.green_gain = 0.75;
|
||||
dm.blue_gain = 2.5;
|
||||
QColor c (128, 255, 64);
|
||||
dm.false_color_nodes.insert (dm.false_color_nodes.begin () + 1, std::make_pair (0.5, c));
|
||||
QColor 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);
|
||||
EXPECT_EQ (from_s (image.to_string ()).equals (&image), true);
|
||||
copy1 = image;
|
||||
EXPECT_EQ (copy1.equals (&image), true);
|
||||
|
||||
dm.false_color_nodes.insert (dm.false_color_nodes.begin () + 1, std::make_pair (0.75, std::make_pair (c, c2)));
|
||||
image.set_data_mapping (dm);
|
||||
EXPECT_EQ (copy1.equals (&image), false);
|
||||
EXPECT_EQ (from_s (image.to_string ()).equals (&image), true);
|
||||
copy1 = image;
|
||||
EXPECT_EQ (copy1.equals (&image), true);
|
||||
|
||||
EXPECT_EQ (copy1.data_mapping ().brightness, 0.5);
|
||||
EXPECT_EQ (copy1.data_mapping ().red_gain, 1.25);
|
||||
EXPECT_EQ (copy1.data_mapping ().false_color_nodes.size (), size_t (3));
|
||||
EXPECT_EQ (copy1.data_mapping ().false_color_nodes.size (), size_t (4));
|
||||
|
||||
img::Object copy2;
|
||||
copy2.from_string (image.to_string ().c_str ());
|
||||
EXPECT_EQ (copy2.equals (&image), true);
|
||||
|
||||
EXPECT_EQ (copy2.data_mapping ().brightness, 0.5);
|
||||
EXPECT_EQ (tl::to_string (copy2.data_mapping ().red_gain), "1.25");
|
||||
EXPECT_EQ (copy2.data_mapping ().false_color_nodes.size (), size_t (3));
|
||||
EXPECT_EQ (copy2.data_mapping ().false_color_nodes.size (), size_t (4));
|
||||
EXPECT_EQ (copy2.equals (&image), true);
|
||||
|
||||
EXPECT_EQ (image.to_string (), copy2.to_string ());
|
||||
|
|
@ -203,7 +219,7 @@ TEST(2)
|
|||
dm.green_gain = 0.75;
|
||||
dm.blue_gain = 2.5;
|
||||
QColor c (128, 255, 64);
|
||||
dm.false_color_nodes.insert (dm.false_color_nodes.begin () + 1, std::make_pair (0.5, c));
|
||||
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);
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 318 B |
Binary file not shown.
|
After Width: | Height: | Size: 368 B |
|
|
@ -127,6 +127,8 @@
|
|||
<file alias="folder_12.png">images/folder_12.png</file>
|
||||
<file alias="file_12.png">images/file_12.png</file>
|
||||
<file alias="empty_12.png">images/empty_12.png</file>
|
||||
<file alias="unlocked_16.png">images/unlocked_16.png</file>
|
||||
<file alias="locked_16.png">images/locked_16.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/syntax">
|
||||
<file alias="ruby.xml">syntax/ruby.xml</file>
|
||||
|
|
|
|||
Loading…
Reference in New Issue