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