Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Core
4 : * Purpose: Read metadata from Spot 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_spot.h"
32 :
33 : #include <ctime>
34 :
35 : #include "cpl_conv.h"
36 : #include "cpl_error.h"
37 : #include "cpl_minixml.h"
38 : #include "cpl_string.h"
39 : #include "cpl_time.h"
40 :
41 : #include "gdal_mdreader.h"
42 :
43 : /**
44 : * GDALMDReaderSpot()
45 : */
46 5031 : GDALMDReaderSpot::GDALMDReaderSpot(const char *pszPath,
47 5031 : char **papszSiblingFiles)
48 5031 : : GDALMDReaderPleiades(pszPath, papszSiblingFiles)
49 : {
50 5031 : const char *pszDirName = CPLGetDirname(pszPath);
51 :
52 5031 : if (m_osIMDSourceFilename.empty())
53 : {
54 : std::string osIMDSourceFilename =
55 10062 : CPLFormFilename(pszDirName, "METADATA.DIM", nullptr);
56 :
57 5031 : if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
58 : {
59 1 : m_osIMDSourceFilename = std::move(osIMDSourceFilename);
60 : }
61 : else
62 : {
63 : osIMDSourceFilename =
64 5030 : CPLFormFilename(pszDirName, "metadata.dim", nullptr);
65 5030 : if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
66 : {
67 0 : m_osIMDSourceFilename = std::move(osIMDSourceFilename);
68 : }
69 : }
70 : }
71 :
72 : // if the file name ended on METADATA.DIM
73 : // Linux specific
74 : // example: R2_CAT_091028105025131_1\METADATA.DIM
75 5031 : if (m_osIMDSourceFilename.empty())
76 : {
77 5030 : if (EQUAL(CPLGetFilename(pszPath), "IMAGERY.TIF"))
78 : {
79 : std::string osIMDSourceFilename =
80 0 : CPLSPrintf("%s\\METADATA.DIM", CPLGetPath(pszPath));
81 :
82 0 : if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
83 : {
84 0 : m_osIMDSourceFilename = std::move(osIMDSourceFilename);
85 : }
86 : else
87 : {
88 : osIMDSourceFilename =
89 0 : CPLSPrintf("%s\\metadata.dim", CPLGetPath(pszPath));
90 0 : if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
91 : {
92 0 : m_osIMDSourceFilename = std::move(osIMDSourceFilename);
93 : }
94 : }
95 : }
96 : }
97 :
98 5031 : if (!m_osIMDSourceFilename.empty())
99 1 : CPLDebug("MDReaderSpot", "IMD Filename: %s",
100 : m_osIMDSourceFilename.c_str());
101 5031 : }
102 :
103 : /**
104 : * ~GDALMDReaderSpot()
105 : */
106 10062 : GDALMDReaderSpot::~GDALMDReaderSpot()
107 : {
108 10062 : }
109 :
110 : /**
111 : * LoadMetadata()
112 : */
113 2 : void GDALMDReaderSpot::LoadMetadata()
114 : {
115 2 : if (m_bIsMetadataLoad)
116 1 : return;
117 :
118 1 : if (!m_osIMDSourceFilename.empty())
119 : {
120 1 : CPLXMLNode *psNode = CPLParseXMLFile(m_osIMDSourceFilename);
121 :
122 1 : if (psNode != nullptr)
123 : {
124 1 : CPLXMLNode *psisdNode = CPLSearchXMLNode(psNode, "=Dimap_Document");
125 :
126 1 : if (psisdNode != nullptr)
127 : {
128 1 : m_papszIMDMD = ReadXMLToList(psisdNode->psChild, m_papszIMDMD);
129 : }
130 1 : CPLDestroyXMLNode(psNode);
131 : }
132 : }
133 :
134 1 : m_papszDEFAULTMD =
135 1 : CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "DIMAP");
136 :
137 1 : m_bIsMetadataLoad = true;
138 :
139 1 : if (nullptr == m_papszIMDMD)
140 : {
141 0 : return;
142 : }
143 :
144 : // extract imagery metadata
145 1 : int nCounter = -1;
146 2 : const char *pszSatId1 = CSLFetchNameValue(
147 1 : m_papszIMDMD,
148 : "Dataset_Sources.Source_Information.Scene_Source.MISSION");
149 1 : if (nullptr == pszSatId1)
150 : {
151 0 : nCounter = 1;
152 0 : for (int i = 0; i < 5; i++)
153 : {
154 0 : pszSatId1 = CSLFetchNameValue(
155 0 : m_papszIMDMD, CPLSPrintf("Dataset_Sources.Source_Information_%"
156 : "d.Scene_Source.MISSION",
157 : nCounter));
158 0 : if (nullptr != pszSatId1)
159 0 : break;
160 0 : nCounter++;
161 : }
162 : }
163 :
164 : const char *pszSatId2;
165 1 : if (nCounter == -1)
166 1 : pszSatId2 = CSLFetchNameValue(
167 1 : m_papszIMDMD,
168 : "Dataset_Sources.Source_Information.Scene_Source.MISSION_INDEX");
169 : else
170 0 : pszSatId2 = CSLFetchNameValue(
171 0 : m_papszIMDMD, CPLSPrintf("Dataset_Sources.Source_Information_%d."
172 : "Scene_Source.MISSION_INDEX",
173 : nCounter));
174 :
175 1 : if (nullptr != pszSatId1 && nullptr != pszSatId2)
176 : {
177 2 : m_papszIMAGERYMD = CSLAddNameValue(
178 : m_papszIMAGERYMD, MD_NAME_SATELLITE,
179 2 : CPLSPrintf("%s %s", CPLStripQuotes(pszSatId1).c_str(),
180 2 : CPLStripQuotes(pszSatId2).c_str()));
181 : }
182 0 : else if (nullptr != pszSatId1 && nullptr == pszSatId2)
183 : {
184 0 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
185 0 : CPLStripQuotes(pszSatId1));
186 : }
187 0 : else if (nullptr == pszSatId1 && nullptr != pszSatId2)
188 : {
189 0 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
190 0 : CPLStripQuotes(pszSatId2));
191 : }
192 :
193 : const char *pszDate;
194 1 : if (nCounter == -1)
195 1 : pszDate = CSLFetchNameValue(
196 1 : m_papszIMDMD,
197 : "Dataset_Sources.Source_Information.Scene_Source.IMAGING_DATE");
198 : else
199 0 : pszDate = CSLFetchNameValue(
200 0 : m_papszIMDMD, CPLSPrintf("Dataset_Sources.Source_Information_%d."
201 : "Scene_Source.IMAGING_DATE",
202 : nCounter));
203 :
204 1 : if (nullptr != pszDate)
205 : {
206 : const char *pszTime;
207 1 : if (nCounter == -1)
208 1 : pszTime = CSLFetchNameValue(
209 1 : m_papszIMDMD,
210 : "Dataset_Sources.Source_Information.Scene_Source.IMAGING_TIME");
211 : else
212 0 : pszTime = CSLFetchNameValue(
213 0 : m_papszIMDMD, CPLSPrintf("Dataset_Sources.Source_Information_%"
214 : "d.Scene_Source.IMAGING_TIME",
215 : nCounter));
216 :
217 1 : if (nullptr == pszTime)
218 0 : pszTime = "00:00:00.0Z";
219 :
220 : char buffer[80];
221 : GIntBig timeMid =
222 1 : GetAcquisitionTimeFromString(CPLSPrintf("%sT%s", pszDate, pszTime));
223 : struct tm tmBuf;
224 1 : strftime(buffer, 80, MD_DATETIMEFORMAT,
225 1 : CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
226 1 : m_papszIMAGERYMD =
227 1 : CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_ACQDATETIME, buffer);
228 : }
229 :
230 1 : m_papszIMAGERYMD =
231 1 : CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER, MD_CLOUDCOVER_NA);
232 : }
233 :
234 : /**
235 : * ReadXMLToList()
236 : */
237 58 : char **GDALMDReaderSpot::ReadXMLToList(CPLXMLNode *psNode, char **papszList,
238 : const char *pszName)
239 : {
240 58 : if (nullptr == psNode)
241 0 : return papszList;
242 :
243 58 : if (psNode->eType == CXT_Text)
244 : {
245 22 : if (!EQUAL(pszName, ""))
246 22 : return AddXMLNameValueToList(papszList, pszName, psNode->pszValue);
247 : }
248 :
249 36 : if (psNode->eType == CXT_Element && !EQUAL(psNode->pszValue, "Data_Strip"))
250 : {
251 31 : int nAddIndex = 0;
252 31 : bool bReset = false;
253 80 : for (CPLXMLNode *psChildNode = psNode->psChild; nullptr != psChildNode;
254 49 : psChildNode = psChildNode->psNext)
255 : {
256 49 : if (psChildNode->eType == CXT_Element)
257 : {
258 : // check name duplicates
259 25 : if (nullptr != psChildNode->psNext)
260 : {
261 16 : if (bReset)
262 : {
263 0 : bReset = false;
264 0 : nAddIndex = 0;
265 : }
266 :
267 16 : if (EQUAL(psChildNode->pszValue,
268 : psChildNode->psNext->pszValue))
269 : {
270 0 : nAddIndex++;
271 : }
272 : else
273 : { // the name changed
274 :
275 16 : if (nAddIndex > 0)
276 : {
277 0 : bReset = true;
278 0 : nAddIndex++;
279 : }
280 : }
281 : }
282 : else
283 : {
284 9 : if (nAddIndex > 0)
285 : {
286 0 : nAddIndex++;
287 : }
288 : }
289 :
290 : char szName[512];
291 25 : if (nAddIndex > 0)
292 : {
293 0 : CPLsnprintf(szName, 511, "%s_%d", psChildNode->pszValue,
294 : nAddIndex);
295 : }
296 : else
297 : {
298 25 : CPLStrlcpy(szName, psChildNode->pszValue, 511);
299 : }
300 :
301 : char szNameNew[512];
302 25 : if (CPLStrnlen(pszName, 511) >
303 : 0) // if no prefix just set name to node name
304 : {
305 10 : CPLsnprintf(szNameNew, 511, "%s.%s", pszName, szName);
306 : }
307 : else
308 : {
309 15 : CPLsnprintf(szNameNew, 511, "%s.%s", psNode->pszValue,
310 : szName);
311 : }
312 :
313 25 : papszList = ReadXMLToList(psChildNode, papszList, szNameNew);
314 : }
315 : else
316 : {
317 : // Text nodes should always have name
318 24 : if (EQUAL(pszName, ""))
319 : {
320 : papszList =
321 0 : ReadXMLToList(psChildNode, papszList, psNode->pszValue);
322 : }
323 : else
324 : {
325 24 : papszList = ReadXMLToList(psChildNode, papszList, pszName);
326 : }
327 : }
328 : }
329 : }
330 :
331 : // proceed next only on top level
332 :
333 36 : if (nullptr != psNode->psNext && EQUAL(pszName, ""))
334 : {
335 8 : papszList = ReadXMLToList(psNode->psNext, papszList, pszName);
336 : }
337 :
338 36 : return papszList;
339 : }
|