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 5895 : GDALMDReaderEROS::GDALMDReaderEROS(const char *pszPath,
30 5895 : CSLConstList papszSiblingFiles)
31 5895 : : GDALMDReaderBase(pszPath, papszSiblingFiles)
32 : {
33 5895 : const CPLString osBaseName = CPLGetBasenameSafe(pszPath);
34 5895 : const CPLString osDirName = CPLGetDirnameSafe(pszPath);
35 5895 : char szMetadataName[512] = {0};
36 : size_t i;
37 5895 : 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 11790 : CPLErrorStateBackuper oBackuper(CPLQuietErrorHandler);
43 :
44 64722 : for (i = 0; i < osBaseName.size(); i++)
45 : {
46 58827 : 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 58827 : szMetadataName[i] = osBaseName[i];
67 : }
68 :
69 5895 : if (m_osIMDSourceFilename.empty())
70 : {
71 : std::string osPassFileName =
72 11790 : CPLFormFilenameSafe(osDirName, szMetadataName, "pass");
73 5895 : if (CPLCheckForFile(&osPassFileName[0], papszSiblingFiles))
74 : {
75 1 : m_osIMDSourceFilename = std::move(osPassFileName);
76 : }
77 : else
78 : {
79 : osPassFileName =
80 5894 : CPLFormFilenameSafe(osDirName, szMetadataName, "PASS");
81 5894 : if (CPLCheckForFile(&osPassFileName[0], papszSiblingFiles))
82 : {
83 0 : m_osIMDSourceFilename = std::move(osPassFileName);
84 : }
85 : }
86 : }
87 :
88 : std::string osRPCFileName =
89 11790 : CPLFormFilenameSafe(osDirName, szMetadataName, "rpc");
90 5895 : if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
91 : {
92 1 : m_osRPBSourceFilename = std::move(osRPCFileName);
93 : }
94 : else
95 : {
96 : osRPCFileName =
97 5894 : CPLFormFilenameSafe(osDirName, szMetadataName, GDAL_MDD_RPC);
98 5894 : if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
99 : {
100 0 : m_osRPBSourceFilename = std::move(osRPCFileName);
101 : }
102 : }
103 :
104 5895 : if (!m_osIMDSourceFilename.empty())
105 1 : CPLDebug("MDReaderEROS", "IMD Filename: %s",
106 : m_osIMDSourceFilename.c_str());
107 5895 : if (!m_osRPBSourceFilename.empty())
108 1 : CPLDebug("MDReaderEROS", "RPB Filename: %s",
109 : m_osRPBSourceFilename.c_str());
110 : }
111 :
112 : /**
113 : * ~GDALMDReaderEROS()
114 : */
115 11790 : GDALMDReaderEROS::~GDALMDReaderEROS()
116 : {
117 11790 : }
118 :
119 : /**
120 : * HasRequiredFiles()
121 : */
122 5895 : bool GDALMDReaderEROS::HasRequiredFiles() const
123 : {
124 5895 : if (!m_osIMDSourceFilename.empty())
125 1 : return true;
126 5894 : if (!m_osRPBSourceFilename.empty())
127 0 : return true;
128 :
129 5894 : return false;
130 : }
131 :
132 : /**
133 : * GetMetadataFiles()
134 : */
135 1 : char **GDALMDReaderEROS::GetMetadataFiles() const
136 : {
137 1 : char **papszFileList = nullptr;
138 1 : if (!m_osIMDSourceFilename.empty())
139 1 : papszFileList = CSLAddString(papszFileList, m_osIMDSourceFilename);
140 1 : if (!m_osRPBSourceFilename.empty())
141 1 : papszFileList = CSLAddString(papszFileList, m_osRPBSourceFilename);
142 1 : return papszFileList;
143 : }
144 :
145 : /**
146 : * LoadMetadata()
147 : */
148 2 : void GDALMDReaderEROS::LoadMetadata()
149 : {
150 2 : if (m_bIsMetadataLoad)
151 1 : return;
152 :
153 1 : if (!m_osIMDSourceFilename.empty())
154 : {
155 1 : m_papszIMDMD = LoadImdTxtFile();
156 : }
157 :
158 1 : if (!m_osRPBSourceFilename.empty())
159 : {
160 1 : m_papszRPCMD = GDALLoadRPCFile(m_osRPBSourceFilename);
161 : }
162 :
163 1 : m_papszDEFAULTMD =
164 1 : CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "EROS");
165 :
166 1 : m_bIsMetadataLoad = true;
167 :
168 1 : const char *pszSatId1 = CSLFetchNameValue(m_papszIMDMD, "satellite");
169 1 : const char *pszSatId2 = CSLFetchNameValue(m_papszIMDMD, "camera");
170 1 : if (nullptr != pszSatId1 && nullptr != pszSatId2)
171 : {
172 2 : m_papszIMAGERYMD = CSLAddNameValue(
173 : m_papszIMAGERYMD, GDALMD_SATELLITEID,
174 2 : CPLSPrintf("%s %s", CPLStripQuotes(pszSatId1).c_str(),
175 2 : CPLStripQuotes(pszSatId2).c_str()));
176 : }
177 0 : else if (nullptr != pszSatId1 && nullptr == pszSatId2)
178 : {
179 0 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, GDALMD_SATELLITEID,
180 0 : CPLStripQuotes(pszSatId1));
181 : }
182 0 : else if (nullptr == pszSatId1 && nullptr != pszSatId2)
183 : {
184 0 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, GDALMD_SATELLITEID,
185 0 : CPLStripQuotes(pszSatId2));
186 : }
187 :
188 1 : const char *pszCloudCover = CSLFetchNameValue(m_papszIMDMD, "overall_cc");
189 1 : if (nullptr != pszCloudCover)
190 : {
191 1 : int nCC = atoi(pszCloudCover);
192 1 : if (nCC > 100 || nCC < 0)
193 : {
194 0 : m_papszIMAGERYMD = CSLAddNameValue(
195 : m_papszIMAGERYMD, GDALMD_CLOUDCOVER, MD_CLOUDCOVER_NA);
196 : }
197 : else
198 : {
199 1 : m_papszIMAGERYMD = CSLAddNameValue(
200 : m_papszIMAGERYMD, GDALMD_CLOUDCOVER, CPLSPrintf("%d", nCC));
201 : }
202 : }
203 :
204 1 : const char *pszDate = CSLFetchNameValue(m_papszIMDMD, "sweep_start_utc");
205 1 : if (nullptr != pszDate)
206 : {
207 : char buffer[80];
208 1 : GIntBig timeMid = GetAcquisitionTimeFromString(CPLStripQuotes(pszDate));
209 : struct tm tmBuf;
210 1 : strftime(buffer, 80, MD_DATETIMEFORMAT,
211 1 : CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
212 1 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
213 : GDALMD_ACQUISITIONDATETIME, buffer);
214 : }
215 : }
216 :
217 : /**
218 : * LoadImdTxtFile
219 : */
220 1 : char **GDALMDReaderEROS::LoadImdTxtFile()
221 : {
222 1 : char **papszLines = CSLLoad(m_osIMDSourceFilename);
223 1 : if (nullptr == papszLines)
224 0 : return nullptr;
225 :
226 1 : char **papszIMD = nullptr;
227 :
228 10 : for (int i = 0; papszLines[i] != nullptr; i++)
229 : {
230 9 : const char *pszLine = papszLines[i];
231 9 : if (CPLStrnlen(pszLine, 21) >= 21)
232 : {
233 : char szName[22];
234 9 : memcpy(szName, pszLine, 21);
235 9 : szName[21] = 0;
236 9 : char *pszSpace = strchr(szName, ' ');
237 9 : if (pszSpace)
238 : {
239 9 : *pszSpace = 0;
240 9 : papszIMD = CSLAddNameValue(papszIMD, szName, pszLine + 20);
241 : }
242 : }
243 : }
244 :
245 1 : CSLDestroy(papszLines);
246 :
247 1 : return papszIMD;
248 : }
249 :
250 : /**
251 : * GetAcqisitionTimeFromString()
252 : */
253 1 : GIntBig GDALMDReaderEROS::GetAcquisitionTimeFromString(const char *pszDateTime)
254 : {
255 1 : if (nullptr == pszDateTime)
256 0 : return 0;
257 :
258 : int iYear;
259 : int iMonth;
260 : int iDay;
261 : int iHours;
262 : int iMin;
263 : int iSec;
264 :
265 : // example: sweep_start_utc 2013-04-22,11:35:02.50724
266 :
267 1 : int r = sscanf(pszDateTime, "%d-%d-%d,%d:%d:%d.%*d", &iYear, &iMonth, &iDay,
268 : &iHours, &iMin, &iSec);
269 :
270 1 : if (r != 6)
271 0 : return 0;
272 :
273 : struct tm tmDateTime;
274 1 : tmDateTime.tm_sec = iSec;
275 1 : tmDateTime.tm_min = iMin;
276 1 : tmDateTime.tm_hour = iHours;
277 1 : tmDateTime.tm_mday = iDay;
278 1 : tmDateTime.tm_mon = iMonth - 1;
279 1 : tmDateTime.tm_year = iYear - 1900;
280 1 : tmDateTime.tm_isdst = -1;
281 :
282 1 : return CPLYMDHMSToUnixTime(&tmDateTime);
283 : }
|