完成功能:改变图像显示的rgb波段;

1、可改变图像显示波段,当修改完成参数时实时刷新图像;
2、TOC中切换选中的多图层时,刷新渲染信息;
3、界面中保存图像的波长信息,参数修改时的选项就是准确的波长信息;
This commit is contained in:
tangchao0503
2026-03-10 17:21:21 +08:00
parent 0ac03f0eb5
commit 452f7c8e5f
8 changed files with 330 additions and 84 deletions

View File

@ -483,10 +483,6 @@ sizePolicy1.setHeightForWidth(graphicsView_delete->sizePolicy().hasHeightForWidt
initControlTabwidget();
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模型看板
ui.mDockWidgetSimulator->setTile(QString::fromLocal8Bit("3D模型"));
//ui.mDockWidgetSimulator->show();
@ -726,6 +722,8 @@ void HPPA::initControlTabwidget()
//图像控制
m_ic = new ImageControl();
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("图像控制"));
//升降桌dock

View File

@ -220,12 +220,28 @@ void Mapcavas::setLayers(RasterLayer* layer)
m_rasterLayer = layer;
}
RasterLayer* Mapcavas::rasterLayer() const
{
return m_rasterLayer;
}
// new: refresh the map by rendering using the RasterLayer's render method
void Mapcavas::freshmap()
{
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);
if (img.isNull()) return;

View File

@ -4,8 +4,7 @@
#include "QGraphicsView"
#include "qlabel.h"
#include <QVector>
class RasterLayer; // forward
#include "RasterLayer.h"
class Mapcavas : public QGraphicsView
{
@ -46,6 +45,9 @@ public:
// new: set raster layer and refresh map
void setLayers(RasterLayer* layer);
void freshmap();
void freshmap(const RasterLayer::RenderParams& params);
RasterLayer* rasterLayer() const;
protected:
QGraphicsScene *m_qtGraphicsScene;

View File

@ -1,6 +1,7 @@
#include "RasterLayer.h"
#include "RasterDataProvider.h"
#include "RasterRenderer.h"
#include <algorithm>
RasterLayer::RasterLayer(const QString& name, const QString& uri)
: MapLayer(name, uri)
@ -84,3 +85,32 @@ QImage RasterLayer::render(const RenderParams& params)
p.maxValue = params.maxValue;
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();
}

View File

@ -38,7 +38,18 @@ public:
// Render the raster using current provider and renderer. Returns an empty QImage on failure.
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:
std::unique_ptr<RasterDataProvider> m_provider;
std::unique_ptr<RasterRenderer> m_renderer;
RenderParams m_currentParams;
};

View File

