LCOV - code coverage report
Current view: top level - gcore/mdreader - reader_eros.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 98 116 84.5 %
Date: 2026-06-19 21:24:00 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Read metadata from EROS imagery.
       5             :  * Author:   Alexander Lisovenko
       6             :  * Author:   Dmitry Baryshnikov, polimax@mail.ru
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2014-2015, NextGIS info@nextgis.ru
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "reader_eros.h"
      16             : 
      17             : #include <cstddef>
      18             : #include <cstdio>
      19             : #include <cstdlib>
      20             : 
      21             : #include "cpl_conv.h"
      22             : #include "cpl_error.h"
      23             : #include "cpl_string.h"
      24             : #include "cpl_time.h"
      25             : 
      26             : /**
      27             :  * GDALMDReaderEROS()
      28             :  */
      29        5895 : GDALMDReaderEROS::GDALMDReaderEROS(const char *pszPath,
      30        5895 :                                    CSLConstList papszSiblingFiles)
      31        5895 :     : GDALMDReaderBase(pszPath, papszSiblingFiles)
      32             : {
      33        5895 :     const CPLString osBaseName = CPLGetBasenameSafe(pszPath);
      34        5895 :     const CPLString osDirName = CPLGetDirnameSafe(pszPath);
      35        5895 :     char szMetadataName[512] = {0};
      36             :     size_t i;
      37        5895 :     if (osBaseName.size() > 511)
      38           0 :         return;
      39             : 
      40             :     // To shutdown HTTP 403 errors when trying to open .pass side-car file on
      41             :     // gdalinfo /vsicurl/https://s3.opengeohub.org/global/dtm/v1.2/gedtm_rf_m_30m_s_20060101_20151231_go_epsg.4326.3855_v1.2.tif --debug on
      42       11790 :     CPLErrorStateBackuper oBackuper(CPLQuietErrorHandler);
      43             : 
      44       64722 :     for (i = 0; i < osBaseName.size(); i++)
      45             :     {
      46       58827 :         if (STARTS_WITH_CI(osBaseName + i, "."))
      47             :         {
      48             :             std::string osPassFileName =
      49          97 :                 CPLFormFilenameSafe(osDirName, szMetadataName, "pass");
      50          97 :             if (CPLCheckForFile(&osPassFileName[0], papszSiblingFiles))
      51             :             {
      52           0 :                 m_osIMDSourceFilename = std::move(osPassFileName);
      53           0 :                 break;
      54             :             }
      55             :             else
      56             :             {
      57             :                 osPassFileName =
      58          97 :                     CPLFormFilenameSafe(osDirName, szMetadataName, "PASS");
      59          97 :                 if (CPLCheckForFile(&osPassFileName[0], papszSiblingFiles))
      60             :                 {
      61           0 :                     m_osIMDSourceFilename = std::move(osPassFileName);
      62           0 :                     break;
      63             :                 }
      64             :             }
      65             :         }
      66       58827 :         szMetadataName[i] = osBaseName[i];
      67             :     }
      68             : 
      69        5895 :     if (m_osIMDSourceFilename.empty())
      70             :     {
      71             :         std::string osPassFileName =
      72       11790 :             CPLFormFilenameSafe(osDirName, szMetadataName, "pass");
      73        5895 :         if (CPLCheckForFile(&osPassFileName[0], papszSiblingFiles))
      74             :         {
      75           1 :             m_osIMDSourceFilename = std::move(osPassFileName);
      76             :         }
      77             :         else
      78             :         {
      79             :             osPassFileName =
      80        5894 :                 CPLFormFilenameSafe(osDirName, szMetadataName, "PASS");
      81        5894 :             if (CPLCheckForFile(&osPassFileName[0], papszSiblingFiles))
      82             :             {
      83           0 :                 m_osIMDSourceFilename = std::move(osPassFileName);
      84             :             }
      85             :         }
      86             :     }
      87             : 
      88             :     std::string osRPCFileName =
      89       11790 :         CPLFormFilenameSafe(osDirName, szMetadataName, "rpc");
      90        5895 :     if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
      91             :     {
      92           1 :         m_osRPBSourceFilename = std::move(osRPCFileName);
      93             :     }
      94             :     else
      95             :     {
      96             :         osRPCFileName =
      97        5894 :             CPLFormFilenameSafe(osDirName, szMetadataName, GDAL_MDD_RPC);
      98        5894 :         if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
      99             :         {
     100           0 :             m_osRPBSourceFilename = std::move(osRPCFileName);
     101             :         }
     102             :     }
     103             : 
     104        5895 :     if (!m_osIMDSourceFilename.empty())
     105           1 :         CPLDebug("MDReaderEROS", "IMD Filename: %s",
     106             :                  m_osIMDSourceFilename.c_str());
     107        5895 :     if (!m_osRPBSourceFilename.empty())
     108           1 :         CPLDebug("MDReaderEROS", "RPB Filename: %s",
     109             :                  m_osRPBSourceFilename.c_str());
     110             : }
     111             : 
     112             : /**
     113             :  * ~GDALMDReaderEROS()
     114             :  */
     115       11790 : GDALMDReaderEROS::~GDALMDReaderEROS()
     116             : {
     117       11790 : }
     118             : 
     119             : /**
     120             :  * HasRequiredFiles()
     121             :  */
     122        5895 : bool GDALMDReaderEROS::HasRequiredFiles() const
     123             : {
     124        5895 :     if (!m_osIMDSourceFilename.empty())
     125           1 :         return true;
     126        5894 :     if (!m_osRPBSourceFilename.empty())
     127           0 :         return true;
     128             : 
     129        5894 :     return false;
     130             : }
     131             : 
     132             : /**
     133             :  * GetMetadataFiles()
     134             :  */
     135           1 : char **GDALMDReaderEROS::GetMetadataFiles() const
     136             : {
     137           1 :     char **papszFileList = nullptr;
     138           1 :     if (!m_osIMDSourceFilename.empty())
     139           1 :         papszFileList = CSLAddString(papszFileList, m_osIMDSourceFilename);
     140           1 :     if (!m_osRPBSourceFilename.empty())
     141           1 :         papszFileList = CSLAddString(papszFileList, m_osRPBSourceFilename);
     142           1 :     return papszFileList;
     143             : }
     144             : 
     145             : /**
     146             :  * LoadMetadata()
     147             :  */
     148           2 : void GDALMDReaderEROS::LoadMetadata()
     149             : {
     150           2 :     if (m_bIsMetadataLoad)
     151           1 :         return;
     152             : 
     153           1 :     if (!m_osIMDSourceFilename.empty())
     154             :     {
     155           1 :         m_papszIMDMD = LoadImdTxtFile();
     156             :     }
     157             : 
     158           1 :     if (!m_osRPBSourceFilename.empty())
     159             :     {
     160           1 :         m_papszRPCMD = GDALLoadRPCFile(m_osRPBSourceFilename);
     161             :     }
     162             : 
     163           1 :     m_papszDEFAULTMD =
     164           1 :         CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "EROS");
     165             : 
     166           1 :     m_bIsMetadataLoad = true;
     167             : 
     168           1 :     const char *pszSatId1 = CSLFetchNameValue(m_papszIMDMD, "satellite");
     169           1 :     const char *pszSatId2 = CSLFetchNameValue(m_papszIMDMD, "camera");
     170           1 :     if (nullptr != pszSatId1 && nullptr != pszSatId2)
     171             :     {
     172           2 :         m_papszIMAGERYMD = CSLAddNameValue(
     173             :             m_papszIMAGERYMD, GDALMD_SATELLITEID,
     174           2 :             CPLSPrintf("%s %s", CPLStripQuotes(pszSatId1).c_str(),
     175           2 :                        CPLStripQuotes(pszSatId2).c_str()));
     176             :     }
     177           0 :     else if (nullptr != pszSatId1 && nullptr == pszSatId2)
     178             :     {
     179           0 :         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, GDALMD_SATELLITEID,
     180           0 :                                            CPLStripQuotes(pszSatId1));
     181             :     }
     182           0 :     else if (nullptr == pszSatId1 && nullptr != pszSatId2)
     183             :     {
     184           0 :         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, GDALMD_SATELLITEID,
     185           0 :                                            CPLStripQuotes(pszSatId2));
     186             :     }
     187             : 
     188           1 :     const char *pszCloudCover = CSLFetchNameValue(m_papszIMDMD, "overall_cc");
     189           1 :     if (nullptr != pszCloudCover)
     190             :     {
     191           1 :         int nCC = atoi(pszCloudCover);
     192           1 :         if (nCC > 100 || nCC < 0)
     193             :         {
     194           0 :             m_papszIMAGERYMD = CSLAddNameValue(
     195             :                 m_papszIMAGERYMD, GDALMD_CLOUDCOVER, MD_CLOUDCOVER_NA);
     196             :         }
     197             :         else
     198             :         {
     199           1 :             m_papszIMAGERYMD = CSLAddNameValue(
     200             :                 m_papszIMAGERYMD, GDALMD_CLOUDCOVER, CPLSPrintf("%d", nCC));
     201             :         }
     202             :     }
     203             : 
     204           1 :     const char *pszDate = CSLFetchNameValue(m_papszIMDMD, "sweep_start_utc");
     205           1 :     if (nullptr != pszDate)
     206             :     {
     207             :         char buffer[80];
     208           1 :         GIntBig timeMid = GetAcquisitionTimeFromString(CPLStripQuotes(pszDate));
     209             :         struct tm tmBuf;
     210           1 :         strftime(buffer, 80, MD_DATETIMEFORMAT,
     211           1 :                  CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
     212           1 :         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
     213             :                                            GDALMD_ACQUISITIONDATETIME, buffer);
     214             :     }
     215             : }
     216             : 
     217             : /**
     218             :  * LoadImdTxtFile
     219             :  */
     220           1 : char **GDALMDReaderEROS::LoadImdTxtFile()
     221             : {
     222           1 :     char **papszLines = CSLLoad(m_osIMDSourceFilename);
     223           1 :     if (nullptr == papszLines)
     224           0 :         return nullptr;
     225             : 
     226           1 :     char **papszIMD = nullptr;
     227             : 
     228          10 :     for (int i = 0; papszLines[i] != nullptr; i++)
     229             :     {
     230           9 :         const char *pszLine = papszLines[i];
     231           9 :         if (CPLStrnlen(pszLine, 21) >= 21)
     232             :         {
     233             :             char szName[22];
     234           9 :             memcpy(szName, pszLine, 21);
     235           9 :             szName[21] = 0;
     236           9 :             char *pszSpace = strchr(szName, ' ');
     237           9 :             if (pszSpace)
     238             :             {
     239           9 :                 *pszSpace = 0;
     240           9 :                 papszIMD = CSLAddNameValue(papszIMD, szName, pszLine + 20);
     241             :             }
     242             :         }
     243             :     }
     244             : 
     245           1 :     CSLDestroy(papszLines);
     246             : 
     247           1 :     return papszIMD;
     248             : }
     249             : 
     250             : /**
     251             :  * GetAcqisitionTimeFromString()
     252             :  */
     253           1 : GIntBig GDALMDReaderEROS::GetAcquisitionTimeFromString(const char *pszDateTime)
     254             : {
     255           1 :     if (nullptr == pszDateTime)
     256           0 :         return 0;
     257             : 
     258             :     int iYear;
     259             :     int iMonth;
     260             :     int iDay;
     261             :     int iHours;
     262             :     int iMin;
     263             :     int iSec;
     264             : 
     265             :     // example: sweep_start_utc     2013-04-22,11:35:02.50724
     266             : 
     267           1 :     int r = sscanf(pszDateTime, "%d-%d-%d,%d:%d:%d.%*d", &iYear, &iMonth, &iDay,
     268             :                    &iHours, &iMin, &iSec);
     269             : 
     270           1 :     if (r != 6)
     271           0 :         return 0;
     272             : 
     273             :     struct tm tmDateTime;
     274           1 :     tmDateTime.tm_sec = iSec;
     275           1 :     tmDateTime.tm_min = iMin;
     276           1 :     tmDateTime.tm_hour = iHours;
     277           1 :     tmDateTime.tm_mday = iDay;
     278           1 :     tmDateTime.tm_mon = iMonth - 1;
     279           1 :     tmDateTime.tm_year = iYear - 1900;
     280           1 :     tmDateTime.tm_isdst = -1;
     281             : 
     282           1 :     return CPLYMDHMSToUnixTime(&tmDateTime);
     283             : }

Generated by: LCOV version 1.14