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