Files
HPPA/HPPA/imageControl.cpp
tangchao0503 dac922eb29 打包
使用qrc和rc文件(exe文件图标)管理svg、png等资源
2026-03-25 10:51:00 +08:00

348 lines
9.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "imageControl.h"
#include "RasterLayer.h"
#include <algorithm>
#include <cmath>
ImageControl::ImageControl(QWidget* parent)
: QDialog(parent)
{
ui.setupUi(this);
// Spinbox valueChanged: only sync the paired slider (no render)
connect(ui.spinRed, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinRedValueChanged);
connect(ui.spinGreen, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinGreenValueChanged);
connect(ui.spinBlue, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinBlueValueChanged);
// Spinbox editingFinished: commit on Enter key / focus lost (trigger render)
connect(ui.spinRed, &QDoubleSpinBox::editingFinished, this, &ImageControl::onSpinRedEditingFinished);
connect(ui.spinGreen, &QDoubleSpinBox::editingFinished, this, &ImageControl::onSpinGreenEditingFinished);
connect(ui.spinBlue, &QDoubleSpinBox::editingFinished, this, &ImageControl::onSpinBlueEditingFinished);
// Slider valueChanged: only sync the paired spinbox (no render)
// Slider now represents band index (0 .. N-1)
connect(ui.sliderRed, &QSlider::valueChanged, this, &ImageControl::onSliderRedValueChanged);
connect(ui.sliderGreen, &QSlider::valueChanged, this, &ImageControl::onSliderGreenValueChanged);
connect(ui.sliderBlue, &QSlider::valueChanged, this, &ImageControl::onSliderBlueValueChanged);
// Slider sliderReleased: commit on mouse release (trigger render)
connect(ui.sliderRed, &QSlider::sliderReleased, this, &ImageControl::onSliderRedReleased);
connect(ui.sliderGreen, &QSlider::sliderReleased, this, &ImageControl::onSliderGreenReleased);
connect(ui.sliderBlue, &QSlider::sliderReleased, this, &ImageControl::onSliderBlueReleased);
// Connect preset buttons
connect(ui.btnTrueColor, &QPushButton::clicked, this, &ImageControl::onTrueColorClicked);
connect(ui.btnColorInfrared, &QPushButton::clicked, this, &ImageControl::onColorInfraredClicked);
// Spinbox only commits on Enter, not on every keystroke
ui.spinRed->setKeyboardTracking(false);
ui.spinGreen->setKeyboardTracking(false);
ui.spinBlue->setKeyboardTracking(false);
ui.groupAdjustments->setStyleSheet(R"(
QDoubleSpinBox {
border: 1px solid #999;
border-radius: 4px;
padding: 2px 20px 2px 6px; /* <20>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>ť */
background: #0e1c4c;
selection-background-color: #0078d7;
font-size: 12px;
color:#ACCDFF ;
}
QDoubleSpinBox::up-button {
subcontrol-origin: border;
subcontrol-position: top right;
width: 16px;
border-left: 1px solid #ccc;
}
QDoubleSpinBox::down-button {
subcontrol-origin: border;
subcontrol-position: bottom right;
width: 16px;
border-left: 1px solid #ccc;
}
QDoubleSpinBox::up-arrow {
image: url(:/svg/resources/icons/svg/arrow_up.svg);
width: 10px;
height: 10px;
}
QDoubleSpinBox::down-arrow {
image: url(:/svg/resources/icons/svg/arrow_down.svg);
width: 10px;
height: 10px;
}
QDoubleSpinBox::up-button:hover,
QDoubleSpinBox::down-button:hover {
background: #e6f2ff;
}
QDoubleSpinBox::up-button:pressed,
QDoubleSpinBox::down-button:pressed {
background: #cce4ff;
}
)");
}
ImageControl::~ImageControl()
{
}
void ImageControl::setActiveLayer(RasterLayer* layer)
{
m_activeLayer = layer;
if (!layer) {
setEnabled(false);
m_wavelengths.clear();
return;
}
setEnabled(true);
// Get band wavelengths from the layer's header
m_wavelengths = layer->bandWavelengths();
std::sort(m_wavelengths.begin(), m_wavelengths.end());
if (m_wavelengths.empty()) {
setEnabled(false);
return;
}
m_minWave = m_wavelengths.front();
m_maxWave = m_wavelengths.back();
// Compute spinbox step as the average wavelength interval between adjacent bands
double step = 1.0;
if (m_wavelengths.size() >= 2) {
step = (m_maxWave - m_minWave) / (m_wavelengths.size() - 1);
}
blockAllSignals(true);
// Configure spinbox ranges and step
ui.spinRed->setMinimum(m_minWave);
ui.spinRed->setMaximum(m_maxWave);
ui.spinRed->setSingleStep(step);
ui.spinGreen->setMinimum(m_minWave);
ui.spinGreen->setMaximum(m_maxWave);
ui.spinGreen->setSingleStep(step);
ui.spinBlue->setMinimum(m_minWave);
ui.spinBlue->setMaximum(m_maxWave);
ui.spinBlue->setSingleStep(step);
// Slider now represents band index (0 .. N-1), step = 1
int maxIdx = static_cast<int>(m_wavelengths.size()) - 1;
ui.sliderRed->setMinimum(0);
ui.sliderRed->setMaximum(maxIdx);
ui.sliderRed->setSingleStep(1);
ui.sliderRed->setPageStep(1);
ui.sliderGreen->setMinimum(0);
ui.sliderGreen->setMaximum(maxIdx);
ui.sliderGreen->setSingleStep(1);
ui.sliderGreen->setPageStep(1);
ui.sliderBlue->setMinimum(0);
ui.sliderBlue->setMaximum(maxIdx);
ui.sliderBlue->setSingleStep(1);
ui.sliderBlue->setPageStep(1);
// Set current values from layer's render params
auto params = layer->currentRenderParams();
int rIdx = nearestBandIndex(params.rWave);
int gIdx = nearestBandIndex(params.gWave);
int bIdx = nearestBandIndex(params.bWave);
ui.spinRed->setValue(m_wavelengths[rIdx]);
ui.spinGreen->setValue(m_wavelengths[gIdx]);
ui.spinBlue->setValue(m_wavelengths[bIdx]);
ui.sliderRed->setValue(rIdx);
ui.sliderGreen->setValue(gIdx);
ui.sliderBlue->setValue(bIdx);
blockAllSignals(false);
}
RasterLayer* ImageControl::activeLayer() const
{
return m_activeLayer;
}
int ImageControl::nearestBandIndex(double wave) const
{
if (m_wavelengths.empty()) return 0;
int best = 0;
double bestDiff = std::abs(m_wavelengths[0] - wave);
for (int i = 1; i < static_cast<int>(m_wavelengths.size()); ++i) {
double d = std::abs(m_wavelengths[i] - wave);
if (d < bestDiff) {
bestDiff = d;
best = i;
}
}
return best;
}
void ImageControl::setControlsToBandIndex(QDoubleSpinBox* spin, QSlider* slider, int idx)
{
if (idx < 0 || idx >= static_cast<int>(m_wavelengths.size())) return;
double wv = m_wavelengths[idx];
spin->blockSignals(true);
spin->setValue(wv);
spin->blockSignals(false);
slider->blockSignals(true);
slider->setValue(idx);
slider->blockSignals(false);
}
// --- Spinbox valueChanged: snap to nearest band, sync slider, no render ---
void ImageControl::onSpinRedValueChanged(double val)
{
int idx = nearestBandIndex(val);
ui.sliderRed->blockSignals(true);
ui.sliderRed->setValue(idx);
ui.sliderRed->blockSignals(false);
}
void ImageControl::onSpinGreenValueChanged(double val)
{
int idx = nearestBandIndex(val);
ui.sliderGreen->blockSignals(true);
ui.sliderGreen->setValue(idx);
ui.sliderGreen->blockSignals(false);
}
void ImageControl::onSpinBlueValueChanged(double val)
{
int idx = nearestBandIndex(val);
ui.sliderBlue->blockSignals(true);
ui.sliderBlue->setValue(idx);
ui.sliderBlue->blockSignals(false);
}
// --- Slider valueChanged: map band index to wavelength, sync spinbox, no render ---
void ImageControl::onSliderRedValueChanged(int val)
{
if (val < 0 || val >= static_cast<int>(m_wavelengths.size())) return;
ui.spinRed->blockSignals(true);
ui.spinRed->setValue(m_wavelengths[val]);
ui.spinRed->blockSignals(false);
}
void ImageControl::onSliderGreenValueChanged(int val)
{
if (val < 0 || val >= static_cast<int>(m_wavelengths.size())) return;
ui.spinGreen->blockSignals(true);
ui.spinGreen->setValue(m_wavelengths[val]);
ui.spinGreen->blockSignals(false);
}
void ImageControl::onSliderBlueValueChanged(int val)
{
if (val < 0 || val >= static_cast<int>(m_wavelengths.size())) return;
ui.spinBlue->blockSignals(true);
ui.spinBlue->setValue(m_wavelengths[val]);
ui.spinBlue->blockSignals(false);
}
// --- Spinbox editingFinished: snap to nearest band wavelength, then commit ---
void ImageControl::onSpinRedEditingFinished()
{
int idx = nearestBandIndex(ui.spinRed->value());
setControlsToBandIndex(ui.spinRed, ui.sliderRed, idx);
emitBandChange();
}
void ImageControl::onSpinGreenEditingFinished()
{
int idx = nearestBandIndex(ui.spinGreen->value());
setControlsToBandIndex(ui.spinGreen, ui.sliderGreen, idx);
emitBandChange();
}
void ImageControl::onSpinBlueEditingFinished()
{
int idx = nearestBandIndex(ui.spinBlue->value());
setControlsToBandIndex(ui.spinBlue, ui.sliderBlue, idx);
emitBandChange();
}
// --- Slider sliderReleased: commit on mouse release ---
void ImageControl::onSliderRedReleased()
{
emitBandChange();
}
void ImageControl::onSliderGreenReleased()
{
emitBandChange();
}
void ImageControl::onSliderBlueReleased()
{
emitBandChange();
}
// --- Preset buttons ---
void ImageControl::onTrueColorClicked()
{
blockAllSignals(true);
int rIdx = nearestBandIndex(665.0);
int gIdx = nearestBandIndex(560.0);
int bIdx = nearestBandIndex(490.0);
setControlsToBandIndex(ui.spinRed, ui.sliderRed, rIdx);
setControlsToBandIndex(ui.spinGreen, ui.sliderGreen, gIdx);
setControlsToBandIndex(ui.spinBlue, ui.sliderBlue, bIdx);
blockAllSignals(false);
emitBandChange();
}
void ImageControl::onColorInfraredClicked()
{
blockAllSignals(true);
int rIdx = nearestBandIndex(800.0);
int gIdx = nearestBandIndex(665.0);
int bIdx = nearestBandIndex(560.0);
setControlsToBandIndex(ui.spinRed, ui.sliderRed, rIdx);
setControlsToBandIndex(ui.spinGreen, ui.sliderGreen, gIdx);
setControlsToBandIndex(ui.spinBlue, ui.sliderBlue, bIdx);
blockAllSignals(false);
emitBandChange();
}
void ImageControl::emitBandChange()
{
double r = ui.spinRed->value();
double g = ui.spinGreen->value();
double b = ui.spinBlue->value();
// Update active layer's stored render params
if (m_activeLayer) {
auto params = m_activeLayer->currentRenderParams();
params.rWave = r;
params.gWave = g;
params.bWave = b;
m_activeLayer->setCurrentRenderParams(params);
}
emit bandSelectionChanged(r, g, b);
}
void ImageControl::blockAllSignals(bool block)
{
ui.spinRed->blockSignals(block);
ui.spinGreen->blockSignals(block);
ui.spinBlue->blockSignals(block);
ui.sliderRed->blockSignals(block);
ui.sliderGreen->blockSignals(block);
ui.sliderBlue->blockSignals(block);
}