Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Core
4 : * Purpose: Read metadata from GeoEye 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_geo_eye.h"
16 :
17 : #include <cstddef>
18 : #include <cstdio>
19 : #include <cstring>
20 :
21 : #include <string>
22 :
23 : #include "cpl_conv.h"
24 : #include "cpl_error.h"
25 : #include "cpl_string.h"
26 : #include "cpl_time.h"
27 :
28 : /**
29 : * GDALMDReaderGeoEye()
30 : */
31 5112 : GDALMDReaderGeoEye::GDALMDReaderGeoEye(const char *pszPath,
32 5112 : char **papszSiblingFiles)
33 5112 : : GDALMDReaderBase(pszPath, papszSiblingFiles)
34 : {
35 :
36 10224 : const CPLString osBaseName = CPLGetBasename(pszPath);
37 10224 : const CPLString osDirName = CPLGetDirname(pszPath);
38 :
39 : // get _metadata.txt file
40 :
41 : // split file name by _rgb_ or _pan_
42 10224 : CPLString osRadixMetadataName(osBaseName);
43 5112 : size_t i = osRadixMetadataName.ifind("_rgb_");
44 5112 : if (i == std::string::npos)
45 5106 : i = osRadixMetadataName.ifind("_pan_");
46 5112 : if (i != std::string::npos)
47 6 : osRadixMetadataName.resize(i);
48 :
49 : // form metadata file name
50 : std::string osIMDSourceFilename = CPLFormFilename(
51 15336 : osDirName, (osRadixMetadataName + "_metadata.txt").c_str(), nullptr);
52 5112 : if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
53 : {
54 5 : m_osIMDSourceFilename = std::move(osIMDSourceFilename);
55 : }
56 : else
57 : {
58 : osIMDSourceFilename = CPLFormFilename(
59 10214 : osDirName, (osRadixMetadataName + "_METADATA.txt").c_str(),
60 5107 : nullptr);
61 5107 : if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
62 : {
63 0 : m_osIMDSourceFilename = std::move(osIMDSourceFilename);
64 : }
65 : }
66 :
67 : // get _rpc.txt file
68 :
69 : std::string osRPBSourceFilename =
70 15336 : CPLFormFilename(osDirName, (osBaseName + "_rpc").c_str(), "txt");
71 5112 : if (CPLCheckForFile(&osRPBSourceFilename[0], papszSiblingFiles))
72 : {
73 12 : m_osRPBSourceFilename = std::move(osRPBSourceFilename);
74 : }
75 : else
76 : {
77 : osRPBSourceFilename =
78 5100 : CPLFormFilename(osDirName, (osBaseName + "_RPC").c_str(), "TXT");
79 5100 : if (CPLCheckForFile(&osRPBSourceFilename[0], papszSiblingFiles))
80 : {
81 0 : m_osRPBSourceFilename = std::move(osRPBSourceFilename);
82 : }
83 : }
84 :
85 5112 : if (!m_osIMDSourceFilename.empty())
86 5 : CPLDebug("MDReaderGeoEye", "IMD Filename: %s",
87 : m_osIMDSourceFilename.c_str());
88 5112 : if (!m_osRPBSourceFilename.empty())
89 12 : CPLDebug("MDReaderGeoEye", "RPB Filename: %s",
90 : m_osRPBSourceFilename.c_str());
91 5112 : }
92 :
93 : /**
94 : * ~GDALMDReaderGeoEye()
95 : */
96 10224 : GDALMDReaderGeoEye::~GDALMDReaderGeoEye()
97 : {
98 10224 : }
99 :
100 : /**
101 : * HasRequiredFiles()
102 : */
103 5112 : bool GDALMDReaderGeoEye::HasRequiredFiles() const
104 : {
105 5112 : if (!m_osIMDSourceFilename.empty())
106 5 : return true;
107 :
108 5107 : if (!m_osRPBSourceFilename.empty())
109 7 : return true;
110 :
111 5100 : return false;
112 : }
113 :
114 : /**
115 : * GetMetadataFiles()
116 : */
117 12 : char **GDALMDReaderGeoEye::GetMetadataFiles() const
118 : {
119 12 : char **papszFileList = nullptr;
120 12 : if (!m_osIMDSourceFilename.empty())
121 5 : papszFileList = CSLAddString(papszFileList, m_osIMDSourceFilename);
122 12 : if (!m_osRPBSourceFilename.empty())
123 12 : papszFileList = CSLAddString(papszFileList, m_osRPBSourceFilename);
124 :
125 12 : return papszFileList;
126 : }
127 :
128 : /**
129 : * LoadMetadata()
130 : */
131 24 : void GDALMDReaderGeoEye::LoadMetadata()
132 : {
133 24 : if (m_bIsMetadataLoad)
134 12 : return;
135 :
136 12 : if (!m_osIMDSourceFilename.empty())
137 : {
138 5 : m_papszIMDMD = LoadIMDWktFile();
139 : }
140 :
141 12 : if (!m_osRPBSourceFilename.empty())
142 : {
143 12 : m_papszRPCMD = GDALLoadRPCFile(m_osRPBSourceFilename);
144 : }
145 :
146 12 : m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "GE");
147 :
148 12 : m_bIsMetadataLoad = true;
149 :
150 12 : if (nullptr == m_papszIMDMD)
151 : {
152 7 : return;
153 : }
154 :
155 : // extract imagery metadata
156 : const char *pszSatId =
157 5 : CSLFetchNameValue(m_papszIMDMD, "Source Image Metadata.Sensor");
158 5 : if (nullptr != pszSatId)
159 : {
160 5 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
161 10 : CPLStripQuotes(pszSatId));
162 : }
163 :
164 10 : const char *pszCloudCover = CSLFetchNameValue(
165 5 : m_papszIMDMD, "Source Image Metadata.Percent Cloud Cover");
166 5 : if (nullptr != pszCloudCover)
167 : {
168 5 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
169 : pszCloudCover);
170 : }
171 :
172 10 : const char *pszDateTime = CSLFetchNameValue(
173 5 : m_papszIMDMD, "Source Image Metadata.Acquisition Date/Time");
174 :
175 5 : if (nullptr != pszDateTime)
176 : {
177 : char buffer[80];
178 5 : GIntBig timeMid = GetAcquisitionTimeFromString(pszDateTime);
179 :
180 : struct tm tmBuf;
181 5 : strftime(buffer, 80, MD_DATETIMEFORMAT,
182 5 : CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
183 5 : m_papszIMAGERYMD =
184 5 : CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_ACQDATETIME, buffer);
185 : }
186 : }
187 :
188 : /**
189 : * GetAcqisitionTimeFromString()
190 : */
191 : GIntBig
192 5 : GDALMDReaderGeoEye::GetAcquisitionTimeFromString(const char *pszDateTime)
193 : {
194 5 : if (nullptr == pszDateTime)
195 0 : return 0;
196 :
197 : int iYear;
198 : int iMonth;
199 : int iDay;
200 : int iHours;
201 : int iMin;
202 5 : int iSec = 0;
203 :
204 : // string example: Acquisition Date/Time: 2006-03-01 11:08 GMT
205 :
206 5 : int r = sscanf(pszDateTime, "%d-%d-%d %d:%d GMT", &iYear, &iMonth, &iDay,
207 : &iHours, &iMin);
208 :
209 5 : if (r != 5)
210 0 : return 0;
211 :
212 : struct tm tmDateTime;
213 5 : tmDateTime.tm_sec = iSec;
214 5 : tmDateTime.tm_min = iMin;
215 5 : tmDateTime.tm_hour = iHours;
216 5 : tmDateTime.tm_mday = iDay;
217 5 : tmDateTime.tm_mon = iMonth - 1;
218 5 : tmDateTime.tm_year = iYear - 1900;
219 5 : tmDateTime.tm_isdst = -1;
220 :
221 5 : return CPLYMDHMSToUnixTime(&tmDateTime);
222 : }
223 :
224 : /**
225 : * LoadWKTIMDFile()
226 : */
227 5 : char **GDALMDReaderGeoEye::LoadIMDWktFile() const
228 : {
229 5 : char **papszResultList = nullptr;
230 5 : char **papszLines = CSLLoad(m_osIMDSourceFilename);
231 5 : bool bBeginSection = false;
232 10 : CPLString osSection;
233 10 : CPLString osKeyLevel1;
234 10 : CPLString osKeyLevel2;
235 10 : CPLString osKeyLevel3;
236 5 : int nLevel = 0;
237 : int nSpaceCount;
238 :
239 5 : if (papszLines == nullptr)
240 0 : return nullptr;
241 :
242 475 : for (int i = 0; papszLines[i] != nullptr; i++)
243 : {
244 : // skip section (=== or ---) lines
245 :
246 470 : if (STARTS_WITH_CI(papszLines[i], "==="))
247 : {
248 30 : bBeginSection = true;
249 120 : continue;
250 : }
251 :
252 870 : if (STARTS_WITH_CI(papszLines[i], "---") ||
253 430 : CPLStrnlen(papszLines[i], 512) == 0)
254 90 : continue;
255 :
256 : // check the metadata level
257 350 : nSpaceCount = 0;
258 590 : for (int j = 0; j < 11; j++)
259 : {
260 590 : if (papszLines[i][j] != ' ')
261 350 : break;
262 240 : nSpaceCount++;
263 : }
264 :
265 350 : if (nSpaceCount % 3 != 0)
266 0 : continue; // not a metadata item
267 350 : nLevel = nSpaceCount / 3;
268 :
269 : const char *pszValue;
270 350 : char *pszKey = nullptr;
271 350 : pszValue = CPLParseNameValue(papszLines[i], &pszKey);
272 :
273 350 : if (nullptr != pszValue && CPLStrnlen(pszValue, 512) > 0)
274 : {
275 :
276 310 : CPLString osCurrentKey;
277 310 : if (nLevel == 0)
278 : {
279 230 : osCurrentKey = CPLOPrintf("%s", pszKey);
280 : }
281 80 : else if (nLevel == 1)
282 : {
283 : osCurrentKey =
284 80 : osKeyLevel1 + "." + CPLOPrintf("%s", pszKey + nSpaceCount);
285 : }
286 0 : else if (nLevel == 2)
287 : {
288 0 : osCurrentKey = osKeyLevel1 + "." + osKeyLevel2 + "." +
289 0 : CPLOPrintf("%s", pszKey + nSpaceCount);
290 : }
291 0 : else if (nLevel == 3)
292 : {
293 0 : osCurrentKey = osKeyLevel1 + "." + osKeyLevel2 + "." +
294 0 : osKeyLevel3 + "." +
295 0 : CPLOPrintf("%s", pszKey + nSpaceCount);
296 : }
297 :
298 310 : if (!osSection.empty())
299 : {
300 305 : osCurrentKey = osSection + "." + osCurrentKey;
301 : }
302 :
303 : papszResultList =
304 310 : CSLAddNameValue(papszResultList, osCurrentKey, pszValue);
305 : }
306 :
307 350 : if (nullptr != pszKey && CPLStrnlen(pszKey, 512) > 0)
308 : {
309 310 : if (bBeginSection)
310 : {
311 5 : osSection = CPLOPrintf("%s", pszKey);
312 5 : bBeginSection = false;
313 : }
314 305 : else if (nLevel == 0)
315 : {
316 225 : osKeyLevel1 = CPLOPrintf("%s", pszKey);
317 : }
318 80 : else if (nLevel == 1)
319 : {
320 80 : osKeyLevel2 = CPLOPrintf("%s", pszKey + nSpaceCount);
321 : }
322 0 : else if (nLevel == 2)
323 : {
324 0 : osKeyLevel3 = CPLOPrintf("%s", pszKey + nSpaceCount);
325 : }
326 : }
327 : else
328 : {
329 40 : if (bBeginSection)
330 : {
331 20 : osSection = CPLOPrintf("%s", papszLines[i]);
332 20 : bBeginSection = false;
333 : }
334 20 : else if (nLevel == 0)
335 : {
336 20 : osKeyLevel1 = CPLOPrintf("%s", papszLines[i]);
337 : }
338 0 : else if (nLevel == 1)
339 : {
340 0 : osKeyLevel2 = CPLOPrintf("%s", papszLines[i] + nSpaceCount);
341 : }
342 0 : else if (nLevel == 2)
343 : {
344 0 : osKeyLevel3 = CPLOPrintf("%s", papszLines[i] + nSpaceCount);
345 : }
346 : }
347 :
348 350 : CPLFree(pszKey);
349 : }
350 :
351 5 : CSLDestroy(papszLines);
352 :
353 5 : return papszResultList;
354 : }
|