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

Generated by: LCOV version 1.14