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>
26#include <QRadioButton>
28#include "ViewPreview.h"
29#include "ViewProfile.h"
30#include "ViewProfileDivider.h"
31#include "ViewProfileScale.h"
35 "DlgSettingsColorFilter",
40 m_modelColorFilterBefore (0),
41 m_modelColorFilterAfter (0)
43 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::DlgSettingsColorFilter";
49DlgSettingsColorFilter::~DlgSettingsColorFilter()
51 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::~DlgSettingsColorFilter";
54void DlgSettingsColorFilter::createControls (QGridLayout *layout,
int &row)
56 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::createControls";
58 QLabel *labelCurve =
new QLabel (tr (
"Curve Name:"));
59 layout->addWidget (labelCurve, row++, 1);
61 m_cmbCurveName =
new QComboBox ();
62 m_cmbCurveName->setWhatsThis (tr (
"Name of the curve that is currently selected for editing"));
63 connect (m_cmbCurveName, SIGNAL (activated (
const QString &)),
this, SLOT (slotCurveName (
const QString &)));
64 layout->addWidget (m_cmbCurveName, row++, 1);
66 QLabel *labelProfile =
new QLabel (tr (
"Filter mode:"));
67 layout->addWidget (labelProfile, row++, 1);
69 m_btnIntensity =
new QRadioButton (colorFilterModeToString (COLOR_FILTER_MODE_INTENSITY));
70 m_btnIntensity->setWhatsThis (tr (
"Filter the original image into black and white pixels using the Intensity parameter, "
71 "to hide unimportant information and emphasize important information.\n\n"
72 "The Intensity value of a pixel is computed from the red, green "
73 "and blue components as I = squareroot (R * R + G * G + B * B)"));
74 connect (m_btnIntensity, SIGNAL (released ()),
this, SLOT (slotIntensity ()));
75 layout->addWidget (m_btnIntensity, row++, 1);
77 m_btnForeground =
new QRadioButton (colorFilterModeToString (COLOR_FILTER_MODE_FOREGROUND));
78 m_btnForeground->setWhatsThis (tr (
"Filter the original image into black and white pixels by isolating the foreground from the background, "
79 "to hide unimportant information and emphasize important information.\n\n"
80 "The background color is shown on the left side of the scale bar.\n\n"
81 "The distance of any color (R, G, B) from the background color (Rb, Gb, Bb) is computed as "
82 "F = squareroot ((R - Rb) * (R - Rb) + (G - Gb) * (G - Gb) + (B - Bb)). On the left end of the "
83 "scale, the foreground distance value is zero, and it increases linearly to the maximum on the far right."));
84 connect (m_btnForeground, SIGNAL (released ()),
this, SLOT (slotForeground ()));
85 layout->addWidget (m_btnForeground, row++, 1);
87 m_btnHue =
new QRadioButton (colorFilterModeToString (COLOR_FILTER_MODE_HUE));
88 m_btnHue->setWhatsThis (tr (
"Filter the original image into black and white pixels using the Hue component of the "
89 "Hue, Saturation and Value (HSV) color components, "
90 "to hide unimportant information and emphasize important information."));
91 connect (m_btnHue, SIGNAL (released ()),
this, SLOT (slotHue ()));
92 layout->addWidget (m_btnHue, row++, 1);
94 m_btnSaturation =
new QRadioButton (colorFilterModeToString (COLOR_FILTER_MODE_SATURATION));
95 m_btnSaturation->setWhatsThis (tr (
"Filter the original image into black and white pixels using the Saturation component of the "
96 "Hue, Saturation and Value (HSV) color components, "
97 "to hide unimportant information and emphasize important information."));
98 connect (m_btnSaturation, SIGNAL (released ()),
this, SLOT (slotSaturation ()));
99 layout->addWidget (m_btnSaturation, row++, 1);
101 m_btnValue =
new QRadioButton (colorFilterModeToString (COLOR_FILTER_MODE_VALUE));
102 m_btnValue->setWhatsThis (tr (
"Filter the original image into black and white pixels using the Value component of the "
103 "Hue, Saturation and Value (HSV) color components, "
104 "to hide unimportant information and emphasize important information.\n\n"
105 "The Value component is also called the Lightness."));
106 connect (m_btnValue, SIGNAL (released ()),
this, SLOT (slotValue ()));
107 layout->addWidget (m_btnValue, row++, 1);
114void DlgSettingsColorFilter::createPreview (QGridLayout *layout,
int &row)
116 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::createPreview";
118 QLabel *labelPreview =
new QLabel (tr (
"Preview"));
119 layout->addWidget (labelPreview, row++, 0, 1, 5);
121 m_scenePreview =
new QGraphicsScene (
this);
123 ViewPreview::VIEW_ASPECT_RATIO_VARIABLE,
125 m_viewPreview->setWhatsThis (tr (
"Preview window that shows how current settings affect the filtering of the original image."));
126 m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
127 m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
129 m_viewPreview->setRenderHint(QPainter::Antialiasing);
131 layout->addWidget (m_viewPreview, row++, 0, 1, 5);
134void DlgSettingsColorFilter::createProfileAndScale (QGridLayout *layout,
int &row)
136 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::createProfileAndScale";
138 const int MINIMUM_VIEW_PROFILE_WIDTH = 70;
140 QLabel *labelProfile =
new QLabel (tr (
"Filter Parameter Histogram Profile"));
141 layout->addWidget (labelProfile, row++, 3);
143 m_sceneProfile =
new QGraphicsScene;
144 m_sceneProfile->setSceneRect(0, 0, PROFILE_SCENE_WIDTH (), PROFILE_SCENE_HEIGHT ());
147 MINIMUM_VIEW_PROFILE_WIDTH);
148 m_viewProfile->setWhatsThis (tr (
"Histogram profile of the selected filter parameter. The two Dividers can be moved back and forth to adjust "
149 "the range of filter parameter values that will be included in the filtered image. The clear portion will "
150 "be included, and the shaded portion will be excluded."));
151 layout->addWidget (m_viewProfile, row, 3, PROFILE_HEIGHT_IN_ROWS (), 1);
152 row += PROFILE_HEIGHT_IN_ROWS ();
155 m_scale->setWhatsThis (tr (
"This read-only box displays a graphical representation of the horizontal axis in the histogram profile above."));
156 m_scale->setAutoFillBackground(
true);
157 layout->addWidget (m_scale, row++, 3, 1, 1);
162 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::createSubPanel";
164 const int EMPTY_COLUMN_WIDTH = 40;
166 QWidget *subPanel =
new QWidget ();
167 QGridLayout *layout =
new QGridLayout (subPanel);
168 subPanel->setLayout (layout);
170 layout->setColumnStretch(0, 0);
171 layout->setColumnMinimumWidth(0, EMPTY_COLUMN_WIDTH);
172 layout->setColumnStretch(1, 0);
173 layout->setColumnMinimumWidth(1, 210);
174 layout->setColumnStretch(2, 0);
175 layout->setColumnMinimumWidth(2, 15);
176 layout->setColumnStretch(3, 1);
177 layout->setColumnMinimumWidth(4, EMPTY_COLUMN_WIDTH);
178 layout->setColumnStretch(4, 0);
180 int rowLeft = 0, rowRight = 0;
181 createControls (layout, rowLeft);
182 createProfileAndScale (layout, rowRight);
184 int row = qMax (rowLeft, rowRight);
185 createPreview (layout, row);
190QRgb DlgSettingsColorFilter::createThread ()
192 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::createThread";
200 if (m_filterThread == 0) {
205 m_filterThread->start();
208 return rgbBackground;
213 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::handleOk";
217 *m_modelColorFilterBefore,
218 *m_modelColorFilterAfter);
226 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::load";
231 if (m_modelColorFilterBefore != 0) {
232 delete m_modelColorFilterBefore;
234 if (m_modelColorFilterAfter != 0) {
235 delete m_modelColorFilterAfter;
243 m_cmbCurveName->clear ();
244 m_cmbCurveName->addItem (AXIS_CURVE_NAME);
246 QStringList::const_iterator itr;
247 for (itr = curveNames.begin (); itr != curveNames.end (); itr++) {
249 QString curveName = *itr;
250 m_cmbCurveName->addItem (curveName);
260void DlgSettingsColorFilter::loadForCurveName()
262 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::loadForCurveName";
265 QString curveName = m_cmbCurveName->currentText();
268 if (!curveName.isEmpty () && m_modelColorFilterAfter != 0) {
271 ColorFilterMode colorFilterMode = m_modelColorFilterAfter->
colorFilterMode(curveName);
272 m_btnIntensity->setChecked (colorFilterMode == COLOR_FILTER_MODE_INTENSITY);
273 m_btnForeground->setChecked (colorFilterMode == COLOR_FILTER_MODE_FOREGROUND);
274 m_btnHue->setChecked (colorFilterMode == COLOR_FILTER_MODE_HUE);
275 m_btnSaturation->setChecked (colorFilterMode == COLOR_FILTER_MODE_SATURATION);
276 m_btnValue->setChecked (colorFilterMode == COLOR_FILTER_MODE_VALUE);
278 m_scenePreview->clear();
280 m_scenePreview->addPixmap (QPixmap::fromImage (m_imagePreview));
282 QRgb rgbBackground = createThread ();
290void DlgSettingsColorFilter::slotCurveName(
const QString & )
292 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotCurveName";
297void DlgSettingsColorFilter::slotDividerHigh (
double xCenter)
299 m_modelColorFilterAfter->
setHigh (m_cmbCurveName->currentText(),
300 xCenter / (
double) PROFILE_SCENE_WIDTH ());
304void DlgSettingsColorFilter::slotDividerLow (
double xCenter)
306 m_modelColorFilterAfter->
setLow (m_cmbCurveName->currentText(),
307 xCenter / (
double) PROFILE_SCENE_WIDTH ());
311void DlgSettingsColorFilter::slotForeground ()
313 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotForeground";
316 COLOR_FILTER_MODE_FOREGROUND);
321void DlgSettingsColorFilter::slotHue ()
323 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotHue";
326 COLOR_FILTER_MODE_HUE);
331void DlgSettingsColorFilter::slotIntensity ()
333 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotIntensity";
336 COLOR_FILTER_MODE_INTENSITY);
341void DlgSettingsColorFilter::slotSaturation ()
343 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotSaturation";
346 COLOR_FILTER_MODE_SATURATION);
359 for (
int xFrom = 0, xTo = xLeft; xFrom < image.width(); xFrom++, xTo++) {
360 for (
int y = 0; y < image.height (); y++) {
362 QColor pixel = image.pixel (xFrom, y);
363 m_imagePreview.setPixel (xTo, y, pixel.rgb());
368 QGraphicsItem *itemPixmap = m_scenePreview->items().at(0);
369 m_scenePreview->removeItem (itemPixmap);
373 m_scenePreview->addPixmap (QPixmap::fromImage (m_imagePreview));
376void DlgSettingsColorFilter::slotValue ()
378 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::slotValue";
381 COLOR_FILTER_MODE_VALUE);
386void DlgSettingsColorFilter::updateHistogram()
388 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettingsColorFilter::updateHistogram";
392 const double PEN_WIDTH = 0.0;
394 QString curveName = m_cmbCurveName->currentText();
396 m_sceneProfile->clear();
416 double logMaxBinCount = qLn (maxBinCount);
422 double count0 = 1.0 + histogramBins [bin - 1];
423 double y0 = (PROFILE_SCENE_HEIGHT () - 1.0) * (1.0 - qLn (count0) / logMaxBinCount);
428 double count1 = 1.0 + histogramBins [bin];
429 double y1 = (PROFILE_SCENE_HEIGHT () - 1.0) * (1.0 - qLn (count1) / logMaxBinCount);
431 QGraphicsLineItem *line =
new QGraphicsLineItem (x0, y0, x1, y1);
432 line->setPen (QPen (QBrush (Qt::black), PEN_WIDTH));
433 m_sceneProfile->addItem (line);
439 PROFILE_SCENE_WIDTH (),
440 PROFILE_SCENE_HEIGHT (),
441 PROFILE_SCENE_HEIGHT () * 2.0 / 3.0,
445 PROFILE_SCENE_HEIGHT (),
446 PROFILE_SCENE_WIDTH (),
447 PROFILE_SCENE_HEIGHT () / 3.0,
452 connect (m_dividerLow, SIGNAL (signalMovedLow (
double)), m_dividerHigh, SLOT (slotOtherMoved(
double)));
453 connect (m_dividerHigh, SIGNAL (signalMovedHigh (
double)), m_dividerLow, SLOT (slotOtherMoved(
double)));
456 connect (m_dividerLow, SIGNAL (signalMovedLow (
double)),
this, SLOT (slotDividerLow (
double)));
457 connect (m_dividerHigh, SIGNAL(signalMovedHigh (
double)),
this, SLOT (slotDividerHigh (
double)));
459 if (m_btnForeground->isChecked()) {
462 m_dividerLow->
setX (m_modelColorFilterAfter->
foregroundLow(curveName), FOREGROUND_MIN, FOREGROUND_MAX);
463 m_dividerHigh->
setX (m_modelColorFilterAfter->
foregroundHigh(curveName), FOREGROUND_MIN, FOREGROUND_MAX);
465 }
else if (m_btnIntensity->isChecked()) {
468 m_dividerLow->
setX (m_modelColorFilterAfter->
intensityLow(curveName), INTENSITY_MIN, INTENSITY_MAX);
469 m_dividerHigh->
setX (m_modelColorFilterAfter->
intensityHigh(curveName), INTENSITY_MIN, INTENSITY_MAX);
471 }
else if (m_btnHue->isChecked()) {
474 m_dividerLow->
setX (m_modelColorFilterAfter->
hueLow(curveName), HUE_MIN, HUE_MAX);
475 m_dividerHigh->
setX (m_modelColorFilterAfter->
hueHigh(curveName), HUE_MIN, HUE_MAX);
477 }
else if (m_btnSaturation->isChecked()) {
480 m_dividerLow->
setX (m_modelColorFilterAfter->
saturationLow(curveName), SATURATION_MIN, SATURATION_MAX);
481 m_dividerHigh->
setX (m_modelColorFilterAfter->
saturationHigh(curveName), SATURATION_MIN, SATURATION_MAX);
483 }
else if (m_btnValue->isChecked()) {
486 m_dividerLow->
setX (m_modelColorFilterAfter->
valueLow(curveName), VALUE_MIN, VALUE_MAX);
487 m_dividerHigh->
setX (m_modelColorFilterAfter->
valueHigh(curveName), VALUE_MIN, VALUE_MAX);
491 ENGAUGE_ASSERT (
false);
495 free (histogramBins);
498void DlgSettingsColorFilter::updatePreview ()
500 LOG4CPP_INFO_S ((*mainCat)) <<
"DlgSettings::updatePreview";
505 QString curveName = m_cmbCurveName->currentText();
507 m_modelColorFilterAfter->
low(curveName),
508 m_modelColorFilterAfter->
high(curveName));
Command for DlgSettingsColorFilter.
Class that generates a histogram according to the current filter.
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.
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...
Abstract base class for all Settings dialogs.
void setCmdMediator(CmdMediator &cmdMediator)
Store CmdMediator for easy access by the leaf class.
CmdMediator & cmdMediator()
Provide access to Document information wrapped inside CmdMediator.
void enableOk(bool enable)
Let leaf subclass control the Ok button.
void finishPanel(QWidget *subPanel)
Add Ok and Cancel buttons to subpanel to get the whole dialog.
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.
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.
double high(const QString &curveName) const
High value of foreground, hue, intensity, saturation or value according to current filter mode.
double low(const QString &curveName) const
Low value of foreground, hue, intensity, saturation or value according to current filter mode normali...
int hueLow(const QString &curveName) const
Get method for hue lower bound.
int hueHigh(const QString &curveName) const
Get method for hue higher bound.
ColorFilterMode colorFilterMode(const QString &curveName) const
Get method for filter mode.
int foregroundHigh(const QString &curveName) const
Get method for foreground higher bound.
int saturationLow(const QString &curveName) const
Get method for saturation lower bound.
int foregroundLow(const QString &curveName) const
Get method for foreground lower bound.
void setHigh(const QString &curveName, double s0To1)
Set the high value for the current filter mode.
int valueLow(const QString &curveName) const
Get method for value low.
int saturationHigh(const QString &curveName) const
Get method for saturation higher bound.
void setColorFilterMode(const QString &curveName, ColorFilterMode colorFilterMode)
Set method for filter mode.
int valueHigh(const QString &curveName) const
Get method for value high.
int intensityHigh(const QString &curveName) const
Get method for intensity higher bound.
void setLow(const QString &curveName, double s0To1)
Set the low value for the current filter mode.
int intensityLow(const QString &curveName) const
Get method for intensity lower bound.
QPixmap pixmap() const
Return the image that is being digitized.
DocumentModelColorFilter modelColorFilter() const
Get method for DocumentModelColorFilter.
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
QString selectedGraphCurve() const
Curve name that is currently selected in m_cmbCurve.
Class that modifies QGraphicsView to automatically expand/shrink the view to fit the window,...
Divider that can be dragged, in a dialog QGraphicsView.
void setX(double x, double xLow, double xHigh)
Set the position by specifying the new x coordinate.
Linear horizontal scale, with the spectrum reflecting the active filter parameter.
void setBackgroundColor(QRgb rgbBackground)
Save the background color for foreground calculations.
void setColorFilterMode(ColorFilterMode colorFilterMode)
Change the gradient type.
Class that modifies QGraphicsView to present a two-dimensional profile, with movable dividers for sel...