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