Engauge Digitizer  2
DlgSettingsColorFilter.cpp
1 #include "CmdMediator.h"
2 #include "CmdSettingsColorFilter.h"
3 #include "ColorFilter.h"
4 #include "ColorFilterHistogram.h"
5 #include "ColorConstants.h"
6 #include "DlgFilterThread.h"
7 #include "DlgSettingsColorFilter.h"
8 #include "EngaugeAssert.h"
9 #include "Logger.h"
10 #include "MainWindow.h"
11 #include <QComboBox>
12 #include <QDebug>
13 #include <QGraphicsLineItem>
14 #include <QGraphicsScene>
15 #include <QGridLayout>
16 #include <QImage>
17 #include <QLabel>
18 #include <qmath.h>
19 #include <QPixmap>
20 #include <QRadioButton>
21 #include <QRgb>
22 #include "ViewPreview.h"
23 #include "ViewProfile.h"
24 #include "ViewProfileDivider.h"
25 #include "ViewProfileScale.h"
26 
28  DlgSettingsAbstractBase ("Filter",
29  "DlgSettingsColorFilter",
30  mainWindow),
31  m_scenePreview (0),
32  m_viewPreview (0),
33  m_filterThread (0),
34  m_modelColorFilterBefore (0),
35  m_modelColorFilterAfter (0)
36 {
37  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::DlgSettingsColorFilter";
38 
39  QWidget *subPanel = createSubPanel ();
40  finishPanel (subPanel);
41 }
42 
43 DlgSettingsColorFilter::~DlgSettingsColorFilter()
44 {
45  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::~DlgSettingsColorFilter";
46 }
47 
48 void DlgSettingsColorFilter::createControls (QGridLayout *layout, int &row)
49 {
50  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::createControls";
51 
52  QLabel *labelCurve = new QLabel ("Curve Name:");
53  layout->addWidget (labelCurve, row++, 1);
54 
55  m_cmbCurveName = new QComboBox ();
56  m_cmbCurveName->setWhatsThis (tr ("Name of the curve that is currently selected for editing"));
57  connect (m_cmbCurveName, SIGNAL (activated (const QString &)), this, SLOT (slotCurveName (const QString &))); // activated() ignores code changes
58  layout->addWidget (m_cmbCurveName, row++, 1);
59 
60  QLabel *labelProfile = new QLabel ("Filter mode:");
61  layout->addWidget (labelProfile, row++, 1);
62 
63  m_btnIntensity = new QRadioButton (colorFilterModeToString (COLOR_FILTER_MODE_INTENSITY));
64  m_btnIntensity->setWhatsThis (tr ("Filter the original image into black and white pixels using the Intensity parameter, "
65  "to hide unimportant information and emphasize important information.\n\n"
66  "The Intensity value of a pixel is computed from the red, green "
67  "and blue components as I = squareroot (R * R + G * G + B * B)"));
68  connect (m_btnIntensity, SIGNAL (released ()), this, SLOT (slotIntensity ()));
69  layout->addWidget (m_btnIntensity, row++, 1);
70 
71  m_btnForeground = new QRadioButton (colorFilterModeToString (COLOR_FILTER_MODE_FOREGROUND));
72  m_btnForeground->setWhatsThis (tr ("Filter the original image into black and white pixels by isolating the foreground from the background, "
73  "to hide unimportant information and emphasize important information.\n\n"
74  "The background color is shown on the left side of the scale bar.\n\n"
75  "The distance of any color (R, G, B) from the background color (Rb, Gb, Bb) is computed as "
76  "F = squareroot ((R - Rb) * (R - Rb) + (G - Gb) * (G - Gb) + (B - Bb)). On the left end of the "
77  "scale, the foreground distance value is zero, and it increases linearly to the maximum on the far right."));
78  connect (m_btnForeground, SIGNAL (released ()), this, SLOT (slotForeground ()));
79  layout->addWidget (m_btnForeground, row++, 1);
80 
81  m_btnHue = new QRadioButton (colorFilterModeToString (COLOR_FILTER_MODE_HUE));
82  m_btnHue->setWhatsThis (tr ("Filter the original image into black and white pixels using the Hue component of the "
83  "Hue, Saturation and Value (HSV) color components, "
84  "to hide unimportant information and emphasize important information."));
85  connect (m_btnHue, SIGNAL (released ()), this, SLOT (slotHue ()));
86  layout->addWidget (m_btnHue, row++, 1);
87 
88  m_btnSaturation = new QRadioButton (colorFilterModeToString (COLOR_FILTER_MODE_SATURATION));
89  m_btnSaturation->setWhatsThis (tr ("Filter the original image into black and white pixels using the Saturation component of the "
90  "Hue, Saturation and Value (HSV) color components, "
91  "to hide unimportant information and emphasize important information."));
92  connect (m_btnSaturation, SIGNAL (released ()), this, SLOT (slotSaturation ()));
93  layout->addWidget (m_btnSaturation, row++, 1);
94 
95  m_btnValue = new QRadioButton (colorFilterModeToString (COLOR_FILTER_MODE_VALUE));
96  m_btnValue->setWhatsThis (tr ("Filter the original image into black and white pixels using the Value component of the "
97  "Hue, Saturation and Value (HSV) color components, "
98  "to hide unimportant information and emphasize important information.\n\n"
99  "The Value component is also called the Lightness."));
100  connect (m_btnValue, SIGNAL (released ()), this, SLOT (slotValue ()));
101  layout->addWidget (m_btnValue, row++, 1);
102 }
103 
104 void DlgSettingsColorFilter::createPreview (QGridLayout *layout, int &row)
105 {
106  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::createPreview";
107 
108  QLabel *labelPreview = new QLabel ("Preview");
109  layout->addWidget (labelPreview, row++, 0, 1, 5);
110 
111  m_scenePreview = new QGraphicsScene (this);
112  m_viewPreview = new ViewPreview (m_scenePreview, this);
113  m_viewPreview->setWhatsThis (tr ("Preview window that shows how current settings affect the filtering of the original image."));
114  m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
115  m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
116  m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
117  m_viewPreview->setRenderHint(QPainter::Antialiasing);
118 
119  layout->addWidget (m_viewPreview, row++, 0, 1, 5);
120 }
121 
122 void DlgSettingsColorFilter::createProfileAndScale (QGridLayout *layout, int &row)
123 {
124  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::createProfileAndScale";
125 
126  const int MINIMUM_VIEW_PROFILE_WIDTH = 70;
127 
128  QLabel *labelProfile = new QLabel ("Filter Parameter Histogram Profile");
129  layout->addWidget (labelProfile, row++, 3);
130 
131  m_sceneProfile = new QGraphicsScene;
132  m_sceneProfile->setSceneRect(0, 0, PROFILE_SCENE_WIDTH (), PROFILE_SCENE_HEIGHT ());
133 
134  m_viewProfile = new ViewProfile (m_sceneProfile,
135  MINIMUM_VIEW_PROFILE_WIDTH);
136  m_viewProfile->setWhatsThis (tr ("Histogram profile of the selected filter parameter. The two Dividers can be moved back and forth to adjust "
137  "the range of filter parameter values that will be included in the filtered image. The clear portion will "
138  "be included, and the shaded portion will be excluded."));
139  layout->addWidget (m_viewProfile, row, 3, PROFILE_HEIGHT_IN_ROWS (), 1);
140  row += PROFILE_HEIGHT_IN_ROWS ();
141 
142  m_scale = new ViewProfileScale (MINIMUM_VIEW_PROFILE_WIDTH);
143  m_scale->setWhatsThis (tr ("This read-only box displays a graphical representation of the horizontal axis in the histogram profile above."));
144  m_scale->setAutoFillBackground(true);
145  layout->addWidget (m_scale, row++, 3, 1, 1);
146 }
147 
149 {
150  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::createSubPanel";
151 
152  const int EMPTY_COLUMN_WIDTH = 40;
153 
154  QWidget *subPanel = new QWidget ();
155  QGridLayout *layout = new QGridLayout (subPanel);
156  subPanel->setLayout (layout);
157 
158  layout->setColumnStretch(0, 0); // Empty column
159  layout->setColumnMinimumWidth(0, EMPTY_COLUMN_WIDTH);
160  layout->setColumnStretch(1, 0); // Radio buttons
161  layout->setColumnMinimumWidth(1, 210);
162  layout->setColumnStretch(2, 0); // Empty column to put some space between previous and next columns, so they are not too close
163  layout->setColumnMinimumWidth(2, 15);
164  layout->setColumnStretch(3, 1); // Profile
165  layout->setColumnMinimumWidth(4, EMPTY_COLUMN_WIDTH); // Empty column
166  layout->setColumnStretch(4, 0);
167 
168  int rowLeft = 0, rowRight = 0;
169  createControls (layout, rowLeft);
170  createProfileAndScale (layout, rowRight);
171 
172  int row = qMax (rowLeft, rowRight);
173  createPreview (layout, row);
174 
175  return subPanel;
176 }
177 
178 QRgb DlgSettingsColorFilter::createThread ()
179 {
180  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::createThread";
181 
182  // Get background color
183  QImage image = cmdMediator().document().pixmap().toImage();
184  ColorFilter filter;
185  QRgb rgbBackground = filter.marginColor(&image);
186 
187  // Only create thread once
188  if (m_filterThread == 0) {
189 
190  m_filterThread = new DlgFilterThread (cmdMediator().document().pixmap(),
191  rgbBackground,
192  *this);
193  m_filterThread->start(); // Now that thread is started, we can use signalApplyFilter
194  }
195 
196  return rgbBackground;
197 }
198 
200 {
201  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::handleOk";
202 
204  cmdMediator ().document(),
205  *m_modelColorFilterBefore,
206  *m_modelColorFilterAfter);
207  cmdMediator ().push (cmd);
208 
209  hide ();
210 }
211 
213 {
214  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::load";
215 
216  setCmdMediator (cmdMediator);
217 
218  // Flush old data
219  if (m_modelColorFilterBefore != 0) {
220  delete m_modelColorFilterBefore;
221  }
222  if (m_modelColorFilterAfter != 0) {
223  delete m_modelColorFilterAfter;
224  }
225 
226  // Save new data
227  m_modelColorFilterBefore = new DocumentModelColorFilter (cmdMediator.document());
228  m_modelColorFilterAfter = new DocumentModelColorFilter (cmdMediator.document());
229 
230  // Populate controls. First load curve name combobox. The curve-specific controls get loaded in slotCurveName
231  m_cmbCurveName->clear ();
232  m_cmbCurveName->addItem (AXIS_CURVE_NAME);
233  QStringList curveNames = cmdMediator.curvesGraphsNames();
234  QStringList::const_iterator itr;
235  for (itr = curveNames.begin (); itr != curveNames.end (); itr++) {
236 
237  QString curveName = *itr;
238  m_cmbCurveName->addItem (curveName);
239  }
240 
241  // This sets the curve name
242  m_cmbCurveName->setCurrentText (mainWindow().selectedGraphCurve());
243  loadForCurveName();
244 
245  enableOk (false); // Disable Ok button since there not yet any changes
246 }
247 
248 void DlgSettingsColorFilter::loadForCurveName()
249 {
250  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::loadForCurveName";
251 
252  // Get curve name from control
253  QString curveName = m_cmbCurveName->currentText();
254 
255  // Skip if everything is not set up yet
256  if (!curveName.isEmpty () && m_modelColorFilterAfter != 0) {
257 
258  // Populate controls
259  ColorFilterMode colorFilterMode = m_modelColorFilterAfter->colorFilterMode(curveName);
260  m_btnIntensity->setChecked (colorFilterMode == COLOR_FILTER_MODE_INTENSITY);
261  m_btnForeground->setChecked (colorFilterMode == COLOR_FILTER_MODE_FOREGROUND);
262  m_btnHue->setChecked (colorFilterMode == COLOR_FILTER_MODE_HUE);
263  m_btnSaturation->setChecked (colorFilterMode == COLOR_FILTER_MODE_SATURATION);
264  m_btnValue->setChecked (colorFilterMode == COLOR_FILTER_MODE_VALUE);
265 
266  m_scenePreview->clear();
267  m_imagePreview = cmdMediator().document().pixmap().toImage();
268  m_scenePreview->addPixmap (QPixmap::fromImage (m_imagePreview));
269 
270  QRgb rgbBackground = createThread ();
271  m_scale->setBackgroundColor (rgbBackground);
272  createThread ();
273  updateHistogram();
274  updatePreview(); // Needs thread initialized
275  }
276 }
277 
278 void DlgSettingsColorFilter::slotCurveName(const QString & /* curveName */)
279 {
280  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::slotCurveName";
281 
282  loadForCurveName ();
283 }
284 
285 void DlgSettingsColorFilter::slotDividerHigh (double xCenter)
286 {
287  m_modelColorFilterAfter->setHigh (m_cmbCurveName->currentText(),
288  xCenter / (double) PROFILE_SCENE_WIDTH ());
289  updatePreview();
290 }
291 
292 void DlgSettingsColorFilter::slotDividerLow (double xCenter)
293 {
294  m_modelColorFilterAfter->setLow (m_cmbCurveName->currentText(),
295  xCenter / (double) PROFILE_SCENE_WIDTH ());
296  updatePreview();
297 }
298 
299 void DlgSettingsColorFilter::slotForeground ()
300 {
301  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::slotForeground";
302 
303  m_modelColorFilterAfter->setColorFilterMode(m_cmbCurveName->currentText(),
304  COLOR_FILTER_MODE_FOREGROUND);
305  updateHistogram();
306  updatePreview();
307 }
308 
309 void DlgSettingsColorFilter::slotHue ()
310 {
311  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::slotHue";
312 
313  m_modelColorFilterAfter->setColorFilterMode(m_cmbCurveName->currentText(),
314  COLOR_FILTER_MODE_HUE);
315  updateHistogram();
316  updatePreview();
317 }
318 
319 void DlgSettingsColorFilter::slotIntensity ()
320 {
321  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::slotIntensity";
322 
323  m_modelColorFilterAfter->setColorFilterMode(m_cmbCurveName->currentText(),
324  COLOR_FILTER_MODE_INTENSITY);
325  updateHistogram();
326  updatePreview();
327 }
328 
329 void DlgSettingsColorFilter::slotSaturation ()
330 {
331  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::slotSaturation";
332 
333  m_modelColorFilterAfter->setColorFilterMode(m_cmbCurveName->currentText(),
334  COLOR_FILTER_MODE_SATURATION);
335  updateHistogram();
336  updatePreview();
337 }
338 
340  QImage image)
341 {
342  // Overwrite one piece of the processed image. This approach is a bit slow because the entire QPixmap
343  // in the QGraphicsScene gets exchanged as part of each update, but that seems to be the only possible
344  // approach when using QGraphicsScene. If not fast enough or there is ugly flicker, we may replace
345  // QGraphicsScene by a simple QWidget and override the paint function - but that approach may get
346  // complicated when resizing the QGraphicsView
347  for (int xFrom = 0, xTo = xLeft; xFrom < image.width(); xFrom++, xTo++) {
348  for (int y = 0; y < image.height (); y++) {
349 
350  QColor pixel = image.pixel (xFrom, y);
351  m_imagePreview.setPixel (xTo, y, pixel.rgb());
352  }
353  }
354 
355  // Remove old pixmap
356  QGraphicsItem *itemPixmap = m_scenePreview->items().at(0);
357  m_scenePreview->removeItem (itemPixmap);
358  delete itemPixmap;
359 
360  // Save new pixmap. Only visible change should be the area covered by the pixels in image
361  m_scenePreview->addPixmap (QPixmap::fromImage (m_imagePreview));
362 }
363 
364 void DlgSettingsColorFilter::slotValue ()
365 {
366  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::slotValue";
367 
368  m_modelColorFilterAfter->setColorFilterMode(m_cmbCurveName->currentText(),
369  COLOR_FILTER_MODE_VALUE);
370  updateHistogram();
371  updatePreview();
372 }
373 
374 void DlgSettingsColorFilter::updateHistogram()
375 {
376  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsColorFilter::updateHistogram";
377 
378  enableOk (true);
379 
380  const double PEN_WIDTH = 0.0; // Zero value gives one-pixel width at all scales
381 
382  QString curveName = m_cmbCurveName->currentText();
383 
384  m_sceneProfile->clear();
385 
386  m_scale->setColorFilterMode (m_modelColorFilterAfter->colorFilterMode(curveName));
387 
388  // Start with original image
389  QImage image = cmdMediator().document().pixmap().toImage();
390 
391  double histogramBins [ColorFilterHistogram::HISTOGRAM_BINS ()];
392 
393  ColorFilter filter;
394  ColorFilterHistogram filterHistogram;
395  int maxBinCount;
396  filterHistogram.generate (filter,
397  histogramBins,
398  m_modelColorFilterAfter->colorFilterMode (curveName),
399  image,
400  maxBinCount);
401 
402  // Draw histogram, normalizing so highest peak exactly fills the vertical range. Log scale is used
403  // so smaller peaks do not disappear
404  double logMaxBinCount = qLn (maxBinCount);
405  for (int bin = 1; bin < ColorFilterHistogram::HISTOGRAM_BINS (); bin++) {
406 
407  double x0 = PROFILE_SCENE_WIDTH () * (bin - 1.0) / (ColorFilterHistogram::HISTOGRAM_BINS () - 1.0);
408 
409  // Map logPixelCount through 0 to 0 through PROFILE_SCENE_HEIGHT-1, using log scale
410  double count0 = 1.0 + histogramBins [bin - 1];
411  double y0 = (PROFILE_SCENE_HEIGHT () - 1.0) * (1.0 - qLn (count0) / logMaxBinCount);
412 
413  double x1 = PROFILE_SCENE_WIDTH () * (bin - 0.0) / (ColorFilterHistogram::HISTOGRAM_BINS () - 1.0);
414 
415  // Map logPixelCount through 0 to 0 through PROFILE_SCENE_HEIGHT-1, using log scale
416  double count1 = 1.0 + histogramBins [bin];
417  double y1 = (PROFILE_SCENE_HEIGHT () - 1.0) * (1.0 - qLn (count1) / logMaxBinCount);
418 
419  QGraphicsLineItem *line = new QGraphicsLineItem (x0, y0, x1, y1);
420  line->setPen (QPen (QBrush (Qt::black), PEN_WIDTH));
421  m_sceneProfile->addItem (line);
422  }
423 
424  // Create low and high dividers
425  m_dividerLow = new ViewProfileDivider(*m_sceneProfile,
426  *m_viewProfile,
427  PROFILE_SCENE_WIDTH (),
428  PROFILE_SCENE_HEIGHT (),
429  PROFILE_SCENE_HEIGHT () * 2.0 / 3.0,
430  true);
431  m_dividerHigh = new ViewProfileDivider(*m_sceneProfile,
432  *m_viewProfile,
433  PROFILE_SCENE_HEIGHT (),
434  PROFILE_SCENE_WIDTH (),
435  PROFILE_SCENE_HEIGHT () / 3.0,
436  false);
437 
438  // Connect the dividers to each other since the shaded areas depend on both divides when low divider is
439  // moved to the right of the high divider
440  connect (m_dividerLow, SIGNAL (signalMovedLow (double)), m_dividerHigh, SLOT (slotOtherMoved(double)));
441  connect (m_dividerHigh, SIGNAL (signalMovedHigh (double)), m_dividerLow, SLOT (slotOtherMoved(double)));
442 
443  // Update preview when the dividers move
444  connect (m_dividerLow, SIGNAL (signalMovedLow (double)), this, SLOT (slotDividerLow (double)));
445  connect (m_dividerHigh, SIGNAL(signalMovedHigh (double)), this, SLOT (slotDividerHigh (double)));
446 
447  if (m_btnForeground->isChecked()) {
448 
449  // Foreground
450  m_dividerLow->setX (m_modelColorFilterAfter->foregroundLow(curveName), FOREGROUND_MIN, FOREGROUND_MAX);
451  m_dividerHigh->setX (m_modelColorFilterAfter->foregroundHigh(curveName), FOREGROUND_MIN, FOREGROUND_MAX);
452 
453  } else if (m_btnIntensity->isChecked()) {
454 
455  // Intensity
456  m_dividerLow->setX (m_modelColorFilterAfter->intensityLow(curveName), INTENSITY_MIN, INTENSITY_MAX);
457  m_dividerHigh->setX (m_modelColorFilterAfter->intensityHigh(curveName), INTENSITY_MIN, INTENSITY_MAX);
458 
459  } else if (m_btnHue->isChecked()) {
460 
461  // Hue
462  m_dividerLow->setX (m_modelColorFilterAfter->hueLow(curveName), HUE_MIN, HUE_MAX);
463  m_dividerHigh->setX (m_modelColorFilterAfter->hueHigh(curveName), HUE_MIN, HUE_MAX);
464 
465  } else if (m_btnSaturation->isChecked()) {
466 
467  // Saturation
468  m_dividerLow->setX (m_modelColorFilterAfter->saturationLow(curveName), SATURATION_MIN, SATURATION_MAX);
469  m_dividerHigh->setX (m_modelColorFilterAfter->saturationHigh(curveName), SATURATION_MIN, SATURATION_MAX);
470 
471  } else if (m_btnValue->isChecked()) {
472 
473  // Value
474  m_dividerLow->setX (m_modelColorFilterAfter->valueLow(curveName), VALUE_MIN, VALUE_MAX);
475  m_dividerHigh->setX (m_modelColorFilterAfter->valueHigh(curveName), VALUE_MIN, VALUE_MAX);
476 
477  } else {
478 
479  ENGAUGE_ASSERT (false);
480 
481  }
482 }
483 
484 void DlgSettingsColorFilter::updatePreview ()
485 {
486  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettings::updatePreview";
487 
488  enableOk (true);
489 
490  // This (indirectly) updates the preview
491  QString curveName = m_cmbCurveName->currentText();
492  emit signalApplyFilter (m_modelColorFilterAfter->colorFilterMode(curveName),
493  m_modelColorFilterAfter->low(curveName),
494  m_modelColorFilterAfter->high(curveName));
495 }
void setBackgroundColor(QRgb rgbBackground)
Save the background color for foreground calculations.
int valueHigh(const QString &curveName) const
Get method for value high.
void generate(const ColorFilter &filter, double histogramBins[], ColorFilterMode colorFilterMode, const QImage &image, int &maxBinCount) const
Generate the histogram.
void setColorFilterMode(const QString &curveName, ColorFilterMode colorFilterMode)
Set method for filter mode.
int saturationLow(const QString &curveName) const
Get method for saturation lower bound.
void setX(double x, double xLow, double xHigh)
Set the position by specifying the new x coordinate.
void setCmdMediator(CmdMediator &cmdMediator)
Store CmdMediator for easy access by the leaf class.
int valueLow(const QString &curveName) const
Get method for value low.
QPixmap pixmap() const
Return the image that is being digitized.
Definition: Document.cpp:511
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:61
Class for filtering image to remove unimportant information.
Definition: ColorFilter.h:12
void slotTransferPiece(int xLeft, QImage image)
Receive processed piece of preview image, to be inserted at xLeft to xLeft+pixmap.width().
virtual void handleOk()
Process slotOk.
int foregroundLow(const QString &curveName) const
Get method for foreground lower bound.
int intensityLow(const QString &curveName) const
Get method for intensity lower bound.
void signalApplyFilter(ColorFilterMode colorFilterMode, double low, double high)
Send filter parameters to DlgFilterThread and DlgFilterWorker for processing.
double low(const QString &curveName) const
Low value of foreground, hue, intensity, saturation or value according to current filter mode normali...
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
void setHigh(const QString &curveName, double s0To1)
Set the high value for the current filter mode.
Class that modifies QGraphicsView to automatically expand/shrink the view to fit the window...
Definition: ViewPreview.h:8
Model for DlgSettingsColorFilter and CmdSettingsColorFilter.
int hueLow(const QString &curveName) const
Get method for hue lower bound.
Linear horizontal scale, with the spectrum reflecting the active filter parameter.
double high(const QString &curveName) const
High value of foreground, hue, intensity, saturation or value according to current filter mode...
QRgb marginColor(const QImage *image) const
Identify the margin color of the image, which is defined as the most common color in the four margins...
Definition: ColorFilter.cpp:52
int hueHigh(const QString &curveName) const
Get method for hue higher bound.
void setColorFilterMode(ColorFilterMode colorFilterMode)
Change the gradient type.
int foregroundHigh(const QString &curveName) const
Get method for foreground higher bound.
Divider that can be dragged, in a dialog QGraphicsView.
ColorFilterMode colorFilterMode(const QString &curveName) const
Get method for filter mode.
Class for processing new filter settings. This is based on http://blog.debao.me/2013/08/how-to-use-qt...
void setLow(const QString &curveName, double s0To1)
Set the low value for the current filter mode.
Command for DlgSettingsColorFilter.
void finishPanel(QWidget *subPanel)
Add Ok and Cancel buttons to subpanel to get the whole dialog.
virtual QWidget * createSubPanel()
Create dialog-specific panel to which base class will add Ok and Cancel buttons.
static int MINIMUM_PREVIEW_HEIGHT
Dialog layout constant that guarantees preview has sufficent room.
void enableOk(bool enable)
Let leaf subclass control the Ok button.
Command queue stack.
Definition: CmdMediator.h:16
DlgSettingsColorFilter(MainWindow &mainWindow)
Single constructor.
Abstract base class for all Settings dialogs.
int intensityHigh(const QString &curveName) const
Get method for intensity higher bound.
Class that generates a histogram according to the current filter.
Class that modifies QGraphicsView to present a two-dimensional profile, with movable dividers for sel...
Definition: ViewProfile.h:9
static int HISTOGRAM_BINS()
Number of histogram bins.
MainWindow & mainWindow()
Get method for MainWindow.
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition: MainWindow.h:60
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition: CmdMediator.cpp:51
int saturationHigh(const QString &curveName) const
Get method for saturation higher bound.
CmdMediator & cmdMediator()
Provide access to Document information wrapped inside CmdMediator.