Files
HPPA/HPPA/RasterDataProvider.cpp
tangchao0503 09095592af fix
1、基于新框架实现点击显示光谱;
2、影像拉伸显示优化;
3、右键菜单新增:移除所有栅格图层;
2026-03-06 17:33:30 +08:00

226 lines
5.6 KiB
C++

#include "RasterDataProvider.h"
#include <QString>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QRegularExpression>
#if HPPA_HAVE_GDAL
#include <gdal_priv.h>
#include <cpl_conv.h>
#endif
RasterDataProvider::RasterDataProvider(const QString& uri)
: m_uri(uri), m_dataset(nullptr)
{
}
RasterDataProvider::~RasterDataProvider()
{
close();
}
bool RasterDataProvider::open()
{
#if HPPA_HAVE_GDAL
GDALAllRegister();
m_dataset = (GDALDataset*)GDALOpen((const char*)m_uri.toLocal8Bit().constData(), GA_ReadOnly);
if (!m_dataset) {
qWarning() << "RasterDataProvider: failed to open dataset:" << m_uri;
return false;
}
return true;
#else
Q_UNUSED(m_uri);
qWarning() << "RasterDataProvider: GDAL not available, open will fail.";
return false;
#endif
}
void RasterDataProvider::close()
{
#if HPPA_HAVE_GDAL
if (m_dataset) {
GDALClose((GDALDatasetH)m_dataset);
m_dataset = nullptr;
}
#else
m_dataset = nullptr;
#endif
}
int RasterDataProvider::bandCount() const
{
#if HPPA_HAVE_GDAL
if (!m_dataset) return 0;
return m_dataset->GetRasterCount();
#else
Q_UNUSED(this);
return 0;
#endif
}
int RasterDataProvider::width() const
{
#if HPPA_HAVE_GDAL
if (!m_dataset) return 0;
return m_dataset->GetRasterXSize();
#else
Q_UNUSED(this);
return 0;
#endif
}
int RasterDataProvider::height() const
{
#if HPPA_HAVE_GDAL
if (!m_dataset) return 0;
return m_dataset->GetRasterYSize();
#else
Q_UNUSED(this);
return 0;
#endif
}
bool RasterDataProvider::isValidPixel(int x, int y) const
{
const int w = width();
const int h = height();
return x >= 0 && y >= 0 && x < w && y < h;
}
std::vector<double> RasterDataProvider::parseEnviHdrWavelengths() const
{
std::vector<double> res;
QFileInfo fi(m_uri);
QString hdrPath = fi.path() + "/" + fi.completeBaseName() + ".hdr";
QFile hdr(hdrPath);
if (!hdr.open(QIODevice::ReadOnly | QIODevice::Text)) {
return res;
}
QString text = QString::fromLocal8Bit(hdr.readAll());
hdr.close();
QRegularExpression rx("wavelength\\s*=\\s*\\{([^}]*)\\}", QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
QRegularExpressionMatch m = rx.match(text);
if (!m.hasMatch()) {
return res;
}
const QString body = m.captured(1);
const QStringList parts = body.split(',', QString::SkipEmptyParts);
res.reserve(parts.size());
for (const QString& p : parts) {
bool ok = false;
double v = p.trimmed().toDouble(&ok);
if (ok) {
res.push_back(v);
}
}
return res;
}
std::vector<double> RasterDataProvider::bandWavelengths() const
{
std::vector<double> res;
#if HPPA_HAVE_GDAL
if (!m_dataset) return res;
// 1) Try ENVI dataset-level metadata first: wavelength = { ... }
const char* dsWave = m_dataset->GetMetadataItem("wavelength", "ENVI");
if (!dsWave) dsWave = m_dataset->GetMetadataItem("Wavelength", "ENVI");
if (dsWave) {
QString dsWaveStr = QString::fromLocal8Bit(dsWave);
dsWaveStr.remove('{').remove('}');
const QStringList parts = dsWaveStr.split(',', QString::SkipEmptyParts);
res.reserve(parts.size());
for (const QString& p : parts) {
bool ok = false;
double v = p.trimmed().toDouble(&ok);
if (ok) res.push_back(v);
}
if (!res.empty()) return res;
}
// 2) Try per-band metadata
for (int i = 1; i <= m_dataset->GetRasterCount(); ++i) {
GDALRasterBand* band = m_dataset->GetRasterBand(i);
if (!band) continue;
const char* val = band->GetMetadataItem("Wavelength");
if (!val) val = band->GetMetadataItem("wavelength");
if (val) {
bool ok = false;
double v = QString::fromLocal8Bit(val).trimmed().toDouble(&ok);
res.push_back(ok ? v : -1.0);
} else {
res.push_back(-1.0);
}
}
if (!res.empty()) return res;
#endif
// 3) Fallback: parse ENVI .hdr directly
return parseEnviHdrWavelengths();
}
bool RasterDataProvider::readPixelSpectrum(int x, int y, std::vector<double>& outSpectrum) const
{
#if HPPA_HAVE_GDAL
outSpectrum.clear();
if (!m_dataset) return false;
if (!isValidPixel(x, y)) return false;
const int bands = m_dataset->GetRasterCount();
if (bands <= 0) return false;
outSpectrum.resize(bands);
for (int i = 0; i < bands; ++i) {
GDALRasterBand* band = m_dataset->GetRasterBand(i + 1);
if (!band) return false;
float value = 0.0f;
CPLErr err = band->RasterIO(
GF_Read,
x, y,
1, 1,
&value,
1, 1,
GDT_Float32,
0, 0);
if (err != CE_None) return false;
outSpectrum[i] = static_cast<double>(value);
}
return true;
#else
Q_UNUSED(x);
Q_UNUSED(y);
Q_UNUSED(outSpectrum);
return false;
#endif
}
bool RasterDataProvider::readBandAsFloat(int bandIndex, std::vector<float>& outBuffer) const
{
#if HPPA_HAVE_GDAL
if (!m_dataset) return false;
int bands = m_dataset->GetRasterCount();
if (bandIndex < 0 || bandIndex >= bands) return false;
GDALRasterBand* band = m_dataset->GetRasterBand(bandIndex + 1);
if (!band) return false;
int w = m_dataset->GetRasterXSize();
int h = m_dataset->GetRasterYSize();
outBuffer.assign(w * h, 0.0f);
CPLErr err = band->RasterIO(GF_Read, 0, 0, w, h, outBuffer.data(), w, h, GDT_Float32, 0, 0);
return err == CE_None;
#else
Q_UNUSED(bandIndex);
Q_UNUSED(outBuffer);
return false;
#endif
}