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" 16 #include "MainWindow.h" 19 #include <QGraphicsLineItem> 20 #include <QGraphicsScene> 21 #include <QGridLayout> 26 #include <QRadioButton> 28 #include "ViewPreview.h" 29 #include "ViewProfile.h" 30 #include "ViewProfileDivider.h" 31 #include "ViewProfileScale.h" 33 const int MINIMUM_DIALOG_WIDTH_COLOR_FILTER = 640;
34 const int MINIMUM_HEIGHT = 500;
38 "DlgSettingsColorFilter",
43 m_modelColorFilterBefore (0),
44 m_modelColorFilterAfter (0)
46 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::DlgSettingsColorFilter";
50 MINIMUM_DIALOG_WIDTH_COLOR_FILTER);
53 DlgSettingsColorFilter::~DlgSettingsColorFilter()
55 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::~DlgSettingsColorFilter";
58 void DlgSettingsColorFilter::createControls (QGridLayout *layout,
int &row)
60 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::createControls";
62 QLabel *labelCurve =
new QLabel (tr (
"Curve Name:"));
63 layout->addWidget (labelCurve, row++, 1);
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 &)));
68 layout->addWidget (m_cmbCurveName, row++, 1);
70 QLabel *labelProfile =
new QLabel (tr (
"Filter mode:"));
71 layout->addWidget (labelProfile, row++, 1);
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);
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);
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);
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);
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);
118 void DlgSettingsColorFilter::createPreview (QGridLayout *layout,
int &row)
120 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::createPreview";
122 QLabel *labelPreview =
new QLabel (tr (
"Preview"));
123 layout->addWidget (labelPreview, row++, 0, 1, 5);
125 m_scenePreview =
new QGraphicsScene (
this);
127 ViewPreview::VIEW_ASPECT_RATIO_VARIABLE,
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);
133 m_viewPreview->setRenderHint(QPainter::Antialiasing);
135 layout->addWidget (m_viewPreview, row++, 0, 1, 5);
138 void DlgSettingsColorFilter::createProfileAndScale (QGridLayout *layout,
int &row)
140 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::createProfileAndScale";
142 const int MINIMUM_VIEW_PROFILE_WIDTH = 70;
144 QLabel *labelProfile =
new QLabel (tr (
"Filter Parameter Histogram Profile"));
145 layout->addWidget (labelProfile, row++, 3);
147 m_sceneProfile =
new QGraphicsScene;
148 m_sceneProfile->setSceneRect(0, 0, PROFILE_SCENE_WIDTH (), PROFILE_SCENE_HEIGHT ());
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 ();
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);
166 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::createSubPanel";
168 const int EMPTY_COLUMN_WIDTH = 40;
170 QWidget *subPanel =
new QWidget ();
171 QGridLayout *layout =
new QGridLayout (subPanel);
172 subPanel->setLayout (layout);
174 layout->setColumnStretch(0, 0);
175 layout->setColumnMinimumWidth(0, EMPTY_COLUMN_WIDTH);
176 layout->setColumnStretch(1, 0);
177 layout->setColumnMinimumWidth(1, 210);
178 layout->setColumnStretch(2, 0);
179 layout->setColumnMinimumWidth(2, 15);
180 layout->setColumnStretch(3, 1);
181 layout->setColumnMinimumWidth(4, EMPTY_COLUMN_WIDTH);
182 layout->setColumnStretch(4, 0);
184 int rowLeft = 0, rowRight = 0;
185 createControls (layout, rowLeft);
186 createProfileAndScale (layout, rowRight);
188 int row = qMax (rowLeft, rowRight);
189 createPreview (layout, row);
194 QRgb DlgSettingsColorFilter::createThread ()
196 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::createThread";
204 if (m_filterThread == 0) {
209 m_filterThread->start();
212 return rgbBackground;
217 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::handleOk";
221 *m_modelColorFilterBefore,
222 *m_modelColorFilterAfter);
230 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::load";
235 if (m_modelColorFilterBefore != 0) {
236 delete m_modelColorFilterBefore;
238 if (m_modelColorFilterAfter != 0) {
239 delete m_modelColorFilterAfter;
247 m_cmbCurveName->clear ();
248 m_cmbCurveName->addItem (AXIS_CURVE_NAME);
250 QStringList::const_iterator itr;
251 for (itr = curveNames.begin (); itr != curveNames.end (); itr++) {
253 QString curveName = *itr;
254 m_cmbCurveName->addItem (curveName);
258 m_cmbCurveName->setCurrentText (
mainWindow().selectedGraphCurve());
264 void DlgSettingsColorFilter::loadForCurveName()
266 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::loadForCurveName";
269 QString curveName = m_cmbCurveName->currentText();
272 if (!curveName.isEmpty () && m_modelColorFilterAfter != 0) {
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);
282 m_scenePreview->clear();
284 m_scenePreview->addPixmap (QPixmap::fromImage (m_imagePreview));
286 QRgb rgbBackground = createThread ();
297 setMinimumHeight (MINIMUM_HEIGHT);
301 void DlgSettingsColorFilter::slotCurveName(
const QString & )
303 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotCurveName";
308 void DlgSettingsColorFilter::slotDividerHigh (
double xCenter)
310 m_modelColorFilterAfter->
setHigh (m_cmbCurveName->currentText(),
311 xCenter / (double) PROFILE_SCENE_WIDTH ());
315 void DlgSettingsColorFilter::slotDividerLow (
double xCenter)
317 m_modelColorFilterAfter->
setLow (m_cmbCurveName->currentText(),
318 xCenter / (double) PROFILE_SCENE_WIDTH ());
322 void DlgSettingsColorFilter::slotForeground ()
324 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotForeground";
327 COLOR_FILTER_MODE_FOREGROUND);
332 void DlgSettingsColorFilter::slotHue ()
334 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotHue";
337 COLOR_FILTER_MODE_HUE);
342 void DlgSettingsColorFilter::slotIntensity ()
344 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotIntensity";
347 COLOR_FILTER_MODE_INTENSITY);
352 void DlgSettingsColorFilter::slotSaturation ()
354 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotSaturation";
357 COLOR_FILTER_MODE_SATURATION);
370 for (
int xFrom = 0, xTo = xLeft; xFrom < image.width(); xFrom++, xTo++) {
371 for (
int y = 0; y < image.height (); y++) {
373 QColor pixel = image.pixel (xFrom, y);
374 m_imagePreview.setPixel (xTo, y, pixel.rgb());
379 QGraphicsItem *itemPixmap = m_scenePreview->items().at(0);
380 m_scenePreview->removeItem (itemPixmap);
384 m_scenePreview->addPixmap (QPixmap::fromImage (m_imagePreview));
387 void DlgSettingsColorFilter::slotValue ()
389 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotValue";
392 COLOR_FILTER_MODE_VALUE);
397 void DlgSettingsColorFilter::updateHistogram()
399 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::updateHistogram";
403 const double PEN_WIDTH = 0.0;
405 QString curveName = m_cmbCurveName->currentText();
407 m_sceneProfile->clear();
427 double logMaxBinCount = qLn (maxBinCount);
433 double count0 = 1.0 + histogramBins [bin - 1];
434 double y0 = (PROFILE_SCENE_HEIGHT () - 1.0) * (1.0 - qLn (count0) / logMaxBinCount);
439 double count1 = 1.0 + histogramBins [bin];
440 double y1 = (PROFILE_SCENE_HEIGHT () - 1.0) * (1.0 - qLn (count1) / logMaxBinCount);
442 QGraphicsLineItem *line =
new QGraphicsLineItem (x0, y0, x1, y1);
443 line->setPen (QPen (QBrush (Qt::black), PEN_WIDTH));
444 m_sceneProfile->addItem (line);
450 PROFILE_SCENE_WIDTH (),
451 PROFILE_SCENE_HEIGHT (),
452 PROFILE_SCENE_HEIGHT () * 2.0 / 3.0,
456 PROFILE_SCENE_HEIGHT (),
457 PROFILE_SCENE_WIDTH (),
458 PROFILE_SCENE_HEIGHT () / 3.0,
463 connect (m_dividerLow, SIGNAL (signalMovedLow (
double)), m_dividerHigh, SLOT (slotOtherMoved(
double)));
464 connect (m_dividerHigh, SIGNAL (signalMovedHigh (
double)), m_dividerLow, SLOT (slotOtherMoved(
double)));
467 connect (m_dividerLow, SIGNAL (signalMovedLow (
double)),
this, SLOT (slotDividerLow (
double)));
468 connect (m_dividerHigh, SIGNAL(signalMovedHigh (
double)),
this, SLOT (slotDividerHigh (
double)));
470 if (m_btnForeground->isChecked()) {
473 m_dividerLow->
setX (m_modelColorFilterAfter->
foregroundLow(curveName), FOREGROUND_MIN, FOREGROUND_MAX);
474 m_dividerHigh->
setX (m_modelColorFilterAfter->
foregroundHigh(curveName), FOREGROUND_MIN, FOREGROUND_MAX);
476 }
else if (m_btnIntensity->isChecked()) {
479 m_dividerLow->
setX (m_modelColorFilterAfter->
intensityLow(curveName), INTENSITY_MIN, INTENSITY_MAX);
480 m_dividerHigh->
setX (m_modelColorFilterAfter->
intensityHigh(curveName), INTENSITY_MIN, INTENSITY_MAX);
482 }
else if (m_btnHue->isChecked()) {
485 m_dividerLow->
setX (m_modelColorFilterAfter->
hueLow(curveName), HUE_MIN, HUE_MAX);
486 m_dividerHigh->
setX (m_modelColorFilterAfter->
hueHigh(curveName), HUE_MIN, HUE_MAX);
488 }
else if (m_btnSaturation->isChecked()) {
491 m_dividerLow->
setX (m_modelColorFilterAfter->
saturationLow(curveName), SATURATION_MIN, SATURATION_MAX);
492 m_dividerHigh->
setX (m_modelColorFilterAfter->
saturationHigh(curveName), SATURATION_MIN, SATURATION_MAX);
494 }
else if (m_btnValue->isChecked()) {
497 m_dividerLow->
setX (m_modelColorFilterAfter->
valueLow(curveName), VALUE_MIN, VALUE_MAX);
498 m_dividerHigh->
setX (m_modelColorFilterAfter->
valueHigh(curveName), VALUE_MIN, VALUE_MAX);
502 ENGAUGE_ASSERT (
false);
506 free (histogramBins);
509 void DlgSettingsColorFilter::updatePreview ()
511 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettings::updatePreview";
516 QString curveName = m_cmbCurveName->currentText();
518 m_modelColorFilterAfter->
low(curveName),
519 m_modelColorFilterAfter->
high(curveName));
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...
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.
Class for filtering image to remove unimportant information.
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...
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.
DlgSettingsColorFilter(MainWindow &mainWindow)
Single constructor.
Abstract base class for all Settings dialogs.
QPixmap pixmap() const
Return the image that is being digitized.
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...
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...
CmdMediator & cmdMediator()
Provide access to Document information wrapped inside CmdMediator.