LCOV - code coverage report
Current view: top level - gcore/mdreader - reader_spot.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 84 121 69.4 %
Date: 2024-11-25 13:07:18 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Read metadata from Spot 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_spot.h"
      16             : 
      17             : #include <ctime>
      18             : 
      19             : #include "cpl_conv.h"
      20             : #include "cpl_error.h"
      21             : #include "cpl_minixml.h"
      22             : #include "cpl_string.h"
      23             : #include "cpl_time.h"
      24             : 
      25             : #include "gdal_mdreader.h"
      26             : 
      27             : /**
      28             :  * GDALMDReaderSpot()
      29             :  */
      30        5085 : GDALMDReaderSpot::GDALMDReaderSpot(const char *pszPath,
      31        5085 :                                    char **papszSiblingFiles)
      32        5085 :     : GDALMDReaderPleiades(pszPath, papszSiblingFiles)
      33             : {
      34        5085 :     const char *pszDirName = CPLGetDirname(pszPath);
      35             : 
      36        5085 :     if (m_osIMDSourceFilename.empty())
      37             :     {
      38             :         std::string osIMDSourceFilename =
      39       10170 :             CPLFormFilename(pszDirName, "METADATA.DIM", nullptr);
      40             : 
      41        5085 :         if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
      42             :         {
      43           1 :             m_osIMDSourceFilename = std::move(osIMDSourceFilename);
      44             :         }
      45             :         else
      46             :         {
      47             :             osIMDSourceFilename =
      48        5084 :                 CPLFormFilename(pszDirName, "metadata.dim", nullptr);
      49        5084 :             if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
      50             :             {
      51           0 :                 m_osIMDSourceFilename = std::move(osIMDSourceFilename);
      52             :             }
      53             :         }
      54             :     }
      55             : 
      56             :     // if the file name ended on METADATA.DIM
      57             :     // Linux specific
      58             :     // example: R2_CAT_091028105025131_1\METADATA.DIM
      59        5085 :     if (m_osIMDSourceFilename.empty())
      60             :     {
      61        5084 :         if (EQUAL(CPLGetFilename(pszPath), "IMAGERY.TIF"))
      62             :         {
      63             :             std::string osIMDSourceFilename =
      64           0 :                 CPLSPrintf("%s\\METADATA.DIM", CPLGetPath(pszPath));
      65             : 
      66           0 :             if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
      67             :             {
      68           0 :                 m_osIMDSourceFilename = std::move(osIMDSourceFilename);
      69             :             }
      70             :             else
      71             :             {
      72             :                 osIMDSourceFilename =
      73           0 :                     CPLSPrintf("%s\\metadata.dim", CPLGetPath(pszPath));
      74           0 :                 if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
      75             :                 {
      76           0 :                     m_osIMDSourceFilename = std::move(osIMDSourceFilename);
      77             :                 }
      78             :             }
      79             :         }
      80             :     }
      81             : 
      82        5085 :     if (!m_osIMDSourceFilename.empty())
      83           1 :         CPLDebug("MDReaderSpot", "IMD Filename: %s",
      84             :                  m_osIMDSourceFilename.c_str());
      85        5085 : }
      86             : 
      87             : /**
      88             :  * ~GDALMDReaderSpot()
      89             :  */
      90       10170 : GDALMDReaderSpot::~GDALMDReaderSpot()
      91             : {
      92       10170 : }
      93             : 
      94             : /**
      95             :  * LoadMetadata()
      96             :  */
      97           2 : void GDALMDReaderSpot::LoadMetadata()
      98             : {
      99           2 :     if (m_bIsMetadataLoad)
     100           1 :         return;
     101             : 
     102           1 :     if (!m_osIMDSourceFilename.empty())
     103             :     {
     104           1 :         CPLXMLNode *psNode = CPLParseXMLFile(m_osIMDSourceFilename);
     105             : 
     106           1 :         if (psNode != nullptr)
     107             :         {
     108           1 :             CPLXMLNode *psisdNode = CPLSearchXMLNode(psNode, "=Dimap_Document");
     109             : 
     110           1 :             if (psisdNode != nullptr)
     111             :             {
     112           1 :                 m_papszIMDMD = ReadXMLToList(psisdNode->psChild, m_papszIMDMD);
     113             :             }
     114           1 :             CPLDestroyXMLNode(psNode);
     115             :         }
     116             :     }
     117             : 
     118           1 :     m_papszDEFAULTMD =
     119           1 :         CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "DIMAP");
     120             : 
     121           1 :     m_bIsMetadataLoad = true;
     122             : 
     123           1 :     if (nullptr == m_papszIMDMD)
     124             :     {
     125           0 :         return;
     126             :     }
     127             : 
     128             :     // extract imagery metadata
     129           1 :     int nCounter = -1;
     130           2 :     const char *pszSatId1 = CSLFetchNameValue(
     131           1 :         m_papszIMDMD,
     132             :         "Dataset_Sources.Source_Information.Scene_Source.MISSION");
     133           1 :     if (nullptr == pszSatId1)
     134             :     {
     135           0 :         nCounter = 1;
     136           0 :         for (int i = 0; i < 5; i++)
     137             :         {
     138           0 :             pszSatId1 = CSLFetchNameValue(
     139           0 :                 m_papszIMDMD, CPLSPrintf("Dataset_Sources.Source_Information_%"
     140             :                                          "d.Scene_Source.MISSION",
     141             :                                          nCounter));
     142           0 :             if (nullptr != pszSatId1)
     143           0 :                 break;
     144           0 :             nCounter++;
     145             :         }
     146             :     }
     147             : 
     148             :     const char *pszSatId2;
     149           1 :     if (nCounter == -1)
     150           1 :         pszSatId2 = CSLFetchNameValue(
     151           1 :             m_papszIMDMD,
     152             :             "Dataset_Sources.Source_Information.Scene_Source.MISSION_INDEX");
     153             :     else
     154           0 :         pszSatId2 = CSLFetchNameValue(
     155           0 :             m_papszIMDMD, CPLSPrintf("Dataset_Sources.Source_Information_%d."
     156             :                                      "Scene_Source.MISSION_INDEX",
     157             :                                      nCounter));
     158             : 
     159           1 :     if (nullptr != pszSatId1 && nullptr != pszSatId2)
     160             :     {
     161           2 :         m_papszIMAGERYMD = CSLAddNameValue(
     162             :             m_papszIMAGERYMD, MD_NAME_SATELLITE,
     163           2 :             CPLSPrintf("%s %s", CPLStripQuotes(pszSatId1).c_str(),
     164           2 :                        CPLStripQuotes(pszSatId2).c_str()));
     165             :     }
     166           0 :     else if (nullptr != pszSatId1 && nullptr == pszSatId2)
     167             :     {
     168           0 :         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
     169           0 :                                            CPLStripQuotes(pszSatId1));
     170             :     }
     171           0 :     else if (nullptr == pszSatId1 && nullptr != pszSatId2)
     172             :     {
     173           0 :         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
     174           0 :                                            CPLStripQuotes(pszSatId2));
     175             :     }
     176             : 
     177             :     const char *pszDate;
     178           1 :     if (nCounter == -1)
     179           1 :         pszDate = CSLFetchNameValue(
     180           1 :             m_papszIMDMD,
     181             :             "Dataset_Sources.Source_Information.Scene_Source.IMAGING_DATE");
     182             :     else
     183           0 :         pszDate = CSLFetchNameValue(
     184           0 :             m_papszIMDMD, CPLSPrintf("Dataset_Sources.Source_Information_%d."
     185             :                                      "Scene_Source.IMAGING_DATE",
     186             :                                      nCounter));
     187             : 
     188           1 :     if (nullptr != pszDate)
     189             :     {
     190             :         const char *pszTime;
     191           1 :         if (nCounter == -1)
     192           1 :             pszTime = CSLFetchNameValue(
     193           1 :                 m_papszIMDMD,
     194             :                 "Dataset_Sources.Source_Information.Scene_Source.IMAGING_TIME");
     195             :         else
     196           0 :             pszTime = CSLFetchNameValue(
     197           0 :                 m_papszIMDMD, CPLSPrintf("Dataset_Sources.Source_Information_%"
     198             :                                          "d.Scene_Source.IMAGING_TIME",
     199             :                                          nCounter));
     200             : 
     201           1 :         if (nullptr == pszTime)
     202           0 :             pszTime = "00:00:00.0Z";
     203             : 
     204             :         char buffer[80];
     205             :         GIntBig timeMid =
     206           1 :             GetAcquisitionTimeFromString(CPLSPrintf("%sT%s", pszDate, pszTime));
     207             :         struct tm tmBuf;
     208           1 :         strftime(buffer, 80, MD_DATETIMEFORMAT,
     209           1 :                  CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
     210           1 :         m_papszIMAGERYMD =
     211           1 :             CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_ACQDATETIME, buffer);
     212             :     }
     213             : 
     214           1 :     m_papszIMAGERYMD =
     215           1 :         CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER, MD_CLOUDCOVER_NA);
     216             : }
     217             : 
     218             : /**
     219             :  * ReadXMLToList()
     220             :  */
     221          58 : char **GDALMDReaderSpot::ReadXMLToList(CPLXMLNode *psNode, char **papszList,
     222             :                                        const char *pszName)
     223             : {
     224          58 :     if (nullptr == psNode)
     225           0 :         return papszList;
     226             : 
     227          58 :     if (psNode->eType == CXT_Text)
     228             :     {
     229          22 :         if (!EQUAL(pszName, ""))
     230          22 :             return AddXMLNameValueToList(papszList, pszName, psNode->pszValue);
     231             :     }
     232             : 
     233          36 :     if (psNode->eType == CXT_Element && !EQUAL(psNode->pszValue, "Data_Strip"))
     234             :     {
     235          31 :         int nAddIndex = 0;
     236          31 :         bool bReset = false;
     237          80 :         for (CPLXMLNode *psChildNode = psNode->psChild; nullptr != psChildNode;
     238          49 :              psChildNode = psChildNode->psNext)
     239             :         {
     240          49 :             if (psChildNode->eType == CXT_Element)
     241             :             {
     242             :                 // check name duplicates
     243          25 :                 if (nullptr != psChildNode->psNext)
     244             :                 {
     245          16 :                     if (bReset)
     246             :                     {
     247           0 :                         bReset = false;
     248           0 :                         nAddIndex = 0;
     249             :                     }
     250             : 
     251          16 :                     if (EQUAL(psChildNode->pszValue,
     252             :                               psChildNode->psNext->pszValue))
     253             :                     {
     254           0 :                         nAddIndex++;
     255             :                     }
     256             :                     else
     257             :                     {  // the name changed
     258             : 
     259          16 :                         if (nAddIndex > 0)
     260             :                         {
     261           0 :                             bReset = true;
     262           0 :                             nAddIndex++;
     263             :                         }
     264             :                     }
     265             :                 }
     266             :                 else
     267             :                 {
     268           9 :                     if (nAddIndex > 0)
     269             :                     {
     270           0 :                         nAddIndex++;
     271             :                     }
     272             :                 }
     273             : 
     274             :                 char szName[512];
     275          25 :                 if (nAddIndex > 0)
     276             :                 {
     277           0 :                     CPLsnprintf(szName, 511, "%s_%d", psChildNode->pszValue,
     278             :                                 nAddIndex);
     279             :                 }
     280             :                 else
     281             :                 {
     282          25 :                     CPLStrlcpy(szName, psChildNode->pszValue, 511);
     283             :                 }
     284             : 
     285             :                 char szNameNew[512];
     286          25 :                 if (CPLStrnlen(pszName, 511) >
     287             :                     0)  // if no prefix just set name to node name
     288             :                 {
     289          10 :                     CPLsnprintf(szNameNew, 511, "%s.%s", pszName, szName);
     290             :                 }
     291             :                 else
     292             :                 {
     293          15 :                     CPLsnprintf(szNameNew, 511, "%s.%s", psNode->pszValue,
     294             :                                 szName);
     295             :                 }
     296             : 
     297          25 :                 papszList = ReadXMLToList(psChildNode, papszList, szNameNew);
     298             :             }
     299             :             else
     300             :             {
     301             :                 // Text nodes should always have name
     302          24 :                 if (EQUAL(pszName, ""))
     303             :                 {
     304             :                     papszList =
     305           0 :                         ReadXMLToList(psChildNode, papszList, psNode->pszValue);
     306             :                 }
     307             :                 else
     308             :                 {
     309          24 :                     papszList = ReadXMLToList(psChildNode, papszList, pszName);
     310             :                 }
     311             :             }
     312             :         }
     313             :     }
     314             : 
     315             :     // proceed next only on top level
     316             : 
     317          36 :     if (nullptr != psNode->psNext && EQUAL(pszName, ""))
     318             :     {
     319           8 :         papszList = ReadXMLToList(psNode->psNext, papszList, pszName);
     320             :     }
     321             : 
     322          36 :     return papszList;
     323             : }

Generated by: LCOV version 1.14