Engauge Digitizer  2
ColorFilterSettings.cpp
1 /******************************************************************************************************
2  * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3  * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5  ******************************************************************************************************/
6 
7 #include "CmdMediator.h"
8 #include "ColorConstants.h"
9 #include "ColorFilterSettings.h"
10 #include "ColorFilterSettingsStrategyAbstractBase.h"
11 #include "ColorFilterSettingsStrategyForeground.h"
12 #include "ColorFilterSettingsStrategyHue.h"
13 #include "ColorFilterSettingsStrategyIntensity.h"
14 #include "ColorFilterSettingsStrategySaturation.h"
15 #include "ColorFilterSettingsStrategyValue.h"
16 #include "DocumentSerialize.h"
17 #include "EngaugeAssert.h"
18 #include "GridCoordDisable.h"
19 #include "Logger.h"
20 #include <QTextStream>
21 #include <QXmlStreamWriter>
22 #include "Xml.h"
23 
25  m_colorFilterMode (COLOR_FILTER_MODE_INTENSITY),
26  m_intensityLow (INTENSITY_LOW_DEFAULT),
27  m_intensityHigh (INTENSITY_HIGH_DEFAULT),
28  m_foregroundLow (FOREGROUND_LOW_DEFAULT),
29  m_foregroundHigh (FOREGROUND_HIGH_DEFAULT),
30  m_hueLow (HUE_LOW_DEFAULT),
31  m_hueHigh (HUE_HIGH_DEFAULT),
32  m_saturationLow (SATURATION_LOW_DEFAULT),
33  m_saturationHigh (SATURATION_HIGH_DEFAULT),
34  m_valueLow (VALUE_LOW_DEFAULT),
35  m_valueHigh (VALUE_HIGH_DEFAULT)
36 {
37  createStrategies ();
38 }
39 
40 ColorFilterSettings::ColorFilterSettings(ColorFilterMode colorFilterMode,
41  int intensityLow,
42  int intensityHigh,
43  int foregroundLow,
44  int foregroundHigh,
45  int hueLow,
46  int hueHigh,
47  int saturationLow,
48  int saturationHigh,
49  int valueLow,
50  int valueHigh) :
51  m_colorFilterMode (colorFilterMode),
52  m_intensityLow (intensityLow),
53  m_intensityHigh (intensityHigh),
54  m_foregroundLow (foregroundLow),
55  m_foregroundHigh (foregroundHigh),
56  m_hueLow (hueLow),
57  m_hueHigh (hueHigh),
58  m_saturationLow (saturationLow),
59  m_saturationHigh (saturationHigh),
60  m_valueLow (valueLow),
61  m_valueHigh (valueHigh)
62 {
63  createStrategies ();
64 }
65 
67  m_colorFilterMode (other.colorFilterMode()),
68  m_intensityLow (other.intensityLow()),
69  m_intensityHigh (other.intensityHigh()),
70  m_foregroundLow (other.foregroundLow()),
71  m_foregroundHigh (other.foregroundHigh()),
72  m_hueLow (other.hueLow()),
73  m_hueHigh (other.hueHigh()),
74  m_saturationLow (other.saturationLow()),
75  m_saturationHigh (other.saturationHigh()),
76  m_valueLow (other.valueLow()),
77  m_valueHigh (other.valueHigh())
78 {
79  createStrategies ();
80 }
81 
83 {
84  loadXml(reader);
85  createStrategies ();
86 }
87 
89 {
90  m_colorFilterMode = other.colorFilterMode();
91  m_intensityLow = other.intensityLow();
92  m_intensityHigh = other.intensityHigh();
93  m_foregroundLow = other.foregroundLow();
94  m_foregroundHigh = other.foregroundHigh();
95  m_hueLow = other.hueLow();
96  m_hueHigh = other.hueHigh();
97  m_saturationLow = other.saturationLow();
98  m_saturationHigh = other.saturationHigh();
99  m_valueLow = other.valueLow();
100  m_valueHigh = other.valueHigh();
101 
102  createStrategies ();
103 
104  return *this;
105 }
106 
108 {
109  qDeleteAll (m_strategies);
110 }
111 
113 {
114  return m_colorFilterMode;
115 }
116 
117 void ColorFilterSettings::createStrategies ()
118 {
119  qDeleteAll (m_strategies); // Prevent memory leak from one constructor calling another
120 
121  m_strategies [COLOR_FILTER_MODE_FOREGROUND] = new ColorFilterSettingsStrategyForeground ();
122  m_strategies [COLOR_FILTER_MODE_HUE ] = new ColorFilterSettingsStrategyHue ();
123  m_strategies [COLOR_FILTER_MODE_INTENSITY ] = new ColorFilterSettingsStrategyIntensity ();
124  m_strategies [COLOR_FILTER_MODE_SATURATION] = new ColorFilterSettingsStrategySaturation ();
125  m_strategies [COLOR_FILTER_MODE_VALUE ] = new ColorFilterSettingsStrategyValue ();
126 }
127 
129 {
130  return ColorFilterSettings ();
131 }
132 
134 {
135  return m_foregroundHigh;
136 }
137 
139 {
140  return m_foregroundLow;
141 }
142 
144 {
145  if (m_strategies.contains (m_colorFilterMode)) {
146 
147  // Ignore false positive cmake compiler warning about -Wreturn-stack-address in next line (bug #26396)
148  const ColorFilterSettingsStrategyAbstractBase *strategy = m_strategies.value (m_colorFilterMode);
149  return strategy->high (*this);
150  } else {
151  ENGAUGE_ASSERT (false);
152  return m_strategies [COLOR_FILTER_MODE_INTENSITY]->high (*this);
153  }
154 }
155 
157 {
158  return m_hueHigh;
159 }
160 
162 {
163  return m_hueLow;
164 }
165 
167 {
168  return m_intensityHigh;
169 }
170 
172 {
173  return m_intensityLow;
174 }
175 
176 void ColorFilterSettings::loadXml(QXmlStreamReader &reader)
177 {
178  LOG4CPP_INFO_S ((*mainCat)) << "ColorFilterSettings::loadXml";
179 
180  bool success = true;
181 
182  QXmlStreamAttributes attributes = reader.attributes();
183 
184  if (attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_MODE) &&
185  attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_INTENSITY_LOW) &&
186  attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_INTENSITY_HIGH) &&
187  attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_FOREGROUND_LOW) &&
188  attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_FOREGROUND_HIGH) &&
189  attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_HUE_LOW) &&
190  attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_HUE_HIGH) &&
191  attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_SATURATION_LOW) &&
192  attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_SATURATION_HIGH) &&
193  attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_VALUE_LOW) &&
194  attributes.hasAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_VALUE_HIGH)) {
195 
196  setColorFilterMode (static_cast<ColorFilterMode> (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_MODE).toInt()));
197  setIntensityLow (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_INTENSITY_LOW).toInt());
198  setIntensityHigh (static_cast<GridCoordDisable> (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_INTENSITY_HIGH).toInt()));
199  setForegroundLow (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_FOREGROUND_LOW).toInt());
200  setForegroundHigh (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_FOREGROUND_HIGH).toInt());
201  setHueLow (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_HUE_LOW).toInt());
202  setHueHigh (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_HUE_HIGH).toInt());
203  setSaturationLow (static_cast<GridCoordDisable> (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_SATURATION_LOW).toInt()));
204  setSaturationHigh (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_SATURATION_HIGH).toInt());
205  setValueLow (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_VALUE_LOW).toInt());
206  setValueHigh (attributes.value(DOCUMENT_SERIALIZE_COLOR_FILTER_VALUE_HIGH).toInt());
207 
208  // Read until end of this subtree
209  while ((reader.tokenType() != QXmlStreamReader::EndElement) ||
210  (reader.name() != DOCUMENT_SERIALIZE_COLOR_FILTER)){
211  loadNextFromReader(reader);
212 
213  if (reader.atEnd()) {
214  success = false;
215  break;
216  }
217  }
218  }
219 
220  if (!success) {
221  reader.raiseError (QObject::tr ("Cannot read curve filter data"));
222  }
223 }
224 
226 {
227  if (m_strategies.contains (m_colorFilterMode)) {
228  const ColorFilterSettingsStrategyAbstractBase *strategy = m_strategies.value (m_colorFilterMode);
229  return strategy->low (*this);
230  } else {
231  ENGAUGE_ASSERT (false);
232  return m_strategies [COLOR_FILTER_MODE_INTENSITY]->low (*this);
233  }
234 }
235 
236 void ColorFilterSettings::printStream (QString indentation,
237  QTextStream &str) const
238 {
239  str << indentation << "ColorFilterSettings\n";
240 
241  indentation += INDENTATION_DELTA;
242 
243  if (m_strategies.contains (m_colorFilterMode)) {
244  const ColorFilterSettingsStrategyAbstractBase *strategy = m_strategies.value (m_colorFilterMode);
245  return strategy->printStream (*this,
246  indentation,
247  str);
248  }
249 }
250 
252 {
253  return m_saturationHigh;
254 }
255 
257 {
258  return m_saturationLow;
259 }
260 
261 void ColorFilterSettings::saveXml(QXmlStreamWriter &writer,
262  const QString &curveName) const
263 {
264  LOG4CPP_INFO_S ((*mainCat)) << "ColorFilterSettings::saveXml";
265 
266  writer.writeStartElement(DOCUMENT_SERIALIZE_COLOR_FILTER);
267  writer.writeAttribute(DOCUMENT_SERIALIZE_CURVE_NAME, curveName);
268  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_MODE, QString::number (m_colorFilterMode));
269  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_MODE_STRING, colorFilterModeToString (m_colorFilterMode));
270  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_INTENSITY_LOW, QString::number (m_intensityLow));
271  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_INTENSITY_HIGH, QString::number (m_intensityHigh));
272  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_FOREGROUND_LOW, QString::number (m_foregroundLow));
273  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_FOREGROUND_HIGH, QString::number (m_foregroundHigh));
274  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_HUE_LOW, QString::number (m_hueLow));
275  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_HUE_HIGH, QString::number (m_hueHigh));
276  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_SATURATION_LOW, QString::number (m_saturationLow));
277  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_SATURATION_HIGH, QString::number (m_saturationHigh));
278  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_VALUE_LOW, QString::number (m_valueLow));
279  writer.writeAttribute(DOCUMENT_SERIALIZE_COLOR_FILTER_VALUE_HIGH, QString::number (m_valueHigh));
280  writer.writeEndElement();
281 }
282 
283 void ColorFilterSettings::setColorFilterMode(ColorFilterMode colorFilterMode)
284 {
285  m_colorFilterMode = colorFilterMode;
286 }
287 
288 void ColorFilterSettings::setForegroundHigh (int foregroundHigh)
289 {
290  ENGAUGE_ASSERT (FOREGROUND_MIN <= foregroundHigh && foregroundHigh <= FOREGROUND_MAX);
291  m_foregroundHigh = foregroundHigh;
292 }
293 
295 {
296  ENGAUGE_ASSERT (FOREGROUND_MIN <= foregroundLow && foregroundLow <= FOREGROUND_MAX);
297  m_foregroundLow = foregroundLow;
298 }
299 
300 void ColorFilterSettings::setHigh (double s0To1)
301 {
302  if (m_strategies.contains (m_colorFilterMode)) {
303  ColorFilterSettingsStrategyAbstractBase *strategy = m_strategies [m_colorFilterMode];
304  return strategy->setHigh (*this,
305  s0To1);
306  } else {
307  ENGAUGE_ASSERT (false);
308  }
309 }
310 
312 {
313  ENGAUGE_ASSERT (HUE_MIN <= hueHigh && hueHigh <= HUE_MAX);
314  m_hueHigh = hueHigh;
315 }
316 
318 {
319  ENGAUGE_ASSERT (HUE_MIN <= hueLow && hueLow <= HUE_MAX);
320  m_hueLow = hueLow;
321 }
322 
324 {
325  ENGAUGE_ASSERT (INTENSITY_MIN <= intensityHigh && intensityHigh <= INTENSITY_MAX);
326  m_intensityHigh = intensityHigh;
327 }
328 
330 {
331  ENGAUGE_ASSERT (INTENSITY_MIN <= intensityLow && intensityLow <= INTENSITY_MAX);
332  m_intensityLow = intensityLow;
333 }
334 
335 void ColorFilterSettings::setLow (double s0To1)
336 {
337  if (m_strategies.contains (m_colorFilterMode)) {
338  ColorFilterSettingsStrategyAbstractBase *strategy = m_strategies [m_colorFilterMode];
339  return strategy->setLow (*this,
340  s0To1);
341  } else {
342  ENGAUGE_ASSERT (false);
343  }
344 }
345 
346 void ColorFilterSettings::setSaturationHigh (int saturationHigh)
347 {
348  ENGAUGE_ASSERT (SATURATION_MIN <= saturationHigh && saturationHigh <= SATURATION_MAX);
349  m_saturationHigh = saturationHigh;
350 }
351 
353 {
354  ENGAUGE_ASSERT (SATURATION_MIN <= saturationLow && saturationLow <= SATURATION_MAX);
355  m_saturationLow = saturationLow;
356 }
357 
359 {
360  ENGAUGE_ASSERT (VALUE_MIN <= valueHigh && valueHigh <= VALUE_MAX);
361  m_valueHigh = valueHigh;
362 }
363 
365 {
366  ENGAUGE_ASSERT (VALUE_MIN <= valueLow && valueLow <= VALUE_MAX);
367  m_valueLow = valueLow;
368 }
369 
371 {
372  return m_valueHigh;
373 }
374 
376 {
377  return m_valueLow;
378 }
void setSaturationLow(int saturationLow)
Set method for saturation low.
void setLow(double s0To1)
Set the low value for the current filter mode.
int valueHigh() const
Get method for value high.
void setHueLow(int hueLow)
Set method for hue lower bound.
Leaf class for hue strategy for ColorFilterSettings.
Color filter parameters for one curve. For a class, this is handled the same as LineStyle and PointSt...
int hueHigh() const
Get method for hue higher bound.
Leaf class for saturation strategy for ColorFilterSettings.
void setColorFilterMode(ColorFilterMode colorFilterMode)
Set method for filter mode.
int foregroundLow() const
Get method for foreground lower bound.
Base class for strategy pattern whose subclasses process the different color filter settings modes (o...
virtual void printStream(const ColorFilterSettings &colorFilterSettings, QString indentation, QTextStream &str) const =0
Print the low and high values.
double high() const
High value of foreground, hue, intensity, saturation or value according to current filter mode,...
ColorFilterSettings & operator=(const ColorFilterSettings &other)
Assignment operator.
void setForegroundLow(int foregroundLow)
Set method for foreground lower bound.
double low() const
Low value of foreground, hue, intensity, saturation or value according to current filter mode,...
void setHigh(double s0To1)
Set the high value for the current filter mode.
virtual void setHigh(ColorFilterSettings &colorFilterSettings, double s0To1)=0
Set the high value given the normalized value.
virtual void setLow(ColorFilterSettings &colorFilterSettings, double s0To1)=0
Set the low value given the normalized value.
void setHueHigh(int hueHigh)
Set method for hue higher bound.
void printStream(QString indentation, QTextStream &str) const
Debugging method that supports print method of this class and printStream method of some other class(...
void setForegroundHigh(int foregroundHigh)
Set method for foreground higher bound.
Leaf class for value strategy for ColorFilterSettings.
int foregroundHigh() const
Get method for foreground higher bound.
static ColorFilterSettings defaultFilter()
Initial default for any Curve.
int intensityHigh() const
Get method for intensity higher bound.
void setIntensityHigh(int intensityHigh)
Set method for intensity higher bound.
int intensityLow() const
Get method for intensity lower bound.
Leaf class for intensity strategy for ColorFilterSettings.
int saturationHigh() const
Get method for saturation higher bound.
void setValueHigh(int valueHigh)
Set method for value high.
void setIntensityLow(int intensityLow)
Set method for intensity lower bound.
int valueLow() const
Get method for value low.
void setValueLow(int valueLow)
Set method for value low.
virtual double high(const ColorFilterSettings &colorFilterSettings) const =0
Return the high value normalized to 0 to 1.
ColorFilterMode colorFilterMode() const
Get method for filter mode.
void setSaturationHigh(int saturationHigh)
Set method for saturation high.
void loadXml(QXmlStreamReader &reader)
Load curve filter to stream.
~ColorFilterSettings()
Destructor deallocates memory.
Leaf class for foreground strategy for ColorFilterSettings.
void saveXml(QXmlStreamWriter &writer, const QString &curveName) const
Save curve filter to stream.
ColorFilterSettings()
Default constructor only for use when this class is being stored by a container that requires the def...
int hueLow() const
Get method for hue lower bound.
virtual double low(const ColorFilterSettings &colorFilterSettings) const =0
Return the low value normalized to 0 to 1.
int saturationLow() const
Get method for saturation lower bound.