File indexing completed on 2024-04-14 14:10:36
0001 /* 0002 SPDX-FileCopyrightText: 2015 Jasem Mutlaq <mutlaqja@ikarustech.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "fitshistogrameditor.h" 0008 0009 #include "fits_debug.h" 0010 0011 #include "Options.h" 0012 #include "fitsdata.h" 0013 #include "fitstab.h" 0014 #include "fitsview.h" 0015 #include "fitsviewer.h" 0016 0017 #include <KMessageBox> 0018 0019 #include <QtConcurrent> 0020 #include <type_traits> 0021 0022 histogramUI::histogramUI(QDialog * parent) : QDialog(parent) 0023 { 0024 setupUi(parent); 0025 setModal(false); 0026 } 0027 0028 FITSHistogramEditor::FITSHistogramEditor(QWidget * parent) : QDialog(parent) 0029 { 0030 ui = new histogramUI(this); 0031 0032 minBoxes << ui->minREdit << ui->minGEdit << ui->minBEdit; 0033 maxBoxes << ui->maxREdit << ui->maxGEdit << ui->maxBEdit; 0034 sliders << ui->redSlider << ui->greenSlider << ui->blueSlider; 0035 0036 ui->histogramPlot->setProperty("linear", !Options::nonLinearHistogram()); 0037 0038 connect(ui->applyB, &QPushButton::clicked, this, &FITSHistogramEditor::applyScale); 0039 // connect(ui->hideSaturated, &QCheckBox::stateChanged, [this]() 0040 // { 0041 // m_ImageData->resetHistogram(); 0042 // m_ImageData->constructHistogram(); 0043 // ui->histogramPlot->syncGUI(); 0044 // }); 0045 0046 rgbWidgets.resize(3); 0047 rgbWidgets[RED_CHANNEL] << ui->RLabel << ui->minREdit << ui->redSlider 0048 << ui->maxREdit; 0049 rgbWidgets[GREEN_CHANNEL] << ui->GLabel << ui->minGEdit << ui->greenSlider 0050 << ui->maxGEdit; 0051 rgbWidgets[BLUE_CHANNEL] << ui->BLabel << ui->minBEdit << ui->blueSlider 0052 << ui->maxBEdit; 0053 0054 for (int i = 0; i < 3; i++) 0055 { 0056 // Box --> Slider 0057 QVector<QWidget *> w = rgbWidgets[i]; 0058 connect(qobject_cast<QDoubleSpinBox *>(w[1]), &QDoubleSpinBox::editingFinished, [this, i, w]() 0059 { 0060 double value = qobject_cast<QDoubleSpinBox *>(w[1])->value(); 0061 w[2]->blockSignals(true); 0062 qobject_cast<ctkRangeSlider *>(w[2])->setMinimumPosition((value - m_ImageData->getMin(i))*sliderScale[i]); 0063 w[2]->blockSignals(false); 0064 }); 0065 connect(qobject_cast<QDoubleSpinBox *>(w[3]), &QDoubleSpinBox::editingFinished, [this, i, w]() 0066 { 0067 double value = qobject_cast<QDoubleSpinBox *>(w[3])->value(); 0068 w[2]->blockSignals(true); 0069 qobject_cast<ctkRangeSlider *>(w[2])->setMaximumPosition((value - m_ImageData->getMin(i) - sliderTick[i])*sliderScale[i]); 0070 w[2]->blockSignals(false); 0071 }); 0072 0073 // Slider --> Box 0074 connect(qobject_cast<ctkRangeSlider *>(w[2]), &ctkRangeSlider::minimumValueChanged, [this, i, w](int position) 0075 { 0076 qobject_cast<QDoubleSpinBox *>(w[1])->setValue(m_ImageData->getMin(i) + (position / sliderScale[i])); 0077 }); 0078 connect(qobject_cast<ctkRangeSlider *>(w[2]), &ctkRangeSlider::maximumValueChanged, [this, i, w](int position) 0079 { 0080 qobject_cast<QDoubleSpinBox *>(w[3])->setValue(m_ImageData->getMin(i) + sliderTick[i] + (position / sliderScale[i])); 0081 }); 0082 } 0083 } 0084 0085 void FITSHistogramEditor::showEvent(QShowEvent * event) 0086 { 0087 Q_UNUSED(event) 0088 // if (!Options::nonLinearHistogram() && !m_ImageData->isHistogramConstructed()) 0089 // m_ImageData->constructHistogram(); 0090 0091 syncGUI(); 0092 0093 } 0094 0095 //void FITSHistogramEditor::createNonLinearHistogram() 0096 //{ 0097 // ui->histogramPlot->createNonLinearHistogram(); 0098 //} 0099 0100 void FITSHistogramEditor::resizePlot() 0101 { 0102 ui->histogramPlot->resizePlot(); 0103 } 0104 0105 void FITSHistogramEditor::syncGUI() 0106 { 0107 if (isGUISynced) 0108 return; 0109 0110 sliderTick.clear(); 0111 sliderScale.clear(); 0112 for (int n = 0; n < m_ImageData->channels(); n++) 0113 { 0114 sliderTick << fabs(m_ImageData->getMax(n) - m_ImageData->getMin(n)) / 99.0; 0115 sliderScale << 99.0 / (m_ImageData->getMax(n) - m_ImageData->getMin(n) - sliderTick[n]); 0116 } 0117 0118 ui->histogramPlot->syncGUI(); 0119 0120 bool isColor = m_ImageData->channels() > 1; 0121 // R/K is always enabled 0122 for (auto w : rgbWidgets[RED_CHANNEL]) 0123 w->setEnabled(true); 0124 // G Channel 0125 for (auto w : rgbWidgets[GREEN_CHANNEL]) 0126 w->setEnabled(isColor); 0127 // B Channel 0128 for (auto w : rgbWidgets[BLUE_CHANNEL]) 0129 w->setEnabled(isColor); 0130 0131 ui->meanEdit->setText(QString::number(m_ImageData->getMean())); 0132 ui->medianEdit->setText(QString::number(m_ImageData->getMedian())); 0133 0134 for (int n = 0; n < m_ImageData->channels(); n++) 0135 { 0136 double median = m_ImageData->getMedian(n); 0137 0138 if (median > 100) 0139 numDecimals << 0; 0140 else if (median > 1) 0141 numDecimals << 2; 0142 else if (median > .01) 0143 numDecimals << 4; 0144 else if (median > .0001) 0145 numDecimals << 6; 0146 else 0147 numDecimals << 10; 0148 0149 minBoxes[n]->setDecimals(numDecimals[n]); 0150 minBoxes[n]->setSingleStep(fabs(m_ImageData->getMax(n) - m_ImageData->getMin(n)) / 20.0); 0151 minBoxes[n]->setMinimum(m_ImageData->getMin(n)); 0152 minBoxes[n]->setMaximum(m_ImageData->getMax(n) - sliderTick[n]); 0153 minBoxes[n]->setValue(m_ImageData->getMin(n) + (sliders[n]->minimumValue() / sliderScale[n])); 0154 0155 maxBoxes[n]->setDecimals(numDecimals[n]); 0156 maxBoxes[n]->setSingleStep(fabs(m_ImageData->getMax(n) - m_ImageData->getMin(n)) / 20.0); 0157 maxBoxes[n]->setMinimum(m_ImageData->getMin(n) + sliderTick[n]); 0158 maxBoxes[n]->setMaximum(m_ImageData->getMax(n)); 0159 maxBoxes[n]->setValue(m_ImageData->getMin(n) + sliderTick[n] + (sliders[n]->maximumValue() / sliderScale[n])); 0160 } 0161 0162 ui->histogramPlot->syncGUI(); 0163 0164 isGUISynced = true; 0165 } 0166 0167 0168 0169 void FITSHistogramEditor::applyScale() 0170 { 0171 QVector<double> min, max; 0172 0173 min << minBoxes[0]->value() << minBoxes[1]->value() << minBoxes[2]->value(); 0174 max << maxBoxes[0]->value() << maxBoxes[1]->value() << maxBoxes[2]->value(); 0175 0176 // if (ui->logR->isChecked()) 0177 // type = FITS_LOG; 0178 // else 0179 type = FITS_LINEAR; 0180 emit newHistogramCommand(new FITSHistogramCommand(m_ImageData, this, type, min, max)); 0181 } 0182 0183 void FITSHistogramEditor::applyFilter(FITSScale ftype) 0184 { 0185 QVector<double> min, max; 0186 min.append(ui->minREdit->value()); 0187 type = ftype; 0188 0189 emit newHistogramCommand(new FITSHistogramCommand(m_ImageData, this, type, min, max)); 0190 } 0191 0192 void FITSHistogramEditor::setImageData(const QSharedPointer<FITSData> &data) 0193 { 0194 m_ImageData = data; 0195 ui->histogramPlot->setImageData(data); 0196 0197 connect(m_ImageData.data(), &FITSData::dataChanged, [this] 0198 { 0199 isGUISynced = false; 0200 syncGUI(); 0201 }); 0202 }