LCOV - code coverage report
Current view: top level - gcore/mdreader - reader_landsat.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 79 84 94.0 %
Date: 2026-09-22 20:07:52 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Read metadata from Landsat 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_landsat.h"
      16             : 
      17             : #include <cstddef>
      18             : #include <cstring>
      19             : #include <ctime>
      20             : 
      21             : #include "cpl_conv.h"
      22             : #include "cpl_error.h"
      23             : #include "cpl_string.h"
      24             : #include "cpl_time.h"
      25             : 
      26             : /**
      27             :  * GDALMDReaderLandsat()
      28             :  */
      29        5808 : GDALMDReaderLandsat::GDALMDReaderLandsat(const char *pszPath,
      30        5808 :                                          CSLConstList papszSiblingFiles)
      31        5808 :     : GDALMDReaderBase(pszPath, papszSiblingFiles)
      32             : {
      33        5808 :     const std::string osBaseName = CPLGetBasenameSafe(pszPath);
      34        5808 :     const std::string osDirName = CPLGetDirnameSafe(pszPath);
      35        5808 :     size_t nBaseNameLen = osBaseName.size();
      36        5808 :     if (nBaseNameLen > 511)
      37           0 :         return;
      38             : 
      39             :     // split file name by _B or _b
      40        5808 :     char szMetadataName[512] = {0};
      41             :     size_t i;
      42       59806 :     for (i = 0; i < nBaseNameLen; i++)
      43             :     {
      44       54223 :         szMetadataName[i] = osBaseName[i];
      45       54223 :         if (STARTS_WITH_CI(osBaseName.c_str() + i, "_B"))
      46             :         {
      47         225 :             break;
      48             :         }
      49             :     }
      50             : 
      51             :     // Level 2: Surface Reflectance or Surface Temperature
      52       10953 :     if (i > 3 && (STARTS_WITH_CI(osBaseName.c_str() + i - 3, "_SR") ||
      53        5145 :                   STARTS_WITH_CI(osBaseName.c_str() + i - 3, "_ST")))
      54             :     {
      55           1 :         i -= 3;
      56             :     }
      57             : 
      58             :     // form metadata file name
      59        5808 :     CPLStrlcpy(szMetadataName + i, "_MTL.txt", 9);
      60             : 
      61             :     std::string osIMDSourceFilename =
      62       11616 :         CPLFormFilenameSafe(osDirName.c_str(), szMetadataName, nullptr);
      63        5808 :     if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
      64             :     {
      65           3 :         m_osIMDSourceFilename = std::move(osIMDSourceFilename);
      66             :     }
      67             :     else
      68             :     {
      69        5805 :         CPLStrlcpy(szMetadataName + i, "_MTL.TXT", 9);
      70             :         osIMDSourceFilename =
      71        5805 :             CPLFormFilenameSafe(osDirName.c_str(), szMetadataName, nullptr);
      72        5805 :         if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
      73             :         {
      74           0 :             m_osIMDSourceFilename = std::move(osIMDSourceFilename);
      75             :         }
      76             :     }
      77             : 
      78        5808 :     if (!m_osIMDSourceFilename.empty())
      79           3 :         CPLDebug("MDReaderLandsat", "IMD Filename: %s",
      80             :                  m_osIMDSourceFilename.c_str());
      81             : }
      82             : 
      83             : /**
      84             :  * ~GDALMDReaderLandsat()
      85             :  */
      86       11616 : GDALMDReaderLandsat::~GDALMDReaderLandsat()
      87             : {
      88       11616 : }
      89             : 
      90             : /**
      91             :  * HasRequiredFiles()
      92             :  */
      93        5808 : bool GDALMDReaderLandsat::HasRequiredFiles() const
      94             : {
      95        5808 :     if (!m_osIMDSourceFilename.empty())
      96           3 :         return true;
      97             : 
      98        5805 :     return false;
      99             : }
     100             : 
     101             : /**
     102             :  * GetMetadataFiles()
     103             :  */
     104           3 : char **GDALMDReaderLandsat::GetMetadataFiles() const
     105             : {
     106           3 :     char **papszFileList = nullptr;
     107           3 :     if (!m_osIMDSourceFilename.empty())
     108           3 :         papszFileList = CSLAddString(papszFileList, m_osIMDSourceFilename);
     109             : 
     110           3 :     return papszFileList;
     111             : }
     112             : 
     113             : /**
     114             :  * LoadMetadata()
     115             :  */
     116           6 : void GDALMDReaderLandsat::LoadMetadata()
     117             : {
     118           6 :     if (m_bIsMetadataLoad)
     119           3 :         return;
     120             : 
     121           3 :     if (!m_osIMDSourceFilename.empty())
     122             :     {
     123           3 :         m_papszIMDMD = GDALLoadIMDFile(m_osIMDSourceFilename);
     124             :     }
     125             : 
     126           3 :     m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "ODL");
     127             : 
     128           3 :     m_bIsMetadataLoad = true;
     129             : 
     130             :     const bool bL8 =
     131           6 :         CSLFetchNameValue(
     132           3 :             m_papszIMDMD,
     133           3 :             "LANDSAT_METADATA_FILE.IMAGE_ATTRIBUTES.SPACECRAFT_ID") != nullptr;
     134             : 
     135             :     // date/time
     136             :     // DATE_ACQUIRED = 2013-04-07
     137             :     // SCENE_CENTER_TIME = 15:47:03.0882620Z
     138             : 
     139             :     // L1_METADATA_FILE.PRODUCT_METADATA.SPACECRAFT_ID
     140           3 :     const char *pszSatId = CSLFetchNameValue(
     141           3 :         m_papszIMDMD,
     142             :         bL8 ? "LANDSAT_METADATA_FILE.IMAGE_ATTRIBUTES.SPACECRAFT_ID"
     143             :             : "L1_METADATA_FILE.PRODUCT_METADATA.SPACECRAFT_ID");
     144           3 :     if (nullptr != pszSatId)
     145             :     {
     146           3 :         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, GDALMD_SATELLITEID,
     147           6 :                                            CPLStripQuotes(pszSatId));
     148             :     }
     149             : 
     150             :     // L1_METADATA_FILE.IMAGE_ATTRIBUTES.CLOUD_COVER
     151           3 :     const char *pszCloudCover = CSLFetchNameValue(
     152           3 :         m_papszIMDMD, bL8 ? "LANDSAT_METADATA_FILE.IMAGE_ATTRIBUTES.CLOUD_COVER"
     153             :                           : "L1_METADATA_FILE.IMAGE_ATTRIBUTES.CLOUD_COVER");
     154           3 :     if (nullptr != pszCloudCover)
     155             :     {
     156           3 :         double fCC = CPLAtofM(pszCloudCover);
     157           3 :         if (fCC < 0)
     158             :         {
     159           0 :             m_papszIMAGERYMD = CSLAddNameValue(
     160             :                 m_papszIMAGERYMD, GDALMD_CLOUDCOVER, MD_CLOUDCOVER_NA);
     161             :         }
     162             :         else
     163             :         {
     164           3 :             m_papszIMAGERYMD =
     165           3 :                 CSLAddNameValue(m_papszIMAGERYMD, GDALMD_CLOUDCOVER,
     166           3 :                                 fCC == std::round(fCC) && fCC < INT_MAX
     167           0 :                                     ? CPLSPrintf("%d", int(fCC))
     168           3 :                                     : CPLSPrintf("%.02f", fCC));
     169             :         }
     170             :     }
     171             : 
     172             :     // L1_METADATA_FILE.PRODUCT_METADATA.ACQUISITION_DATE
     173             :     // L1_METADATA_FILE.PRODUCT_METADATA.SCENE_CENTER_SCAN_TIME
     174             : 
     175             :     // L1_METADATA_FILE.PRODUCT_METADATA.DATE_ACQUIRED
     176             :     // L1_METADATA_FILE.PRODUCT_METADATA.SCENE_CENTER_TIME
     177             : 
     178           3 :     const char *pszDate = CSLFetchNameValue(
     179           3 :         m_papszIMDMD,
     180             :         bL8 ? "LANDSAT_METADATA_FILE.IMAGE_ATTRIBUTES.DATE_ACQUIRED"
     181             :             : "L1_METADATA_FILE.PRODUCT_METADATA.ACQUISITION_DATE");
     182           3 :     if (nullptr == pszDate)
     183             :     {
     184           1 :         pszDate = CSLFetchNameValue(
     185           1 :             m_papszIMDMD, "L1_METADATA_FILE.PRODUCT_METADATA.DATE_ACQUIRED");
     186             :     }
     187             : 
     188           3 :     if (nullptr != pszDate)
     189             :     {
     190           3 :         const char *pszTime = CSLFetchNameValue(
     191           3 :             m_papszIMDMD,
     192             :             bL8 ? "LANDSAT_METADATA_FILE.IMAGE_ATTRIBUTES.SCENE_CENTER_TIME"
     193             :                 : "L1_METADATA_FILE.PRODUCT_METADATA.SCENE_CENTER_SCAN_TIME");
     194           3 :         if (nullptr == pszTime)
     195             :         {
     196           1 :             pszTime = CSLFetchNameValue(
     197           1 :                 m_papszIMDMD,
     198             :                 "L1_METADATA_FILE.PRODUCT_METADATA.SCENE_CENTER_TIME");
     199             :         }
     200           3 :         if (nullptr == pszTime)
     201           0 :             pszTime = "00:00:00.000000Z";
     202             : 
     203           3 :         std::string osTime(pszTime);
     204           3 :         if (osTime.size() > 2 && osTime.front() == '"' && osTime.back() == '"')
     205           2 :             osTime = osTime.substr(1, osTime.size() - 2);
     206             : 
     207             :         char buffer[80];
     208           3 :         GIntBig timeMid = GetAcquisitionTimeFromString(
     209           3 :             CPLSPrintf("%sT%s", pszDate, osTime.c_str()));
     210             :         struct tm tmBuf;
     211           3 :         strftime(buffer, 80, MD_DATETIMEFORMAT,
     212           3 :                  CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
     213           3 :         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
     214             :                                            GDALMD_ACQUISITIONDATETIME, buffer);
     215             :     }
     216             : }

Generated by: LCOV version 1.14