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