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 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_port.h"
31 : #include "reader_geo_eye.h"
32 :
33 : #include <cstddef>
34 : #include <cstdio>
35 : #include <cstring>
36 :
37 : #include <string>
38 :
39 : #include "cpl_conv.h"
40 : #include "cpl_error.h"
41 : #include "cpl_string.h"
42 : #include "cpl_time.h"
43 :
44 : /**
45 : * GDALMDReaderGeoEye()
46 : */
47 5058 : GDALMDReaderGeoEye::GDALMDReaderGeoEye(const char *pszPath,
48 5058 : char **papszSiblingFiles)
49 5058 : : GDALMDReaderBase(pszPath, papszSiblingFiles)
50 : {
51 :
52 10116 : const CPLString osBaseName = CPLGetBasename(pszPath);
53 10116 : const CPLString osDirName = CPLGetDirname(pszPath);
54 :
55 : // get _metadata.txt file
56 :
57 : // split file name by _rgb_ or _pan_
58 10116 : CPLString osRadixMetadataName(osBaseName);
59 5058 : size_t i = osRadixMetadataName.ifind("_rgb_");
60 5058 : if (i == std::string::npos)
61 5052 : i = osRadixMetadataName.ifind("_pan_");
62 5058 : if (i != std::string::npos)
63 6 : osRadixMetadataName.resize(i);
64 :
65 : // form metadata file name
66 : std::string osIMDSourceFilename = CPLFormFilename(
67 15174 : osDirName, (osRadixMetadataName + "_metadata.txt").c_str(), nullptr);
68 5058 : if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
69 : {
70 5 : m_osIMDSourceFilename = std::move(osIMDSourceFilename);
71 : }
72 : else
73 : {
74 : osIMDSourceFilename = CPLFormFilename(
75 10106 : osDirName, (osRadixMetadataName + "_METADATA.txt").c_str(),
76 5053 : nullptr);
77 5053 : if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
78 : {
79 0 : m_osIMDSourceFilename = std::move(osIMDSourceFilename);
80 : }
81 : }
82 :
83 : // get _rpc.txt file
84 :
85 : std::string osRPBSourceFilename =
86 15174 : CPLFormFilename(osDirName, (osBaseName + "_rpc").c_str(), "txt");
87 5058 : if (CPLCheckForFile(&osRPBSourceFilename[0], papszSiblingFiles))
88 : {
89 12 : m_osRPBSourceFilename = std::move(osRPBSourceFilename);
90 : }
91 : else
92 : {
93 : osRPBSourceFilename =
94 5046 : CPLFormFilename(osDirName, (osBaseName + "_RPC").c_str(), "TXT");
95 5046 : if (CPLCheckForFile(&osRPBSourceFilename[0], papszSiblingFiles))
96 : {
97 0 : m_osRPBSourceFilename = std::move(osRPBSourceFilename);
98 : }
99 : }
100 :
101 5058 : if (!m_osIMDSourceFilename.empty())
102 5 : CPLDebug("MDReaderGeoEye", "IMD Filename: %s",
103 : m_osIMDSourceFilename.c_str());
104 5058 : if (!m_osRPBSourceFilename.empty())
105 12 : CPLDebug("MDReaderGeoEye", "RPB Filename: %s",
106 : m_osRPBSourceFilename.c_str());
107 5058 : }
108 :
109 : /**
110 : * ~GDALMDReaderGeoEye()
111 : */
112 10116 : GDALMDReaderGeoEye::~GDALMDReaderGeoEye()
113 : {
114 10116 : }
115 :
116 : /**
117 : * HasRequiredFiles()
118 : */
119 5058 : bool GDALMDReaderGeoEye::HasRequiredFiles() const
120 : {
121 5058 : if (!m_osIMDSourceFilename.empty())
122 5 : return true;
123 :
124 5053 : if (!m_osRPBSourceFilename.empty())
125 7 : return true;
126 :
127 5046 : return false;
128 : }
129 :
130 : /**
131 : * GetMetadataFiles()
132 : */
133 12 : char **GDALMDReaderGeoEye::GetMetadataFiles() const
134 : {
135 12 : char **papszFileList = nullptr;
136 12 : if (!m_osIMDSourceFilename.empty())
137 5 : papszFileList = CSLAddString(papszFileList, m_osIMDSourceFilename);
138 12 : if (!m_osRPBSourceFilename.empty())
139 12 : papszFileList = CSLAddString(papszFileList, m_osRPBSourceFilename);
140 :
141 12 : return papszFileList;
142 : }
143 :
144 : /**
145 : * LoadMetadata()
146 : */
147 24 : void GDALMDReaderGeoEye::LoadMetadata()
148 : {
149 24 : if (m_bIsMetadataLoad)
150 12 : return;
151 :
152 12 : if (!m_osIMDSourceFilename.empty())
153 : {
154 5 : m_papszIMDMD = LoadIMDWktFile();
155 : }
156 :
157 12 : if (!m_osRPBSourceFilename.empty())
158 : {
159 12 : m_papszRPCMD = GDALLoadRPCFile(m_osRPBSourceFilename);
160 : }
161 :
162 12 : m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "GE");
163 :
164 12 : m_bIsMetadataLoad = true;
165 :
166 12 : if (nullptr == m_papszIMDMD)
167 : {
168 7 : return;
169 : }
170 :
171 : // extract imagery metadata
172 : const char *pszSatId =
173 5 : CSLFetchNameValue(m_papszIMDMD, "Source Image Metadata.Sensor");
174 5 : if (nullptr != pszSatId)
175 : {
176 5 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
177 10 : CPLStripQuotes(pszSatId));
178 : }
179 :
180 10 : const char *pszCloudCover = CSLFetchNameValue(
181 5 : m_papszIMDMD, "Source Image Metadata.Percent Cloud Cover");
182 5 : if (nullptr != pszCloudCover)
183 : {
184 5 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
185 : pszCloudCover);
186 : }
187 :
188 10 : const char *pszDateTime = CSLFetchNameValue(
189 5 : m_papszIMDMD, "Source Image Metadata.Acquisition Date/Time");
190 :
191 5 : if (nullptr != pszDateTime)
192 : {
193 : char buffer[80];
194 5 : GIntBig timeMid = GetAcquisitionTimeFromString(pszDateTime);
195 :
196 : struct tm tmBuf;
197 5 : strftime(buffer, 80, MD_DATETIMEFORMAT,
198 5 : CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
199 5 : m_papszIMAGERYMD =
200 5 : CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_ACQDATETIME, buffer);
201 : }
202 : }
203 :
204 : /**
205 : * GetAcqisitionTimeFromString()
206 : */
207 : GIntBig
208 5 : GDALMDReaderGeoEye::GetAcquisitionTimeFromString(const char *pszDateTime)
209 : {
210 5 : if (nullptr == pszDateTime)
211 0 : return 0;
212 :
213 : int iYear;
214 : int iMonth;
215 : int iDay;
216 : int iHours;
217 : int iMin;
218 5 : int iSec = 0;
219 :
220 : // string example: Acquisition Date/Time: 2006-03-01 11:08 GMT
221 :
222 5 : int r = sscanf(pszDateTime, "%d-%d-%d %d:%d GMT", &iYear, &iMonth, &iDay,
223 : &iHours, &iMin);
224 :
225 5 : if (r != 5)
226 0 : return 0;
227 :
228 : struct tm tmDateTime;
229 5 : tmDateTime.tm_sec = iSec;
230 5 : tmDateTime.tm_min = iMin;
231 5 : tmDateTime.tm_hour = iHours;
232 5 : tmDateTime.tm_mday = iDay;
233 5 : tmDateTime.tm_mon = iMonth - 1;
234 5 : tmDateTime.tm_year = iYear - 1900;
235 5 : tmDateTime.tm_isdst = -1;
236 :
237 5 : return CPLYMDHMSToUnixTime(&tmDateTime);
238 : }
239 :
240 : /**
241 : * LoadWKTIMDFile()
242 : */
243 5 : char **GDALMDReaderGeoEye::LoadIMDWktFile() const
244 : {
245 5 : char **papszResultList = nullptr;
246 5 : char **papszLines = CSLLoad(m_osIMDSourceFilename);
247 5 : bool bBeginSection = false;
248 10 : CPLString osSection;
249 10 : CPLString osKeyLevel1;
250 10 : CPLString osKeyLevel2;
251 10 : CPLString osKeyLevel3;
252 5 : int nLevel = 0;
253 : int nSpaceCount;
254 :
255 5 : if (papszLines == nullptr)
256 0 : return nullptr;
257 :
258 475 : for (int i = 0; papszLines[i] != nullptr; i++)
259 : {
260 : // skip section (=== or ---) lines
261 :
262 470 : if (STARTS_WITH_CI(papszLines[i], "==="))
263 : {
264 30 : bBeginSection = true;
265 120 : continue;
266 : }
267 :
268 870 : if (STARTS_WITH_CI(papszLines[i], "---") ||
269 430 : CPLStrnlen(papszLines[i], 512) == 0)
270 90 : continue;
271 :
272 : // check the metadata level
273 350 : nSpaceCount = 0;
274 590 : for (int j = 0; j < 11; j++)
275 : {
276 590 : if (papszLines[i][j] != ' ')
277 350 : break;
278 240 : nSpaceCount++;
279 : }
280 :
281 350 : if (nSpaceCount % 3 != 0)
282 0 : continue; // not a metadata item
283 350 : nLevel = nSpaceCount / 3;
284 :
285 : const char *pszValue;
286 350 : char *pszKey = nullptr;
287 350 : pszValue = CPLParseNameValue(papszLines[i], &pszKey);
288 :
289 350 : if (nullptr != pszValue && CPLStrnlen(pszValue, 512) > 0)
290 : {
291 :
292 310 : CPLString osCurrentKey;
293 310 : if (nLevel == 0)
294 : {
295 230 : osCurrentKey = CPLOPrintf("%s", pszKey);
296 : }
297 80 : else if (nLevel == 1)
298 : {
299 : osCurrentKey =
300 80 : osKeyLevel1 + "." + CPLOPrintf("%s", pszKey + nSpaceCount);
301 : }
302 0 : else if (nLevel == 2)
303 : {
304 0 : osCurrentKey = osKeyLevel1 + "." + osKeyLevel2 + "." +
305 0 : CPLOPrintf("%s", pszKey + nSpaceCount);
306 : }
307 0 : else if (nLevel == 3)
308 : {
309 0 : osCurrentKey = osKeyLevel1 + "." + osKeyLevel2 + "." +
310 0 : osKeyLevel3 + "." +
311 0 : CPLOPrintf("%s", pszKey + nSpaceCount);
312 : }
313 :
314 310 : if (!osSection.empty())
315 : {
316 305 : osCurrentKey = osSection + "." + osCurrentKey;
317 : }
318 :
319 : papszResultList =
320 310 : CSLAddNameValue(papszResultList, osCurrentKey, pszValue);
321 : }
322 :
323 350 : if (nullptr != pszKey && CPLStrnlen(pszKey, 512) > 0)
324 : {
325 310 : if (bBeginSection)
326 : {
327 5 : osSection = CPLOPrintf("%s", pszKey);
328 5 : bBeginSection = false;
329 : }
330 305 : else if (nLevel == 0)
331 : {
332 225 : osKeyLevel1 = CPLOPrintf("%s", pszKey);
333 : }
334 80 : else if (nLevel == 1)
335 : {
336 80 : osKeyLevel2 = CPLOPrintf("%s", pszKey + nSpaceCount);
337 : }
338 0 : else if (nLevel == 2)
339 : {
340 0 : osKeyLevel3 = CPLOPrintf("%s", pszKey + nSpaceCount);
341 : }
342 : }
343 : else
344 : {
345 40 : if (bBeginSection)
346 : {
347 20 : osSection = CPLOPrintf("%s", papszLines[i]);
348 20 : bBeginSection = false;
349 : }
350 20 : else if (nLevel == 0)
351 : {
352 20 : osKeyLevel1 = CPLOPrintf("%s", papszLines[i]);
353 : }
354 0 : else if (nLevel == 1)
355 : {
356 0 : osKeyLevel2 = CPLOPrintf("%s", papszLines[i] + nSpaceCount);
357 : }
358 0 : else if (nLevel == 2)
359 : {
360 0 : osKeyLevel3 = CPLOPrintf("%s", papszLines[i] + nSpaceCount);
361 : }
362 : }
363 :
364 350 : CPLFree(pszKey);
365 : }
366 :
367 5 : CSLDestroy(papszLines);
368 :
369 5 : return papszResultList;
370 : }
|