@ -1,24 +1,42 @@
#include "imageControl.h"
#include "RasterLayer.h"
#include <algorithm>
#include <cmath>
ImageControl::ImageControl(QWidget* parent)
: QDialog(parent)
{
ui.setupUi(this);
// Connect spinboxes
connect(ui.spinRed, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinRedChanged);
connect(ui.spinGreen, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinGreenChanged);
connect(ui.spinBlue, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ImageControl::onSpinBlueChanged);
// 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);
// Connect sliders
connect(ui.sliderRed, &QSlider::valueChanged, this, &ImageControl::onSliderRedChanged);
connect(ui.sliderGreen, &QSlider::valueChanged, this, &ImageControl::onSliderGreenChanged);
connect(ui.sliderBlue, &QSlider::valueChanged, this, &ImageControl::onSliderBlueChanged);
// 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);
}
ImageControl::~ImageControl()
@ -31,46 +49,71 @@ void ImageControl::setActiveLayer(RasterLayer* layer)
if (!layer) {
setEnabled(false);
m_wavelengths.clear();
return;
}
setEnabled(true);
// Get wavelength range from the layer
double minW = 374.5, maxW = 948.1;
if (layer->wavelengthRange(minW, maxW)) {
m_minWave = minW;
m_maxWave = maxW;
// 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
// 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);
// Configure slider ranges (integer, multiply by 10 for 0.1 nm resolution)
int sliderMin = static_cast<int>(m_minWave * 10.0);
int sliderMax = static_cast<int>(m_maxWave * 10.0);
ui.sliderRed->setMinimum(sliderMin);
ui.sliderRed->setMaximum(sliderMax);
ui.sliderGreen->setMinimum(sliderMin);
ui.sliderGreen->setMaximum(sliderMax);
ui.sliderBlue->setMinimum(sliderMin);
ui.sliderBlue->setMaximum(sliderMax);
// 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();
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));
ui.sliderGreen->setValue(static_cast<int>(params.gWave * 10.0));
ui.sliderBlue->setValue(static_cast<int>(params.bWave * 10.0));
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);
}
@ -80,66 +123,136 @@ RasterLayer* ImageControl::activeLayer() const
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->setValue(static_cast<int>(val * 10.0));
ui.sliderRed->setValue(idx);
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->setValue(static_cast<int>(val * 10.0));
ui.sliderGreen->setValue(idx);
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->setValue(static_cast<int>(val * 10.0));
ui.sliderBlue->setValue(idx);
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->setValue(wv);
ui.spinRed->setValue(m_wavelengths[val]);
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->setValue(wv);
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::onSliderBlueChanged(int val)
void ImageControl::onSpinGreenEditingFinished()
{
double wv = val / 10.0;
ui.spinBlue->blockSignals(true);
ui.spinBlue->setValue(wv);
ui.spinBlue->blockSignals(false);
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);
ui.spinRed->setValue(665.0);
ui.spinGreen->setValue(560.0);
ui.spinBlue->setValue(490.0);
ui.sliderRed->setValue(static_cast<int>(665.0 * 10.0));
ui.sliderGreen->setValue(static_cast<int>(560.0 * 10.0));
ui.sliderBlue->setValue(static_cast<int>(490.0 * 10.0));
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();
}
@ -147,12 +260,12 @@ void ImageControl::onTrueColorClicked()
void ImageControl::onColorInfraredClicked()
{
blockAllSignals(true);
ui.spinRed->setValue(800.0);
ui.spinGreen->setValue(665.0);
ui.spinBlue->setValue(560.0);
ui.sliderRed->setValue(static_cast<int>(800.0 * 10.0));
ui.sliderGreen->setValue(static_cast<int>(665.0 * 10.0));
ui.sliderBlue->setValue(static_cast<int>(560.0 * 10.0));
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();
}

View File

@ -4,6 +4,7 @@
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <vector>
#include "ui_imgControl.h"
@ -28,12 +29,26 @@ Q_SIGNALS:
void bandSelectionChanged(double rWave, double gWave, double bWave);
private Q_SLOTS:
void onSpinRedChanged(double val);
void onSpinGreenChanged(double val);
void onSpinBlueChanged(double val);
void onSliderRedChanged(int val);
void onSliderGreenChanged(int val);
void onSliderBlueChanged(int val);
// Sync slider position while dragging spinbox (no render)
void onSpinRedValueChanged(double val);
void onSpinGreenValueChanged(double val);
void onSpinBlueValueChanged(double 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 onColorInfraredClicked();
@ -41,8 +56,14 @@ private:
void emitBandChange();
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;
RasterLayer* m_activeLayer = nullptr;
double m_minWave = 374.5;
double m_maxWave = 948.1;
std::vector<double> m_wavelengths; // band wavelengths from header
};

View File

@ -13,17 +13,72 @@
<property name="windowTitle">
<string>Color Adjust</string>
</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">
<item>
<widget class="QGroupBox" name="groupAdjustments">
<property name="title">
<string>Adjustments</string>
<string>调整</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="labelRed">
<property name="text">
<string>Red</string>
<string></string>
</property>
</widget>
</item>
@ -57,7 +112,7 @@
<item row="1" column="0">
<widget class="QLabel" name="labelGreen">
<property name="text">
<string>Green</string>
<string>绿</string>
</property>
</widget>
</item>
@ -91,7 +146,7 @@
<item row="2" column="0">
<widget class="QLabel" name="labelBlue">
<property name="text">
<string>Blue</string>
<string></string>
</property>
</widget>
</item>
@ -128,20 +183,20 @@
<item>
<widget class="QGroupBox" name="groupPresets">
<property name="title">
<string>Presets</string>
<string>预设</string>
</property>
<layout class="QVBoxLayout" name="presetLayout">
<item>
<widget class="QPushButton" name="btnTrueColor">
<property name="text">
<string>True Color</string>
<string>真彩色</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnColorInfrared">
<property name="text">
<string>Color Infrared</string>
<string>假彩色</string>
</property>
</widget>
</item>