#include "RasterDataProvider.h" #include #include #include #include #include #if HPPA_HAVE_GDAL #include #include #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 RasterDataProvider::parseEnviHdrWavelengths() const { std::vector 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 RasterDataProvider::bandWavelengths() const { std::vector 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& 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(value); } return true; #else Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(outSpectrum); return false; #endif } bool RasterDataProvider::readBandAsFloat(int bandIndex, std::vector& 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 }