LCOV - code coverage report
Current view: top level - gcore/mdreader - reader_alos.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 140 179 78.2 %
Date: 2025-01-18 12:42:00 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Read metadata from Alos 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 "reader_alos.h"
      15             : 
      16             : #include <cstdio>
      17             : #include <cstdlib>
      18             : 
      19             : #include <string>
      20             : 
      21             : #include "cpl_conv.h"
      22             : #include "cpl_error.h"
      23             : #include "cpl_string.h"
      24             : #include "cpl_time.h"
      25             : #include "gdal_mdreader.h"
      26             : 
      27             : /**
      28             :  * GDALMDReaderALOS()
      29             :  */
      30        5342 : GDALMDReaderALOS::GDALMDReaderALOS(const char *pszPath,
      31        5342 :                                    char **papszSiblingFiles)
      32        5342 :     : GDALMDReaderBase(pszPath, papszSiblingFiles)
      33             : {
      34       10684 :     const CPLString osDirName = CPLGetDirnameSafe(pszPath);
      35       10684 :     const CPLString osBaseName = CPLGetBasenameSafe(pszPath);
      36             : 
      37             :     CPLString osIMDSourceFilename =
      38       10684 :         CPLFormFilenameSafe(osDirName, "summary", ".txt");
      39        5342 :     if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
      40             :     {
      41           1 :         m_osIMDSourceFilename = std::move(osIMDSourceFilename);
      42             :     }
      43             :     else
      44             :     {
      45        5341 :         osIMDSourceFilename = CPLFormFilenameSafe(osDirName, "SUMMARY", ".TXT");
      46        5341 :         if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
      47             :         {
      48           0 :             m_osIMDSourceFilename = std::move(osIMDSourceFilename);
      49             :         }
      50             :     }
      51             : 
      52        5342 :     if (osBaseName.size() >= 6)
      53             :     {
      54             :         // check if this is separate band or whole image
      55             :         // test without 6 symbols
      56        6342 :         CPLString osHDRFileName = CPLFormFilenameSafe(
      57        6342 :             osDirName, (std::string("HDR") + (osBaseName.c_str() + 6)).c_str(),
      58        6342 :             "txt");
      59        3171 :         if (CPLCheckForFile(&osHDRFileName[0], papszSiblingFiles))
      60             :         {
      61           0 :             m_osHDRSourceFilename = std::move(osHDRFileName);
      62             :         }
      63             :         else
      64             :         {
      65        3171 :             osHDRFileName = CPLFormFilenameSafe(
      66             :                 osDirName,
      67        6342 :                 (std::string("HDR") + (osBaseName.c_str() + 6)).c_str(), "TXT");
      68        3171 :             if (CPLCheckForFile(&osHDRFileName[0], papszSiblingFiles))
      69             :             {
      70           0 :                 m_osHDRSourceFilename = std::move(osHDRFileName);
      71             :             }
      72             :         }
      73             :     }
      74             : 
      75             :     // test without 3 symbols
      76        5342 :     if (osBaseName.size() >= 3 && m_osHDRSourceFilename.empty())
      77             :     {
      78       10648 :         CPLString osHDRFileName = CPLFormFilenameSafe(
      79       10648 :             osDirName, (std::string("HDR") + (osBaseName.c_str() + 3)).c_str(),
      80       10648 :             "txt");
      81        5324 :         if (CPLCheckForFile(&osHDRFileName[0], papszSiblingFiles))
      82             :         {
      83           0 :             m_osHDRSourceFilename = std::move(osHDRFileName);
      84             :         }
      85             :         else
      86             :         {
      87        5324 :             osHDRFileName = CPLFormFilenameSafe(
      88             :                 osDirName,
      89       10648 :                 (std::string("HDR") + (osBaseName.c_str() + 3)).c_str(), "TXT");
      90        5324 :             if (CPLCheckForFile(&osHDRFileName[0], papszSiblingFiles))
      91             :             {
      92           0 :                 m_osHDRSourceFilename = std::move(osHDRFileName);
      93             :             }
      94             :         }
      95             :     }
      96             : 
      97             :     // test without 6 symbols
      98        5342 :     if (osBaseName.size() >= 6)
      99             :     {
     100        6342 :         CPLString osRPCFileName = CPLFormFilenameSafe(
     101        6342 :             osDirName, (std::string("RPC") + (osBaseName.c_str() + 6)).c_str(),
     102        6342 :             "txt");
     103        3171 :         if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
     104             :         {
     105           0 :             m_osRPBSourceFilename = std::move(osRPCFileName);
     106             :         }
     107             :         else
     108             :         {
     109        3171 :             osRPCFileName = CPLFormFilenameSafe(
     110             :                 osDirName,
     111        6342 :                 (std::string("RPC") + (osBaseName.c_str() + 6)).c_str(), "TXT");
     112        3171 :             if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
     113             :             {
     114           0 :                 m_osRPBSourceFilename = std::move(osRPCFileName);
     115             :             }
     116             :         }
     117             :     }
     118             : 
     119             :     // test without 3 symbols
     120        5342 :     if (osBaseName.size() >= 3 && m_osRPBSourceFilename.empty())
     121             :     {
     122       10648 :         CPLString osRPCFileName = CPLFormFilenameSafe(
     123       10648 :             osDirName, (std::string("RPC") + (osBaseName.c_str() + 3)).c_str(),
     124       10648 :             "txt");
     125        5324 :         if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
     126             :         {
     127           1 :             m_osRPBSourceFilename = std::move(osRPCFileName);
     128             :         }
     129             :         else
     130             :         {
     131        5323 :             osRPCFileName = CPLFormFilenameSafe(
     132             :                 osDirName,
     133       10646 :                 (std::string("RPC") + (osBaseName.c_str() + 3)).c_str(), "TXT");
     134        5323 :             if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
     135             :             {
     136           0 :                 m_osRPBSourceFilename = std::move(osRPCFileName);
     137             :             }
     138             :         }
     139             :     }
     140             : 
     141        5342 :     if (!m_osIMDSourceFilename.empty())
     142           1 :         CPLDebug("MDReaderALOS", "IMD Filename: %s",
     143             :                  m_osIMDSourceFilename.c_str());
     144        5342 :     if (!m_osHDRSourceFilename.empty())
     145           0 :         CPLDebug("MDReaderALOS", "HDR Filename: %s",
     146             :                  m_osHDRSourceFilename.c_str());
     147        5342 :     if (!m_osRPBSourceFilename.empty())
     148           1 :         CPLDebug("MDReaderALOS", "RPB Filename: %s",
     149             :                  m_osRPBSourceFilename.c_str());
     150        5342 : }
     151             : 
     152             : /**
     153             :  * ~GDALMDReaderALOS()
     154             :  */
     155       10684 : GDALMDReaderALOS::~GDALMDReaderALOS()
     156             : {
     157       10684 : }
     158             : 
     159             : /**
     160             :  * HasRequiredFiles()
     161             :  */
     162        5342 : bool GDALMDReaderALOS::HasRequiredFiles() const
     163             : {
     164        5342 :     if (!m_osIMDSourceFilename.empty())
     165           1 :         return true;
     166             : 
     167        5341 :     if (!m_osHDRSourceFilename.empty() && !m_osRPBSourceFilename.empty())
     168           0 :         return true;
     169             : 
     170        5341 :     return false;
     171             : }
     172             : 
     173             : /**
     174             :  * GetMetadataFiles()
     175             :  */
     176           1 : char **GDALMDReaderALOS::GetMetadataFiles() const
     177             : {
     178           1 :     char **papszFileList = nullptr;
     179           1 :     if (!m_osIMDSourceFilename.empty())
     180           1 :         papszFileList = CSLAddString(papszFileList, m_osIMDSourceFilename);
     181           1 :     if (!m_osHDRSourceFilename.empty())
     182           0 :         papszFileList = CSLAddString(papszFileList, m_osHDRSourceFilename);
     183           1 :     if (!m_osRPBSourceFilename.empty())
     184           1 :         papszFileList = CSLAddString(papszFileList, m_osRPBSourceFilename);
     185             : 
     186           1 :     return papszFileList;
     187             : }
     188             : 
     189             : /**
     190             :  * LoadMetadata()
     191             :  */
     192           2 : void GDALMDReaderALOS::LoadMetadata()
     193             : {
     194           2 :     if (m_bIsMetadataLoad)
     195           1 :         return;
     196             : 
     197           1 :     if (!m_osIMDSourceFilename.empty())
     198             :     {
     199           1 :         m_papszIMDMD = CSLLoad(m_osIMDSourceFilename);
     200             :     }
     201             : 
     202           1 :     if (!m_osHDRSourceFilename.empty())
     203             :     {
     204           0 :         if (nullptr == m_papszIMDMD)
     205             :         {
     206           0 :             m_papszIMDMD = CSLLoad(m_osHDRSourceFilename);
     207             :         }
     208             :         else
     209             :         {
     210           0 :             char **papszHDR = CSLLoad(m_osHDRSourceFilename);
     211           0 :             m_papszIMDMD = CSLMerge(m_papszIMDMD, papszHDR);
     212           0 :             CSLDestroy(papszHDR);
     213             :         }
     214             :     }
     215             : 
     216           1 :     m_papszRPCMD = LoadRPCTxtFile();
     217             : 
     218           1 :     m_papszDEFAULTMD =
     219           1 :         CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "ALOS");
     220             : 
     221           1 :     m_bIsMetadataLoad = true;
     222             : 
     223           1 :     const char *pszSatId1 = CSLFetchNameValue(m_papszIMDMD, "Lbi_Satellite");
     224           1 :     const char *pszSatId2 = CSLFetchNameValue(m_papszIMDMD, "Lbi_Sensor");
     225           1 :     if (nullptr != pszSatId1 && nullptr != pszSatId2)
     226             :     {
     227           2 :         m_papszIMAGERYMD = CSLAddNameValue(
     228             :             m_papszIMAGERYMD, MD_NAME_SATELLITE,
     229           2 :             CPLSPrintf("%s %s", CPLStripQuotes(pszSatId1).c_str(),
     230           2 :                        CPLStripQuotes(pszSatId2).c_str()));
     231             :     }
     232           0 :     else if (nullptr != pszSatId1 && nullptr == pszSatId2)
     233             :     {
     234           0 :         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
     235           0 :                                            CPLStripQuotes(pszSatId1));
     236             :     }
     237           0 :     else if (nullptr == pszSatId1 && nullptr != pszSatId2)
     238             :     {
     239           0 :         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
     240           0 :                                            CPLStripQuotes(pszSatId2));
     241             :     }
     242             : 
     243             :     const char *pszCloudCover =
     244           1 :         CSLFetchNameValue(m_papszIMDMD, "Img_CloudQuantityOfAllImage");
     245           1 :     if (nullptr != pszCloudCover)
     246             :     {
     247           0 :         int nCC = atoi(pszCloudCover);
     248           0 :         if (nCC >= 99)
     249             :         {
     250           0 :             m_papszIMAGERYMD = CSLAddNameValue(
     251             :                 m_papszIMAGERYMD, MD_NAME_CLOUDCOVER, MD_CLOUDCOVER_NA);
     252             :         }
     253             :         else
     254             :         {
     255           0 :             m_papszIMAGERYMD =
     256           0 :                 CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
     257             :                                 CPLSPrintf("%d", nCC * 10));
     258             :         }
     259             :     }
     260             : 
     261             :     const char *pszDate =
     262           1 :         CSLFetchNameValue(m_papszIMDMD, "Img_SceneCenterDateTime");
     263             : 
     264           1 :     if (nullptr != pszDate)
     265             :     {
     266             :         char buffer[80];
     267           0 :         GIntBig timeMid = GetAcquisitionTimeFromString(CPLStripQuotes(pszDate));
     268             :         struct tm tmBuf;
     269           0 :         strftime(buffer, 80, MD_DATETIMEFORMAT,
     270           0 :                  CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
     271           0 :         m_papszIMAGERYMD =
     272           0 :             CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_ACQDATETIME, buffer);
     273             :     }
     274             :     else
     275             :     {
     276           1 :         pszDate = CSLFetchNameValue(m_papszIMDMD, "Lbi_ObservationDate");
     277           1 :         if (nullptr != pszDate)
     278             :         {
     279           1 :             const char *pszTime = "00:00:00.000";
     280             : 
     281             :             char buffer[80];
     282           2 :             GIntBig timeMid = GetAcquisitionTimeFromString(
     283           2 :                 CPLSPrintf("%s %s", CPLStripQuotes(pszDate).c_str(),
     284           2 :                            CPLStripQuotes(pszTime).c_str()));
     285             :             struct tm tmBuf;
     286           1 :             strftime(buffer, 80, MD_DATETIMEFORMAT,
     287           1 :                      CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
     288           1 :             m_papszIMAGERYMD =
     289           1 :                 CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_ACQDATETIME, buffer);
     290             :         }
     291             :     }
     292             : }
     293             : 
     294             : /**
     295             :  * LoadRPCTxtFile
     296             :  */
     297           1 : char **GDALMDReaderALOS::LoadRPCTxtFile()
     298             : {
     299           1 :     if (m_osRPBSourceFilename.empty())
     300           0 :         return nullptr;
     301             : 
     302           2 :     const CPLStringList aosLines(CSLLoad(m_osRPBSourceFilename));
     303           1 :     if (aosLines.empty())
     304           0 :         return nullptr;
     305             : 
     306           1 :     const char *pszFirstRow = aosLines[0];
     307           2 :     CPLStringList aosRPB;
     308           1 :     if (nullptr != pszFirstRow)
     309             :     {
     310             :         static const struct
     311             :         {
     312             :             const char *pszName;
     313             :             int nSize;
     314             :         } apsFieldDescriptors[] = {
     315             :             {RPC_LINE_OFF, 6},     {RPC_SAMP_OFF, 5},   {RPC_LAT_OFF, 8},
     316             :             {RPC_LONG_OFF, 9},     {RPC_HEIGHT_OFF, 5}, {RPC_LINE_SCALE, 6},
     317             :             {RPC_SAMP_SCALE, 5},   {RPC_LAT_SCALE, 8},  {RPC_LONG_SCALE, 9},
     318             :             {RPC_HEIGHT_SCALE, 5},
     319             :         };
     320             : 
     321           1 :         int nRequiredSize = 0;
     322          11 :         for (const auto &sFieldDescriptor : apsFieldDescriptors)
     323             :         {
     324          10 :             nRequiredSize += sFieldDescriptor.nSize;
     325             :         }
     326             : 
     327             :         static const char *const apszRPCTXT20ValItems[] = {
     328             :             RPC_LINE_NUM_COEFF, RPC_LINE_DEN_COEFF, RPC_SAMP_NUM_COEFF,
     329             :             RPC_SAMP_DEN_COEFF};
     330             : 
     331           1 :         constexpr int RPC_COEFF_COUNT1 = CPL_ARRAYSIZE(apszRPCTXT20ValItems);
     332           1 :         constexpr int RPC_COEFF_COUNT2 = 20;
     333           1 :         constexpr int RPC_COEFF_SIZE = 12;
     334           1 :         nRequiredSize += RPC_COEFF_COUNT1 * RPC_COEFF_COUNT2 * RPC_COEFF_SIZE;
     335           1 :         if (strlen(pszFirstRow) < static_cast<size_t>(nRequiredSize))
     336             :         {
     337           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     338             :                      "%s has only %d bytes wherea %d are required",
     339           0 :                      m_osRPBSourceFilename.c_str(), int(strlen(pszFirstRow)),
     340             :                      nRequiredSize);
     341           0 :             return nullptr;
     342             :         }
     343             : 
     344           1 :         int nOffset = 0;
     345           1 :         char buff[16] = {0};
     346          11 :         for (const auto &sFieldDescriptor : apsFieldDescriptors)
     347             :         {
     348          10 :             CPLAssert(sFieldDescriptor.nSize < int(sizeof(buff)));
     349          10 :             memcpy(buff, pszFirstRow + nOffset, sFieldDescriptor.nSize);
     350          10 :             buff[sFieldDescriptor.nSize] = 0;
     351          10 :             aosRPB.SetNameValue(sFieldDescriptor.pszName, buff);
     352          10 :             nOffset += sFieldDescriptor.nSize;
     353             :         }
     354             : 
     355           5 :         for (const char *pszItem : apszRPCTXT20ValItems)
     356             :         {
     357           8 :             std::string osValue;
     358          84 :             for (int j = 0; j < RPC_COEFF_COUNT2; j++)
     359             :             {
     360          80 :                 memcpy(buff, pszFirstRow + nOffset, RPC_COEFF_SIZE);
     361          80 :                 buff[RPC_COEFF_SIZE] = 0;
     362          80 :                 nOffset += RPC_COEFF_SIZE;
     363             : 
     364          80 :                 if (!osValue.empty())
     365          76 :                     osValue += " ";
     366          80 :                 osValue += buff;
     367             :             }
     368           4 :             aosRPB.SetNameValue(pszItem, osValue.c_str());
     369             :         }
     370             :     }
     371             : 
     372           1 :     return aosRPB.StealList();
     373             : }
     374             : 
     375             : /**
     376             :  * GetAcqisitionTimeFromString()
     377             :  */
     378           1 : GIntBig GDALMDReaderALOS::GetAcquisitionTimeFromString(const char *pszDateTime)
     379             : {
     380           1 :     if (nullptr == pszDateTime)
     381           0 :         return 0;
     382             : 
     383             :     int iYear;
     384             :     int iMonth;
     385             :     int iDay;
     386             :     int iHours;
     387             :     int iMin;
     388             :     int iSec;
     389             : 
     390           1 :     int r = sscanf(pszDateTime, "%4d%2d%2d %d:%d:%d.%*d", &iYear, &iMonth,
     391             :                    &iDay, &iHours, &iMin, &iSec);
     392             : 
     393           1 :     if (r != 6)
     394           0 :         return 0;
     395             : 
     396             :     struct tm tmDateTime;
     397           1 :     tmDateTime.tm_sec = iSec;
     398           1 :     tmDateTime.tm_min = iMin;
     399           1 :     tmDateTime.tm_hour = iHours;
     400           1 :     tmDateTime.tm_mday = iDay;
     401           1 :     tmDateTime.tm_mon = iMonth - 1;
     402           1 :     tmDateTime.tm_year = iYear - 1900;
     403           1 :     tmDateTime.tm_isdst = -1;
     404             : 
     405           1 :     return CPLYMDHMSToUnixTime(&tmDateTime);
     406             : }

Generated by: LCOV version 1.14