完成功能:改变图像显示的rgb波段;
1、可改变图像显示波段,当修改完成参数时实时刷新图像; 2、TOC中切换选中的多图层时,刷新渲染信息; 3、界面中保存图像的波长信息,参数修改时的选项就是准确的波长信息;
This commit is contained in:
@ -483,10 +483,6 @@ sizePolicy1.setHeightForWidth(graphicsView_delete->sizePolicy().hasHeightForWidt
|
|||||||
initControlTabwidget();
|
initControlTabwidget();
|
||||||
m_tabManager = new TabManager(ui.controlTabWidget, this);
|
m_tabManager = new TabManager(ui.controlTabWidget, this);
|
||||||
|
|
||||||
// Connect ImageControl band change to re-render (m_ic created in initControlTabwidget)
|
|
||||||
connect(m_ic, SIGNAL(bandSelectionChanged(double,double,double)),
|
|
||||||
this, SLOT(onBandSelectionChanged(double,double,double)));
|
|
||||||
|
|
||||||
//3D模型看板
|
//3D模型看板
|
||||||
ui.mDockWidgetSimulator->setTile(QString::fromLocal8Bit("3D模型"));
|
ui.mDockWidgetSimulator->setTile(QString::fromLocal8Bit("3D模型"));
|
||||||
//ui.mDockWidgetSimulator->show();
|
//ui.mDockWidgetSimulator->show();
|
||||||
@ -726,6 +722,8 @@ void HPPA::initControlTabwidget()
|
|||||||
//图像控制
|
//图像控制
|
||||||
m_ic = new ImageControl();
|
m_ic = new ImageControl();
|
||||||
m_ic->setWindowFlags(Qt::Widget);
|
m_ic->setWindowFlags(Qt::Widget);
|
||||||
|
connect(m_ic, SIGNAL(bandSelectionChanged(double, double, double)),
|
||||||
|
this, SLOT(onBandSelectionChanged(double, double, double)));
|
||||||
ui.controlTabWidget->addTab(m_ic, QString::fromLocal8Bit("图像控制"));
|
ui.controlTabWidget->addTab(m_ic, QString::fromLocal8Bit("图像控制"));
|
||||||
|
|
||||||
//升降桌dock
|
//升降桌dock
|
||||||
|
|||||||
@ -220,12 +220,28 @@ void Mapcavas::setLayers(RasterLayer* layer)
|
|||||||
m_rasterLayer = layer;
|
m_rasterLayer = layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RasterLayer* Mapcavas::rasterLayer() const
|
||||||
|
{
|
||||||
|
return m_rasterLayer;
|
||||||
|
}
|
||||||
|
|
||||||
// new: refresh the map by rendering using the RasterLayer's render method
|
// new: refresh the map by rendering using the RasterLayer's render method
|
||||||
void Mapcavas::freshmap()
|
void Mapcavas::freshmap()
|
||||||
{
|
{
|
||||||
if (!m_rasterLayer) return;
|
if (!m_rasterLayer) return;
|
||||||
|
|
||||||
RasterLayer::RenderParams params; // default params; could be extended
|
RasterLayer::RenderParams params = m_rasterLayer->currentRenderParams();
|
||||||
|
QImage img = m_rasterLayer->render(params);
|
||||||
|
if (img.isNull()) return;
|
||||||
|
|
||||||
|
QPixmap pm = QPixmap::fromImage(img);
|
||||||
|
SetImage(&pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mapcavas::freshmap(const RasterLayer::RenderParams& params)
|
||||||
|
{
|
||||||
|
if (!m_rasterLayer) return;
|
||||||
|
|
||||||
QImage img = m_rasterLayer->render(params);
|
QImage img = m_rasterLayer->render(params);
|
||||||
if (img.isNull()) return;
|
if (img.isNull()) return;
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,7 @@
|
|||||||
#include "QGraphicsView"
|
#include "QGraphicsView"
|
||||||
#include "qlabel.h"
|
#include "qlabel.h"
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include "RasterLayer.h"
|
||||||
class RasterLayer; // forward
|
|
||||||
|
|
||||||
class Mapcavas : public QGraphicsView
|
class Mapcavas : public QGraphicsView
|
||||||
{
|
{
|
||||||
@ -46,6 +45,9 @@ public:
|
|||||||
// new: set raster layer and refresh map
|
// new: set raster layer and refresh map
|
||||||
void setLayers(RasterLayer* layer);
|
void setLayers(RasterLayer* layer);
|
||||||
void freshmap();
|
void freshmap();
|
||||||
|
void freshmap(const RasterLayer::RenderParams& params);
|
||||||
|
|
||||||
|
RasterLayer* rasterLayer() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QGraphicsScene *m_qtGraphicsScene;
|
QGraphicsScene *m_qtGraphicsScene;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "RasterLayer.h"
|
#include "RasterLayer.h"
|
||||||
#include "RasterDataProvider.h"
|
#include "RasterDataProvider.h"
|
||||||
#include "RasterRenderer.h"
|
#include "RasterRenderer.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
RasterLayer::RasterLayer(const QString& name, const QString& uri)
|
RasterLayer::RasterLayer(const QString& name, const QString& uri)
|
||||||
: MapLayer(name, uri)
|
: MapLayer(name, uri)
|
||||||
@ -84,3 +85,32 @@ QImage RasterLayer::render(const RenderParams& params)
|
|||||||
p.maxValue = params.maxValue;
|
p.maxValue = params.maxValue;
|
||||||
return m_renderer->render(p);
|
return m_renderer->render(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RasterLayer::RenderParams RasterLayer::currentRenderParams() const
|
||||||
|
{
|
||||||
|
return m_currentParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterLayer::setCurrentRenderParams(const RenderParams& params)
|
||||||
|
{
|
||||||
|
m_currentParams = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RasterLayer::wavelengthRange(double& minWave, double& maxWave) const
|
||||||
|
{
|
||||||
|
auto wl = bandWavelengths();
|
||||||
|
if (wl.empty()) return false;
|
||||||
|
minWave = *std::min_element(wl.begin(), wl.end());
|
||||||
|
maxWave = *std::max_element(wl.begin(), wl.end());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> RasterLayer::bandWavelengths() const
|
||||||
|
{
|
||||||
|
if (!m_provider) {
|
||||||
|
// need to open provider to read wavelengths - cast away const for lazy init
|
||||||
|
auto* self = const_cast<RasterLayer*>(this);
|
||||||
|
if (!self->openDataProvider()) return {};
|
||||||
|
}
|
||||||
|
return m_provider->bandWavelengths();
|
||||||
|
}
|
||||||
|
|||||||
@ -38,7 +38,18 @@ public:
|
|||||||
// Render the raster using current provider and renderer. Returns an empty QImage on failure.
|
// Render the raster using current provider and renderer. Returns an empty QImage on failure.
|
||||||
QImage render(const RenderParams& params);
|
QImage render(const RenderParams& params);
|
||||||
|
|
||||||
|
// Current render params stored per layer
|
||||||
|
RenderParams currentRenderParams() const;
|
||||||
|
void setCurrentRenderParams(const RenderParams& params);
|
||||||
|
|
||||||
|
// Get wavelength range from data provider (min, max). Returns false if unavailable.
|
||||||
|
bool wavelengthRange(double& minWave, double& maxWave) const;
|
||||||
|
|
||||||
|
// Get all band wavelengths
|
||||||
|
std::vector<double> bandWavelengths() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<RasterDataProvider> m_provider;
|
std::unique_ptr<RasterDataProvider> m_provider;
|
||||||
std::unique_ptr<RasterRenderer> m_renderer;
|
std::unique_ptr<RasterRenderer> m_renderer;
|
||||||
|
RenderParams m_currentParams;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,24 +1,42 @@
|
|||||||
#include "imageControl.h"
|
#include "imageControl.h"
|
||||||
#include "RasterLayer.h"
|
#include "RasterLayer.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
ImageControl::ImageControl(QWidget* parent)
|
ImageControl::ImageControl(QWidget* parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
{
|
{
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
|
|
||||||
// Connect spinboxes
|
// Spinbox valueChanged: only sync the paired slider (no render)
|
||||||
connect(ui.spinRed, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinRedChanged);
|
connect(ui.spinRed, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinRedValueChanged);
|
||||||
connect(ui.spinGreen, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinGreenChanged);
|
connect(ui.spinGreen, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinGreenValueChanged);
|
||||||
connect(ui.spinBlue, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinBlueChanged);
|
connect(ui.spinBlue, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinBlueValueChanged);
|
||||||
|
|
||||||
// Connect sliders
|
// Spinbox editingFinished: commit on Enter key / focus lost (trigger render)
|
||||||
connect(ui.sliderRed, &QSlider::valueChanged, this, &ImageControl::onSliderRedChanged);
|
connect(ui.spinRed, &QDoubleSpinBox::editingFinished, this, &ImageControl::onSpinRedEditingFinished);
|
||||||
connect(ui.sliderGreen, &QSlider::valueChanged, this, &ImageControl::onSliderGreenChanged);
|
connect(ui.spinGreen, &QDoubleSpinBox::editingFinished, this, &ImageControl::onSpinGreenEditingFinished);
|
||||||
connect(ui.sliderBlue, &QSlider::valueChanged, this, &ImageControl::onSliderBlueChanged);
|
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 preset buttons
|
||||||
connect(ui.btnTrueColor, &QPushButton::clicked, this, &ImageControl::onTrueColorClicked);
|
connect(ui.btnTrueColor, &QPushButton::clicked, this, &ImageControl::onTrueColorClicked);
|
||||||
connect(ui.btnColorInfrared, &QPushButton::clicked, this, &ImageControl::onColorInfraredClicked);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageControl::~ImageControl()
|
ImageControl::~ImageControl()
|
||||||
@ -31,46 +49,71 @@ void ImageControl::setActiveLayer(RasterLayer* layer)
|
|||||||
|
|
||||||
if (!layer) {
|
if (!layer) {
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
|
m_wavelengths.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setEnabled(true);
|
setEnabled(true);
|
||||||
|
|
||||||
// Get wavelength range from the layer
|
// Get band wavelengths from the layer's header
|
||||||
double minW = 374.5, maxW = 948.1;
|
m_wavelengths = layer->bandWavelengths();
|
||||||
if (layer->wavelengthRange(minW, maxW)) {
|
std::sort(m_wavelengths.begin(), m_wavelengths.end());
|
||||||
m_minWave = minW;
|
|
||||||
m_maxWave = maxW;
|
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);
|
blockAllSignals(true);
|
||||||
|
|
||||||
// Configure spinbox ranges
|
// Configure spinbox ranges and step
|
||||||
ui.spinRed->setMinimum(m_minWave);
|
ui.spinRed->setMinimum(m_minWave);
|
||||||
ui.spinRed->setMaximum(m_maxWave);
|
ui.spinRed->setMaximum(m_maxWave);
|
||||||
|
ui.spinRed->setSingleStep(step);
|
||||||
ui.spinGreen->setMinimum(m_minWave);
|
ui.spinGreen->setMinimum(m_minWave);
|
||||||
ui.spinGreen->setMaximum(m_maxWave);
|
ui.spinGreen->setMaximum(m_maxWave);
|
||||||
|
ui.spinGreen->setSingleStep(step);
|
||||||
ui.spinBlue->setMinimum(m_minWave);
|
ui.spinBlue->setMinimum(m_minWave);
|
||||||
ui.spinBlue->setMaximum(m_maxWave);
|
ui.spinBlue->setMaximum(m_maxWave);
|
||||||
|
ui.spinBlue->setSingleStep(step);
|
||||||
|
|
||||||
// Configure slider ranges (integer, multiply by 10 for 0.1 nm resolution)
|
// Slider now represents band index (0 .. N-1), step = 1
|
||||||
int sliderMin = static_cast<int>(m_minWave * 10.0);
|
int maxIdx = static_cast<int>(m_wavelengths.size()) - 1;
|
||||||
int sliderMax = static_cast<int>(m_maxWave * 10.0);
|
ui.sliderRed->setMinimum(0);
|
||||||
ui.sliderRed->setMinimum(sliderMin);
|
ui.sliderRed->setMaximum(maxIdx);
|
||||||
ui.sliderRed->setMaximum(sliderMax);
|
ui.sliderRed->setSingleStep(1);
|
||||||
ui.sliderGreen->setMinimum(sliderMin);
|
ui.sliderRed->setPageStep(1);
|
||||||
ui.sliderGreen->setMaximum(sliderMax);
|
ui.sliderGreen->setMinimum(0);
|
||||||
ui.sliderBlue->setMinimum(sliderMin);
|
ui.sliderGreen->setMaximum(maxIdx);
|
||||||
ui.sliderBlue->setMaximum(sliderMax);
|
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
|
// Set current values from layer's render params
|
||||||
auto params = layer->currentRenderParams();
|
auto params = layer->currentRenderParams();
|
||||||
ui.spinRed->setValue(params.rWave);
|
|
||||||
ui.spinGreen->setValue(params.gWave);
|
|
||||||
ui.spinBlue->setValue(params.bWave);
|
|
||||||
|
|
||||||
ui.sliderRed->setValue(static_cast<int>(params.rWave * 10.0));
|
int rIdx = nearestBandIndex(params.rWave);
|
||||||
ui.sliderGreen->setValue(static_cast<int>(params.gWave * 10.0));
|
int gIdx = nearestBandIndex(params.gWave);
|
||||||
ui.sliderBlue->setValue(static_cast<int>(params.bWave * 10.0));
|
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);
|
blockAllSignals(false);
|
||||||
}
|
}
|
||||||
@ -80,66 +123,136 @@ RasterLayer* ImageControl::activeLayer() const
|
|||||||
return m_activeLayer;
|
return m_activeLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageControl::onSpinRedChanged(double val)
|
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->blockSignals(true);
|
||||||
ui.sliderRed->setValue(static_cast<int>(val * 10.0));
|
ui.sliderRed->setValue(idx);
|
||||||
ui.sliderRed->blockSignals(false);
|
ui.sliderRed->blockSignals(false);
|
||||||
emitBandChange();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageControl::onSpinGreenChanged(double val)
|
void ImageControl::onSpinGreenValueChanged(double val)
|
||||||
{
|
{
|
||||||
|
int idx = nearestBandIndex(val);
|
||||||
ui.sliderGreen->blockSignals(true);
|
ui.sliderGreen->blockSignals(true);
|
||||||
ui.sliderGreen->setValue(static_cast<int>(val * 10.0));
|
ui.sliderGreen->setValue(idx);
|
||||||
ui.sliderGreen->blockSignals(false);
|
ui.sliderGreen->blockSignals(false);
|
||||||
emitBandChange();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageControl::onSpinBlueChanged(double val)
|
void ImageControl::onSpinBlueValueChanged(double val)
|
||||||
{
|
{
|
||||||
|
int idx = nearestBandIndex(val);
|
||||||
ui.sliderBlue->blockSignals(true);
|
ui.sliderBlue->blockSignals(true);
|
||||||
ui.sliderBlue->setValue(static_cast<int>(val * 10.0));
|
ui.sliderBlue->setValue(idx);
|
||||||
ui.sliderBlue->blockSignals(false);
|
ui.sliderBlue->blockSignals(false);
|
||||||
emitBandChange();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageControl::onSliderRedChanged(int val)
|
// --- Slider valueChanged: map band index to wavelength, sync spinbox, no render ---
|
||||||
|
|
||||||
|
void ImageControl::onSliderRedValueChanged(int val)
|
||||||
{
|
{
|
||||||
double wv = val / 10.0;
|
if (val < 0 || val >= static_cast<int>(m_wavelengths.size())) return;
|
||||||
ui.spinRed->blockSignals(true);
|
ui.spinRed->blockSignals(true);
|
||||||
ui.spinRed->setValue(wv);
|
ui.spinRed->setValue(m_wavelengths[val]);
|
||||||
ui.spinRed->blockSignals(false);
|
ui.spinRed->blockSignals(false);
|
||||||
emitBandChange();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageControl::onSliderGreenChanged(int val)
|
void ImageControl::onSliderGreenValueChanged(int val)
|
||||||
{
|
{
|
||||||
double wv = val / 10.0;
|
if (val < 0 || val >= static_cast<int>(m_wavelengths.size())) return;
|
||||||
ui.spinGreen->blockSignals(true);
|
ui.spinGreen->blockSignals(true);
|
||||||
ui.spinGreen->setValue(wv);
|
ui.spinGreen->setValue(m_wavelengths[val]);
|
||||||
ui.spinGreen->blockSignals(false);
|
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();
|
emitBandChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageControl::onSliderBlueChanged(int val)
|
void ImageControl::onSpinGreenEditingFinished()
|
||||||
{
|
{
|
||||||
double wv = val / 10.0;
|
int idx = nearestBandIndex(ui.spinGreen->value());
|
||||||
ui.spinBlue->blockSignals(true);
|
setControlsToBandIndex(ui.spinGreen, ui.sliderGreen, idx);
|
||||||
ui.spinBlue->setValue(wv);
|
|
||||||
ui.spinBlue->blockSignals(false);
|
|
||||||
emitBandChange();
|
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()
|
void ImageControl::onTrueColorClicked()
|
||||||
{
|
{
|
||||||
blockAllSignals(true);
|
blockAllSignals(true);
|
||||||
ui.spinRed->setValue(665.0);
|
int rIdx = nearestBandIndex(665.0);
|
||||||
ui.spinGreen->setValue(560.0);
|
int gIdx = nearestBandIndex(560.0);
|
||||||
ui.spinBlue->setValue(490.0);
|
int bIdx = nearestBandIndex(490.0);
|
||||||
ui.sliderRed->setValue(static_cast<int>(665.0 * 10.0));
|
setControlsToBandIndex(ui.spinRed, ui.sliderRed, rIdx);
|
||||||
ui.sliderGreen->setValue(static_cast<int>(560.0 * 10.0));
|
setControlsToBandIndex(ui.spinGreen, ui.sliderGreen, gIdx);
|
||||||
ui.sliderBlue->setValue(static_cast<int>(490.0 * 10.0));
|
setControlsToBandIndex(ui.spinBlue, ui.sliderBlue, bIdx);
|
||||||
blockAllSignals(false);
|
blockAllSignals(false);
|
||||||
emitBandChange();
|
emitBandChange();
|
||||||
}
|
}
|
||||||
@ -147,12 +260,12 @@ void ImageControl::onTrueColorClicked()
|
|||||||
void ImageControl::onColorInfraredClicked()
|
void ImageControl::onColorInfraredClicked()
|
||||||
{
|
{
|
||||||
blockAllSignals(true);
|
blockAllSignals(true);
|
||||||
ui.spinRed->setValue(800.0);
|
int rIdx = nearestBandIndex(800.0);
|
||||||
ui.spinGreen->setValue(665.0);
|
int gIdx = nearestBandIndex(665.0);
|
||||||
ui.spinBlue->setValue(560.0);
|
int bIdx = nearestBandIndex(560.0);
|
||||||
ui.sliderRed->setValue(static_cast<int>(800.0 * 10.0));
|
setControlsToBandIndex(ui.spinRed, ui.sliderRed, rIdx);
|
||||||
ui.sliderGreen->setValue(static_cast<int>(665.0 * 10.0));
|
setControlsToBandIndex(ui.spinGreen, ui.sliderGreen, gIdx);
|
||||||
ui.sliderBlue->setValue(static_cast<int>(560.0 * 10.0));
|
setControlsToBandIndex(ui.spinBlue, ui.sliderBlue, bIdx);
|
||||||
blockAllSignals(false);
|
blockAllSignals(false);
|
||||||
emitBandChange();
|
emitBandChange();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "ui_imgControl.h"
|
#include "ui_imgControl.h"
|
||||||
|
|
||||||
@ -28,12 +29,26 @@ Q_SIGNALS:
|
|||||||
void bandSelectionChanged(double rWave, double gWave, double bWave);
|
void bandSelectionChanged(double rWave, double gWave, double bWave);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void onSpinRedChanged(double val);
|
// Sync slider position while dragging spinbox (no render)
|
||||||
void onSpinGreenChanged(double val);
|
void onSpinRedValueChanged(double val);
|
||||||
void onSpinBlueChanged(double val);
|
void onSpinGreenValueChanged(double val);
|
||||||
void onSliderRedChanged(int val);
|
void onSpinBlueValueChanged(double val);
|
||||||
void onSliderGreenChanged(int val);
|
|
||||||
void onSliderBlueChanged(int val);
|
// Sync spinbox display while dragging slider (no render)
|
||||||
|
void onSliderRedValueChanged(int val);
|
||||||
|
void onSliderGreenValueChanged(int val);
|
||||||
|
void onSliderBlueValueChanged(int val);
|
||||||
|
|
||||||
|
// Commit: spinbox Enter key pressed / focus lost
|
||||||
|
void onSpinRedEditingFinished();
|
||||||
|
void onSpinGreenEditingFinished();
|
||||||
|
void onSpinBlueEditingFinished();
|
||||||
|
|
||||||
|
// Commit: slider mouse released
|
||||||
|
void onSliderRedReleased();
|
||||||
|
void onSliderGreenReleased();
|
||||||
|
void onSliderBlueReleased();
|
||||||
|
|
||||||
void onTrueColorClicked();
|
void onTrueColorClicked();
|
||||||
void onColorInfraredClicked();
|
void onColorInfraredClicked();
|
||||||
|
|
||||||
@ -41,8 +56,14 @@ private:
|
|||||||
void emitBandChange();
|
void emitBandChange();
|
||||||
void blockAllSignals(bool block);
|
void blockAllSignals(bool block);
|
||||||
|
|
||||||
|
// Find the band index whose wavelength is closest to the given value
|
||||||
|
int nearestBandIndex(double wave) const;
|
||||||
|
// Set spinbox and slider to wavelength of the given band index
|
||||||
|
void setControlsToBandIndex(QDoubleSpinBox* spin, QSlider* slider, int idx);
|
||||||
|
|
||||||
Ui::ImageControl ui;
|
Ui::ImageControl ui;
|
||||||
RasterLayer* m_activeLayer = nullptr;
|
RasterLayer* m_activeLayer = nullptr;
|
||||||
double m_minWave = 374.5;
|
double m_minWave = 374.5;
|
||||||
double m_maxWave = 948.1;
|
double m_maxWave = 948.1;
|
||||||
|
std::vector<double> m_wavelengths; // band wavelengths from header
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,17 +13,72 @@
|
|||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Color Adjust</string>
|
<string>Color Adjust</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QLabel {
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSlider::groove:horizontal {
|
||||||
|
height: 10px;
|
||||||
|
background: #1e2a44;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 已滑过:渐变蓝 */
|
||||||
|
QSlider::sub-page:horizontal {
|
||||||
|
background: qlineargradient(
|
||||||
|
x1:0, y1:0, x2:1, y2:0,
|
||||||
|
stop:0 #1f4fff,
|
||||||
|
stop:0.5 #2f6bff,
|
||||||
|
stop:1 #5fa0ff
|
||||||
|
);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 未滑过 */
|
||||||
|
QSlider::add-page:horizontal {
|
||||||
|
height: 10px;
|
||||||
|
background: #2a3550;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== 滑块按钮 ===== */
|
||||||
|
QSlider::handle:horizontal {
|
||||||
|
width: 15px;
|
||||||
|
height: 10px;
|
||||||
|
|
||||||
|
/* 蓝色实心 */
|
||||||
|
background: #2f6bff;
|
||||||
|
|
||||||
|
/* 白色外圈 */
|
||||||
|
border: 2px solid #ffffff;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
/* 垂直居中 */
|
||||||
|
margin: -5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 悬停 */
|
||||||
|
QSlider::handle:horizontal:hover {
|
||||||
|
background: #4d8dff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 按下 */
|
||||||
|
QSlider::handle:horizontal:pressed {
|
||||||
|
background: #1f4fff;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupAdjustments">
|
<widget class="QGroupBox" name="groupAdjustments">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Adjustments</string>
|
<string>调整</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="labelRed">
|
<widget class="QLabel" name="labelRed">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Red</string>
|
<string>红</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -57,7 +112,7 @@
|
|||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="labelGreen">
|
<widget class="QLabel" name="labelGreen">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Green</string>
|
<string>绿</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -91,7 +146,7 @@
|
|||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="labelBlue">
|
<widget class="QLabel" name="labelBlue">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Blue</string>
|
<string>蓝</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -128,20 +183,20 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupPresets">
|
<widget class="QGroupBox" name="groupPresets">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Presets</string>
|
<string>预设</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="presetLayout">
|
<layout class="QVBoxLayout" name="presetLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnTrueColor">
|
<widget class="QPushButton" name="btnTrueColor">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>True Color</string>
|
<string>真彩色</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnColorInfrared">
|
<widget class="QPushButton" name="btnColorInfrared">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Color Infrared</string>
|
<string>假彩色</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
Reference in New Issue
Block a user