Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Core
4 : * Purpose: Read metadata from DigitalGlobe 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_digital_globe.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_priv.h"
42 :
43 : /**
44 : * GDALMDReaderDigitalGlobe()
45 : */
46 5095 : GDALMDReaderDigitalGlobe::GDALMDReaderDigitalGlobe(const char *pszPath,
47 5095 : char **papszSiblingFiles)
48 : : GDALMDReaderBase(pszPath, papszSiblingFiles),
49 : m_osXMLSourceFilename(
50 : GDALFindAssociatedFile(pszPath, "XML", papszSiblingFiles, 0)),
51 : m_osIMDSourceFilename(
52 : GDALFindAssociatedFile(pszPath, "IMD", papszSiblingFiles, 0)),
53 : m_osRPBSourceFilename(
54 5095 : GDALFindAssociatedFile(pszPath, "RPB", papszSiblingFiles, 0))
55 : {
56 5095 : if (!m_osIMDSourceFilename.empty())
57 36 : CPLDebug("MDReaderDigitalGlobe", "IMD Filename: %s",
58 : m_osIMDSourceFilename.c_str());
59 5095 : if (!m_osRPBSourceFilename.empty())
60 10 : CPLDebug("MDReaderDigitalGlobe", "RPB Filename: %s",
61 : m_osRPBSourceFilename.c_str());
62 5095 : if (!m_osXMLSourceFilename.empty())
63 9 : CPLDebug("MDReaderDigitalGlobe", "XML Filename: %s",
64 : m_osXMLSourceFilename.c_str());
65 5095 : }
66 :
67 : /**
68 : * ~GDALMDReaderDigitalGlobe()
69 : */
70 10190 : GDALMDReaderDigitalGlobe::~GDALMDReaderDigitalGlobe()
71 : {
72 10190 : }
73 :
74 : /**
75 : * HasRequiredFiles()
76 : */
77 5095 : bool GDALMDReaderDigitalGlobe::HasRequiredFiles() const
78 : {
79 5095 : if (!m_osIMDSourceFilename.empty())
80 36 : return true;
81 5059 : if (!m_osRPBSourceFilename.empty())
82 0 : return true;
83 :
84 : // check <isd>
85 5068 : if (!m_osXMLSourceFilename.empty() &&
86 9 : GDALCheckFileHeader(m_osXMLSourceFilename, "<isd>"))
87 2 : return true;
88 :
89 5057 : return false;
90 : }
91 :
92 : /**
93 : * LoadMetadata()
94 : */
95 76 : void GDALMDReaderDigitalGlobe::LoadMetadata()
96 : {
97 76 : if (m_bIsMetadataLoad)
98 38 : return;
99 :
100 38 : if (!m_osIMDSourceFilename.empty())
101 : {
102 36 : m_papszIMDMD = GDALLoadIMDFile(m_osIMDSourceFilename);
103 : }
104 :
105 38 : if (!m_osRPBSourceFilename.empty())
106 : {
107 10 : m_papszRPCMD = GDALLoadRPBFile(m_osRPBSourceFilename);
108 : }
109 :
110 66 : if ((nullptr == m_papszIMDMD || nullptr == m_papszRPCMD) &&
111 28 : !m_osXMLSourceFilename.empty())
112 : {
113 2 : CPLXMLNode *psNode = CPLParseXMLFile(m_osXMLSourceFilename);
114 :
115 2 : if (psNode != nullptr)
116 : {
117 2 : CPLXMLNode *psisdNode = psNode->psNext;
118 2 : if (psisdNode != nullptr)
119 : {
120 2 : if (m_papszIMDMD == nullptr)
121 2 : m_papszIMDMD =
122 2 : LoadIMDXmlNode(CPLSearchXMLNode(psisdNode, "IMD"));
123 2 : if (m_papszRPCMD == nullptr)
124 2 : m_papszRPCMD =
125 2 : LoadRPBXmlNode(CPLSearchXMLNode(psisdNode, "RPB"));
126 : }
127 2 : CPLDestroyXMLNode(psNode);
128 : }
129 : }
130 :
131 38 : m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "DG");
132 :
133 38 : m_bIsMetadataLoad = true;
134 :
135 38 : if (nullptr == m_papszIMDMD)
136 : {
137 4 : return;
138 : }
139 : // extract imagery metadata
140 34 : const char *pszSatId = CSLFetchNameValue(m_papszIMDMD, "IMAGE.SATID");
141 34 : if (nullptr != pszSatId)
142 : {
143 2 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
144 4 : CPLStripQuotes(pszSatId));
145 : }
146 : else
147 : {
148 32 : pszSatId = CSLFetchNameValue(m_papszIMDMD, "IMAGE_1.SATID");
149 32 : if (nullptr != pszSatId)
150 : {
151 30 : m_papszIMAGERYMD = CSLAddNameValue(
152 60 : m_papszIMAGERYMD, MD_NAME_SATELLITE, CPLStripQuotes(pszSatId));
153 : }
154 : }
155 :
156 : const char *pszCloudCover =
157 34 : CSLFetchNameValue(m_papszIMDMD, "IMAGE.CLOUDCOVER");
158 34 : if (nullptr != pszCloudCover)
159 : {
160 2 : double fCC = CPLAtofM(pszCloudCover);
161 2 : if (fCC < 0)
162 : {
163 0 : m_papszIMAGERYMD = CSLAddNameValue(
164 : m_papszIMAGERYMD, MD_NAME_CLOUDCOVER, MD_CLOUDCOVER_NA);
165 : }
166 : else
167 : {
168 2 : m_papszIMAGERYMD =
169 2 : CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
170 2 : CPLSPrintf("%d", int(fCC * 100)));
171 : }
172 : }
173 : else
174 : {
175 32 : pszCloudCover = CSLFetchNameValue(m_papszIMDMD, "IMAGE_1.cloudCover");
176 32 : if (nullptr != pszCloudCover)
177 : {
178 30 : double fCC = CPLAtofM(pszCloudCover);
179 30 : if (fCC < 0)
180 : {
181 0 : m_papszIMAGERYMD = CSLAddNameValue(
182 : m_papszIMAGERYMD, MD_NAME_CLOUDCOVER, MD_CLOUDCOVER_NA);
183 : }
184 : else
185 : {
186 30 : m_papszIMAGERYMD =
187 30 : CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
188 30 : CPLSPrintf("%d", int(fCC * 100)));
189 : }
190 : }
191 : }
192 :
193 : const char *pszDateTime =
194 34 : CSLFetchNameValue(m_papszIMDMD, "IMAGE.FIRSTLINETIME");
195 34 : if (nullptr != pszDateTime)
196 : {
197 2 : GIntBig timeStart = GetAcquisitionTimeFromString(pszDateTime);
198 : char szMidDateTime[80];
199 : struct tm tmBuf;
200 2 : strftime(szMidDateTime, 80, MD_DATETIMEFORMAT,
201 2 : CPLUnixTimeToYMDHMS(timeStart, &tmBuf));
202 :
203 2 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
204 : MD_NAME_ACQDATETIME, szMidDateTime);
205 : }
206 : else
207 : {
208 32 : pszDateTime = CSLFetchNameValue(m_papszIMDMD, "IMAGE_1.firstLineTime");
209 32 : if (nullptr != pszDateTime)
210 : {
211 30 : GIntBig timeStart = GetAcquisitionTimeFromString(pszDateTime);
212 : char szMidDateTime[80];
213 : struct tm tmBuf;
214 30 : strftime(szMidDateTime, 80, MD_DATETIMEFORMAT,
215 30 : CPLUnixTimeToYMDHMS(timeStart, &tmBuf));
216 :
217 30 : m_papszIMAGERYMD = CSLAddNameValue(
218 : m_papszIMAGERYMD, MD_NAME_ACQDATETIME, szMidDateTime);
219 : }
220 : }
221 : }
222 :
223 : /**
224 : * GetMetadataFiles()
225 : */
226 38 : char **GDALMDReaderDigitalGlobe::GetMetadataFiles() const
227 : {
228 38 : char **papszFileList = nullptr;
229 38 : if (!m_osIMDSourceFilename.empty())
230 36 : papszFileList = CSLAddString(papszFileList, m_osIMDSourceFilename);
231 38 : if (!m_osRPBSourceFilename.empty())
232 10 : papszFileList = CSLAddString(papszFileList, m_osRPBSourceFilename);
233 38 : if (!m_osXMLSourceFilename.empty())
234 2 : papszFileList = CSLAddString(papszFileList, m_osXMLSourceFilename);
235 :
236 38 : return papszFileList;
237 : }
238 :
239 : /**
240 : * GDALLoadIMDXmlNode()
241 : */
242 2 : char **GDALMDReaderDigitalGlobe::LoadIMDXmlNode(CPLXMLNode *psNode)
243 : {
244 2 : if (nullptr == psNode)
245 0 : return nullptr;
246 2 : char **papszList = nullptr;
247 2 : return ReadXMLToList(psNode->psChild, papszList);
248 : }
249 :
250 : /**
251 : * GDALLoadRPBXmlNode()
252 : */
253 : static const char *const apszRPBMap[] = {RPC_ERR_BIAS,
254 : "image.errBias",
255 : RPC_ERR_RAND,
256 : "image.errRand",
257 : RPC_LINE_OFF,
258 : "image.lineOffset",
259 : RPC_SAMP_OFF,
260 : "image.sampOffset",
261 : RPC_LAT_OFF,
262 : "image.latOffset",
263 : RPC_LONG_OFF,
264 : "image.longOffset",
265 : RPC_HEIGHT_OFF,
266 : "image.heightOffset",
267 : RPC_LINE_SCALE,
268 : "image.lineScale",
269 : RPC_SAMP_SCALE,
270 : "image.sampScale",
271 : RPC_LAT_SCALE,
272 : "image.latScale",
273 : RPC_LONG_SCALE,
274 : "image.longScale",
275 : RPC_HEIGHT_SCALE,
276 : "image.heightScale",
277 : RPC_LINE_NUM_COEFF,
278 : "image.lineNumCoefList.lineNumCoef",
279 : RPC_LINE_DEN_COEFF,
280 : "image.lineDenCoefList.lineDenCoef",
281 : RPC_SAMP_NUM_COEFF,
282 : "image.sampNumCoefList.sampNumCoef",
283 : RPC_SAMP_DEN_COEFF,
284 : "image.sampDenCoefList.sampDenCoef",
285 : nullptr,
286 : nullptr};
287 :
288 2 : char **GDALMDReaderDigitalGlobe::LoadRPBXmlNode(CPLXMLNode *psNode)
289 : {
290 2 : if (nullptr == psNode)
291 1 : return nullptr;
292 1 : char **papszList = nullptr;
293 1 : papszList = ReadXMLToList(psNode->psChild, papszList);
294 :
295 1 : if (nullptr == papszList)
296 0 : return nullptr;
297 :
298 1 : char **papszRPB = nullptr;
299 17 : for (int i = 0; apszRPBMap[i] != nullptr; i += 2)
300 : {
301 : papszRPB =
302 16 : CSLAddNameValue(papszRPB, apszRPBMap[i],
303 16 : CSLFetchNameValue(papszList, apszRPBMap[i + 1]));
304 : }
305 :
306 1 : CSLDestroy(papszList);
307 :
308 1 : return papszRPB;
309 : }
|