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 : }
|