Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Core
4 : * Purpose: Read metadata from EROS 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_eros.h"
16 :
17 : #include <cstddef>
18 : #include <cstdio>
19 : #include <cstdlib>
20 :
21 : #include "cpl_conv.h"
22 : #include "cpl_error.h"
23 : #include "cpl_string.h"
24 : #include "cpl_time.h"
25 :
26 : /**
27 : * GDALMDReaderEROS()
28 : */
29 5837 : GDALMDReaderEROS::GDALMDReaderEROS(const char *pszPath,
30 5837 : CSLConstList papszSiblingFiles)
31 5837 : : GDALMDReaderBase(pszPath, papszSiblingFiles)
32 : {
33 5837 : const CPLString osBaseName = CPLGetBasenameSafe(pszPath);
34 5837 : const CPLString osDirName = CPLGetDirnameSafe(pszPath);
35 5837 : char szMetadataName[512] = {0};
36 : size_t i;
37 5837 : if (osBaseName.size() > 511)
38 0 : return;
39 :
40 : // To shutdown HTTP 403 errors when trying to open .pass side-car file on
41 : // gdalinfo /vsicurl/https://s3.opengeohub.org/global/dtm/v1.2/gedtm_rf_m_30m_s_20060101_20151231_go_epsg.4326.3855_v1.2.tif --debug on
42 11674 : CPLErrorStateBackuper oBackuper(CPLQuietErrorHandler);
43 :
44 64396 : for (i = 0; i < osBaseName.size(); i++)
45 : {
46 58559 : if (STARTS_WITH_CI(osBaseName + i, "."))
47 : {
48 : std::string osPassFileName =
49 97 : CPLFormFilenameSafe(osDirName, szMetadataName, "pass");
50 97 : if (CPLCheckForFile(&osPassFileName[0], papszSiblingFiles))
51 : {
52 0 : m_osIMDSourceFilename = std::move(osPassFileName);
53 0 : break;
54 : }
55 : else
56 : {
57 : osPassFileName =
58 97 : CPLFormFilenameSafe(osDirName, szMetadataName, "PASS");
59 97 : if (CPLCheckForFile(&osPassFileName[0], papszSiblingFiles))
60 : {
61 0 : m_osIMDSourceFilename = std::move(osPassFileName);
62 0 : break;
63 : }
64 : }
65 : }
66 58559 : szMetadataName[i] = osBaseName[i];
67 : }
68 :
69 5837 : if (m_osIMDSourceFilename.empty())
70 : {
71 : std::string osPassFileName =
72 11674 : CPLFormFilenameSafe(osDirName, szMetadataName, "pass");
73 5837 : if (CPLCheckForFile(&osPassFileName[0], papszSiblingFiles))
74 : {
75 1 : m_osIMDSourceFilename = std::move(osPassFileName);
76 : }
77 : else
78 : {
79 : osPassFileName =
80 5836 : CPLFormFilenameSafe(osDirName, szMetadataName, "PASS");
81 5836 : if (CPLCheckForFile(&osPassFileName[0], papszSiblingFiles))
82 : {
83 0 : m_osIMDSourceFilename = std::move(osPassFileName);
84 : }
85 : }
86 : }
87 :
88 : std::string osRPCFileName =
89 11674 : CPLFormFilenameSafe(osDirName, szMetadataName, "rpc");
90 5837 : if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
91 : {
92 1 : m_osRPBSourceFilename = std::move(osRPCFileName);
93 : }
94 : else
95 : {
96 5836 : osRPCFileName = CPLFormFilenameSafe(osDirName, szMetadataName, "RPC");
97 5836 : if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
98 : {
99 0 : m_osRPBSourceFilename = std::move(osRPCFileName);
100 : }
101 : }
102 :
103 5837 : if (!m_osIMDSourceFilename.empty())
104 1 : CPLDebug("MDReaderEROS", "IMD Filename: %s",
105 : m_osIMDSourceFilename.c_str());
106 5837 : if (!m_osRPBSourceFilename.empty())
107 1 : CPLDebug("MDReaderEROS", "RPB Filename: %s",
108 : m_osRPBSourceFilename.c_str());
109 : }
110 :
111 : /**
112 : * ~GDALMDReaderEROS()
113 : */
114 11674 : GDALMDReaderEROS::~GDALMDReaderEROS()
115 : {
116 11674 : }
117 :
118 : /**
119 : * HasRequiredFiles()
120 : */
121 5837 : bool GDALMDReaderEROS::HasRequiredFiles() const
122 : {
123 5837 : if (!m_osIMDSourceFilename.empty())
124 1 : return true;
125 5836 : if (!m_osRPBSourceFilename.empty())
126 0 : return true;
127 :
128 5836 : return false;
129 : }
130 :
131 : /**
132 : * GetMetadataFiles()
133 : */
134 1 : char **GDALMDReaderEROS::GetMetadataFiles() const
135 : {
136 1 : char **papszFileList = nullptr;
137 1 : if (!m_osIMDSourceFilename.empty())
138 1 : papszFileList = CSLAddString(papszFileList, m_osIMDSourceFilename);
139 1 : if (!m_osRPBSourceFilename.empty())
140 1 : papszFileList = CSLAddString(papszFileList, m_osRPBSourceFilename);
141 1 : return papszFileList;
142 : }
143 :
144 : /**
145 : * LoadMetadata()
146 : */
147 2 : void GDALMDReaderEROS::LoadMetadata()
148 : {
149 2 : if (m_bIsMetadataLoad)
150 1 : return;
151 :
152 1 : if (!m_osIMDSourceFilename.empty())
153 : {
154 1 : m_papszIMDMD = LoadImdTxtFile();
155 : }
156 :
157 1 : if (!m_osRPBSourceFilename.empty())
158 : {
159 1 : m_papszRPCMD = GDALLoadRPCFile(m_osRPBSourceFilename);
160 : }
161 :
162 1 : m_papszDEFAULTMD =
163 1 : CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "EROS");
164 :
165 1 : m_bIsMetadataLoad = true;
166 :
167 1 : const char *pszSatId1 = CSLFetchNameValue(m_papszIMDMD, "satellite");
168 1 : const char *pszSatId2 = CSLFetchNameValue(m_papszIMDMD, "camera");
169 1 : if (nullptr != pszSatId1 && nullptr != pszSatId2)
170 : {
171 2 : m_papszIMAGERYMD = CSLAddNameValue(
172 : m_papszIMAGERYMD, MD_NAME_SATELLITE,
173 2 : CPLSPrintf("%s %s", CPLStripQuotes(pszSatId1).c_str(),
174 2 : CPLStripQuotes(pszSatId2).c_str()));
175 : }
176 0 : else if (nullptr != pszSatId1 && nullptr == pszSatId2)
177 : {
178 0 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
179 0 : CPLStripQuotes(pszSatId1));
180 : }
181 0 : else if (nullptr == pszSatId1 && nullptr != pszSatId2)
182 : {
183 0 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
184 0 : CPLStripQuotes(pszSatId2));
185 : }
186 :
187 1 : const char *pszCloudCover = CSLFetchNameValue(m_papszIMDMD, "overall_cc");
188 1 : if (nullptr != pszCloudCover)
189 : {
190 1 : int nCC = atoi(pszCloudCover);
191 1 : if (nCC > 100 || nCC < 0)
192 : {
193 0 : m_papszIMAGERYMD = CSLAddNameValue(
194 : m_papszIMAGERYMD, MD_NAME_CLOUDCOVER, MD_CLOUDCOVER_NA);
195 : }
196 : else
197 : {
198 1 : m_papszIMAGERYMD = CSLAddNameValue(
199 : m_papszIMAGERYMD, MD_NAME_CLOUDCOVER, CPLSPrintf("%d", nCC));
200 : }
201 : }
202 :
203 1 : const char *pszDate = CSLFetchNameValue(m_papszIMDMD, "sweep_start_utc");
204 1 : if (nullptr != pszDate)
205 : {
206 : char buffer[80];
207 1 : GIntBig timeMid = GetAcquisitionTimeFromString(CPLStripQuotes(pszDate));
208 : struct tm tmBuf;
209 1 : strftime(buffer, 80, MD_DATETIMEFORMAT,
210 1 : CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
211 1 : m_papszIMAGERYMD =
212 1 : CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_ACQDATETIME, buffer);
213 : }
214 : }
215 :
216 : /**
217 : * LoadImdTxtFile
218 : */
219 1 : char **GDALMDReaderEROS::LoadImdTxtFile()
220 : {
221 1 : char **papszLines = CSLLoad(m_osIMDSourceFilename);
222 1 : if (nullptr == papszLines)
223 0 : return nullptr;
224 :
225 1 : char **papszIMD = nullptr;
226 :
227 10 : for (int i = 0; papszLines[i] != nullptr; i++)
228 : {
229 9 : const char *pszLine = papszLines[i];
230 9 : if (CPLStrnlen(pszLine, 21) >= 21)
231 : {
232 : char szName[22];
233 9 : memcpy(szName, pszLine, 21);
234 9 : szName[21] = 0;
235 9 : char *pszSpace = strchr(szName, ' ');
236 9 : if (pszSpace)
237 : {
238 9 : *pszSpace = 0;
239 9 : papszIMD = CSLAddNameValue(papszIMD, szName, pszLine + 20);
240 : }
241 : }
242 : }
243 :
244 1 : CSLDestroy(papszLines);
245 :
246 1 : return papszIMD;
247 : }
248 :
249 : /**
250 : * GetAcqisitionTimeFromString()
251 : */
252 1 : GIntBig GDALMDReaderEROS::GetAcquisitionTimeFromString(const char *pszDateTime)
253 : {
254 1 : if (nullptr == pszDateTime)
255 0 : return 0;
256 :
257 : int iYear;
258 : int iMonth;
259 : int iDay;
260 : int iHours;
261 : int iMin;
262 : int iSec;
263 :
264 : // example: sweep_start_utc 2013-04-22,11:35:02.50724
265 :
266 1 : int r = sscanf(pszDateTime, "%d-%d-%d,%d:%d:%d.%*d", &iYear, &iMonth, &iDay,
267 : &iHours, &iMin, &iSec);
268 :
269 1 : if (r != 6)
270 0 : return 0;
271 :
272 : struct tm tmDateTime;
273 1 : tmDateTime.tm_sec = iSec;
274 1 : tmDateTime.tm_min = iMin;
275 1 : tmDateTime.tm_hour = iHours;
276 1 : tmDateTime.tm_mday = iDay;
277 1 : tmDateTime.tm_mon = iMonth - 1;
278 1 : tmDateTime.tm_year = iYear - 1900;
279 1 : tmDateTime.tm_isdst = -1;
280 :
281 1 : return CPLYMDHMSToUnixTime(&tmDateTime);
282 : }
|