Kstars

fitshistogrameditor.cpp
1/*
2 SPDX-FileCopyrightText: 2015 Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "fitshistogrameditor.h"
8
9#include "fits_debug.h"
10
11#include "Options.h"
12#include "fitsdata.h"
13#include "fitstab.h"
14#include "fitsview.h"
15#include "fitsviewer.h"
16
17#include <KMessageBox>
18
19#include <QtConcurrent>
20#include <type_traits>
21
22histogramUI::histogramUI(QDialog * parent) : QDialog(parent)
23{
24 setupUi(parent);
25 setModal(false);
26}
27
28FITSHistogramEditor::FITSHistogramEditor(QWidget * parent) : QDialog(parent)
29{
30 ui = new histogramUI(this);
31
32 minBoxes << ui->minREdit << ui->minGEdit << ui->minBEdit;
33 maxBoxes << ui->maxREdit << ui->maxGEdit << ui->maxBEdit;
34 sliders << ui->redSlider << ui->greenSlider << ui->blueSlider;
35
36 ui->histogramPlot->setProperty("linear", !Options::nonLinearHistogram());
37
38 connect(ui->applyB, &QPushButton::clicked, this, &FITSHistogramEditor::applyScale);
39 // connect(ui->hideSaturated, &QCheckBox::stateChanged, [this]()
40 // {
41 // m_ImageData->resetHistogram();
42 // m_ImageData->constructHistogram();
43 // ui->histogramPlot->syncGUI();
44 // });
45
46 rgbWidgets.resize(3);
47 rgbWidgets[RED_CHANNEL] << ui->RLabel << ui->minREdit << ui->redSlider
48 << ui->maxREdit;
49 rgbWidgets[GREEN_CHANNEL] << ui->GLabel << ui->minGEdit << ui->greenSlider
50 << ui->maxGEdit;
51 rgbWidgets[BLUE_CHANNEL] << ui->BLabel << ui->minBEdit << ui->blueSlider
52 << ui->maxBEdit;
53
54 for (int i = 0; i < 3; i++)
55 {
56 // Box --> Slider
57 QVector<QWidget *> w = rgbWidgets[i];
58 connect(qobject_cast<QDoubleSpinBox *>(w[1]), &QDoubleSpinBox::editingFinished, [this, i, w]()
59 {
60 double value = qobject_cast<QDoubleSpinBox *>(w[1])->value();
61 w[2]->blockSignals(true);
62 qobject_cast<ctkRangeSlider *>(w[2])->setMinimumPosition((value - m_ImageData->getMin(i))*sliderScale[i]);
63 w[2]->blockSignals(false);
64 });
65 connect(qobject_cast<QDoubleSpinBox *>(w[3]), &QDoubleSpinBox::editingFinished, [this, i, w]()
66 {
67 double value = qobject_cast<QDoubleSpinBox *>(w[3])->value();
68 w[2]->blockSignals(true);
69 qobject_cast<ctkRangeSlider *>(w[2])->setMaximumPosition((value - m_ImageData->getMin(i) - sliderTick[i])*sliderScale[i]);
70 w[2]->blockSignals(false);
71 });
72
73 // Slider --> Box
74 connect(qobject_cast<ctkRangeSlider *>(w[2]), &ctkRangeSlider::minimumValueChanged, [this, i, w](int position)
75 {
76 qobject_cast<QDoubleSpinBox *>(w[1])->setValue(m_ImageData->getMin(i) + (position / sliderScale[i]));
77 });
78 connect(qobject_cast<ctkRangeSlider *>(w[2]), &ctkRangeSlider::maximumValueChanged, [this, i, w](int position)
79 {
80 qobject_cast<QDoubleSpinBox *>(w[3])->setValue(m_ImageData->getMin(i) + sliderTick[i] + (position / sliderScale[i]));
81 });
82 }
83}
84
85void FITSHistogramEditor::showEvent(QShowEvent * event)
86{
87 Q_UNUSED(event)
88 // if (!Options::nonLinearHistogram() && !m_ImageData->isHistogramConstructed())
89 // m_ImageData->constructHistogram();
90
91 syncGUI();
92
93}
94
95//void FITSHistogramEditor::createNonLinearHistogram()
96//{
97// ui->histogramPlot->createNonLinearHistogram();
98//}
99
100void FITSHistogramEditor::resizePlot()
101{
102 ui->histogramPlot->resizePlot();
103}
104
105void FITSHistogramEditor::syncGUI()
106{
107 if (isGUISynced)
108 return;
109
110 sliderTick.clear();
111 sliderScale.clear();
112 for (int n = 0; n < m_ImageData->channels(); n++)
113 {
114 sliderTick << fabs(m_ImageData->getMax(n) - m_ImageData->getMin(n)) / 99.0;
115 sliderScale << 99.0 / (m_ImageData->getMax(n) - m_ImageData->getMin(n) - sliderTick[n]);
116 }
117
118 ui->histogramPlot->syncGUI();
119
120 bool isColor = m_ImageData->channels() > 1;
121 // R/K is always enabled
122 for (auto w : rgbWidgets[RED_CHANNEL])
123 w->setEnabled(true);
124 // G Channel
125 for (auto w : rgbWidgets[GREEN_CHANNEL])
126 w->setEnabled(isColor);
127 // B Channel
128 for (auto w : rgbWidgets[BLUE_CHANNEL])
129 w->setEnabled(isColor);
130
131 ui->meanEdit->setText(QString::number(m_ImageData->getMean()));
132 ui->medianEdit->setText(QString::number(m_ImageData->getMedian()));
133
134 for (int n = 0; n < m_ImageData->channels(); n++)
135 {
136 double median = m_ImageData->getMedian(n);
137
138 if (median > 100)
139 numDecimals << 0;
140 else if (median > 1)
141 numDecimals << 2;
142 else if (median > .01)
143 numDecimals << 4;
144 else if (median > .0001)
145 numDecimals << 6;
146 else
147 numDecimals << 10;
148
149 minBoxes[n]->setDecimals(numDecimals[n]);
150 minBoxes[n]->setSingleStep(fabs(m_ImageData->getMax(n) - m_ImageData->getMin(n)) / 20.0);
151 minBoxes[n]->setMinimum(m_ImageData->getMin(n));
152 minBoxes[n]->setMaximum(m_ImageData->getMax(n) - sliderTick[n]);
153 minBoxes[n]->setValue(m_ImageData->getMin(n) + (sliders[n]->minimumValue() / sliderScale[n]));
154
155 maxBoxes[n]->setDecimals(numDecimals[n]);
156 maxBoxes[n]->setSingleStep(fabs(m_ImageData->getMax(n) - m_ImageData->getMin(n)) / 20.0);
157 maxBoxes[n]->setMinimum(m_ImageData->getMin(n) + sliderTick[n]);
158 maxBoxes[n]->setMaximum(m_ImageData->getMax(n));
159 maxBoxes[n]->setValue(m_ImageData->getMin(n) + sliderTick[n] + (sliders[n]->maximumValue() / sliderScale[n]));
160 }
161
162 ui->histogramPlot->syncGUI();
163
164 isGUISynced = true;
165}
166
167
168
169void FITSHistogramEditor::applyScale()
170{
171 QVector<double> min, max;
172
173 min << minBoxes[0]->value() << minBoxes[1]->value() << minBoxes[2]->value();
174 max << maxBoxes[0]->value() << maxBoxes[1]->value() << maxBoxes[2]->value();
175
176 // if (ui->logR->isChecked())
177 // type = FITS_LOG;
178 // else
179 type = FITS_LINEAR;
180 emit newHistogramCommand(new FITSHistogramCommand(m_ImageData, this, type, min, max));
181}
182
183void FITSHistogramEditor::applyFilter(FITSScale ftype)
184{
185 QVector<double> min, max;
186 min.append(ui->minREdit->value());
187 type = ftype;
188
189 emit newHistogramCommand(new FITSHistogramCommand(m_ImageData, this, type, min, max));
190}
191
192void FITSHistogramEditor::setImageData(const QSharedPointer<FITSData> &data)
193{
194 m_ImageData = data;
195 ui->histogramPlot->setImageData(data);
196
197 connect(m_ImageData.data(), &FITSData::dataChanged, [this]
198 {
199 isGUISynced = false;
200 syncGUI();
201 });
202}
void minimumValueChanged(int min)
This signal is emitted when the slider minimum value has changed, with the new slider value as argume...
void maximumValueChanged(int max)
This signal is emitted when the slider maximum value has changed, with the new slider value as argume...
void clicked(bool checked)
void editingFinished()
void append(QList< T > &&value)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T * data() const const
QString number(double n, char format, int precision)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
virtual bool event(QEvent *event) override
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 29 2024 11:57:48 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.