Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Core
4 : * Purpose: Read metadata from Kompsat 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_kompsat.h"
32 :
33 : #include <cstddef>
34 : #include <cstdio>
35 : #include <cstdlib>
36 :
37 : #include "cpl_error.h"
38 : #include "cpl_string.h"
39 : #include "cpl_time.h"
40 :
41 : #include "gdal_mdreader.h"
42 : #include "gdal_priv.h"
43 :
44 : /**
45 : * GDALMDReaderKompsat()
46 : */
47 5028 : GDALMDReaderKompsat::GDALMDReaderKompsat(const char *pszPath,
48 5028 : char **papszSiblingFiles)
49 : : GDALMDReaderBase(pszPath, papszSiblingFiles),
50 : m_osIMDSourceFilename(
51 : GDALFindAssociatedFile(pszPath, "TXT", papszSiblingFiles, 0)),
52 : m_osRPBSourceFilename(
53 5028 : GDALFindAssociatedFile(pszPath, "RPC", papszSiblingFiles, 0))
54 : {
55 5028 : if (!m_osIMDSourceFilename.empty())
56 2 : CPLDebug("MDReaderDigitalGlobe", "IMD Filename: %s",
57 : m_osIMDSourceFilename.c_str());
58 5028 : if (!m_osRPBSourceFilename.empty())
59 3 : CPLDebug("MDReaderDigitalGlobe", "RPB Filename: %s",
60 : m_osRPBSourceFilename.c_str());
61 5028 : }
62 :
63 : /**
64 : * ~GDALMDReaderKompsat()
65 : */
66 10056 : GDALMDReaderKompsat::~GDALMDReaderKompsat()
67 : {
68 10056 : }
69 :
70 : /**
71 : * HasRequiredFiles()
72 : */
73 5028 : bool GDALMDReaderKompsat::HasRequiredFiles() const
74 : {
75 5028 : if (!m_osIMDSourceFilename.empty() && !m_osRPBSourceFilename.empty())
76 2 : return true;
77 :
78 5026 : return false;
79 : }
80 :
81 : /**
82 : * GetMetadataFiles()
83 : */
84 2 : char **GDALMDReaderKompsat::GetMetadataFiles() const
85 : {
86 2 : char **papszFileList = nullptr;
87 2 : if (!m_osIMDSourceFilename.empty())
88 2 : papszFileList = CSLAddString(papszFileList, m_osIMDSourceFilename);
89 2 : if (!m_osRPBSourceFilename.empty())
90 2 : papszFileList = CSLAddString(papszFileList, m_osRPBSourceFilename);
91 :
92 2 : return papszFileList;
93 : }
94 :
95 : /**
96 : * LoadMetadata()
97 : */
98 4 : void GDALMDReaderKompsat::LoadMetadata()
99 : {
100 4 : if (m_bIsMetadataLoad)
101 2 : return;
102 :
103 2 : if (!m_osIMDSourceFilename.empty())
104 : {
105 2 : m_papszIMDMD = ReadTxtToList();
106 : }
107 :
108 2 : if (!m_osRPBSourceFilename.empty())
109 : {
110 2 : m_papszRPCMD = GDALLoadRPCFile(m_osRPBSourceFilename);
111 : }
112 :
113 2 : m_papszDEFAULTMD =
114 2 : CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "KARI");
115 :
116 2 : m_bIsMetadataLoad = true;
117 :
118 : const char *pszSatId1 =
119 2 : CSLFetchNameValue(m_papszIMDMD, "AUX_SATELLITE_NAME");
120 : const char *pszSatId2 =
121 2 : CSLFetchNameValue(m_papszIMDMD, "AUX_SATELLITE_SENSOR");
122 2 : if (nullptr != pszSatId1 && nullptr != pszSatId2)
123 : {
124 4 : m_papszIMAGERYMD = CSLAddNameValue(
125 : m_papszIMAGERYMD, MD_NAME_SATELLITE,
126 4 : CPLSPrintf("%s %s", CPLStripQuotes(pszSatId1).c_str(),
127 4 : CPLStripQuotes(pszSatId2).c_str()));
128 : }
129 0 : else if (nullptr != pszSatId1 && nullptr == pszSatId2)
130 : {
131 0 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
132 0 : CPLStripQuotes(pszSatId1));
133 : }
134 0 : else if (nullptr == pszSatId1 && nullptr != pszSatId2)
135 : {
136 0 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
137 0 : CPLStripQuotes(pszSatId2));
138 : }
139 :
140 : const char *pszCloudCover =
141 2 : CSLFetchNameValue(m_papszIMDMD, "AUX_CLOUD_STATUS");
142 2 : if (nullptr != pszCloudCover)
143 : {
144 2 : int nCC = atoi(pszCloudCover);
145 2 : if (nCC > 100 || nCC < 0)
146 : {
147 0 : m_papszIMAGERYMD = CSLAddNameValue(
148 : m_papszIMAGERYMD, MD_NAME_CLOUDCOVER, MD_CLOUDCOVER_NA);
149 : }
150 : else
151 : {
152 2 : m_papszIMAGERYMD = CSLAddNameValue(
153 : m_papszIMAGERYMD, MD_NAME_CLOUDCOVER, CPLSPrintf("%d", nCC));
154 : }
155 : }
156 :
157 : const char *pszDate =
158 2 : CSLFetchNameValue(m_papszIMDMD, "AUX_STRIP_ACQ_DATE_UT");
159 2 : if (nullptr != pszDate)
160 : {
161 : const char *pszTime =
162 2 : CSLFetchNameValue(m_papszIMDMD, "AUX_STRIP_ACQ_START_UT");
163 :
164 2 : if (nullptr == pszTime)
165 0 : pszTime = "000000.000000";
166 :
167 : char buffer[80];
168 : GIntBig timeMid =
169 2 : GetAcquisitionTimeFromString(CPLSPrintf("%sT%s", pszDate, pszTime));
170 : struct tm tmBuf;
171 2 : strftime(buffer, 80, MD_DATETIMEFORMAT,
172 2 : CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
173 2 : m_papszIMAGERYMD =
174 2 : CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_ACQDATETIME, buffer);
175 : }
176 : }
177 :
178 : /**
179 : * ReadTxtToList
180 : */
181 2 : char **GDALMDReaderKompsat::ReadTxtToList()
182 : {
183 2 : char **papszLines = CSLLoad(m_osIMDSourceFilename);
184 2 : if (nullptr == papszLines)
185 0 : return nullptr;
186 :
187 2 : char **papszIMD = nullptr;
188 : char szName[512];
189 : int i;
190 : size_t j;
191 2 : CPLString soGroupName;
192 :
193 18 : for (i = 0; papszLines[i] != nullptr; i++)
194 : {
195 16 : const char *pszLine = papszLines[i];
196 16 : const size_t nLineLenLimited = CPLStrnlen(pszLine, 512);
197 :
198 : // check if this is begin block
199 16 : if (STARTS_WITH_CI(pszLine, "BEGIN_"))
200 : {
201 0 : for (j = 6; j + 1 < nLineLenLimited; j++)
202 : {
203 0 : if (STARTS_WITH_CI(pszLine + j, "_BLOCK"))
204 : {
205 0 : szName[j - 6] = 0;
206 0 : break;
207 : }
208 0 : szName[j - 6] = pszLine[j];
209 : }
210 0 : szName[j - 6] = '\0';
211 :
212 0 : soGroupName = szName;
213 :
214 0 : continue;
215 : }
216 :
217 : // check if this is end block
218 16 : if (STARTS_WITH_CI(pszLine, "END_"))
219 : {
220 0 : soGroupName.clear(); // we don't expect subblocks
221 0 : continue;
222 : }
223 :
224 : // get name and value
225 288 : for (j = 0; j + 1 < nLineLenLimited; j++)
226 : {
227 288 : if (pszLine[j] == '\t')
228 : {
229 16 : if (soGroupName.empty() || j > 0)
230 : {
231 16 : szName[j] = 0;
232 16 : j++;
233 16 : break;
234 : }
235 : else
236 : {
237 0 : continue;
238 : }
239 : }
240 272 : szName[j] = pszLine[j];
241 : }
242 16 : szName[j] = '\0';
243 :
244 : // trim
245 16 : while (pszLine[j] == ' ')
246 0 : j++;
247 :
248 16 : if (soGroupName.empty())
249 : {
250 16 : papszIMD = CSLAddNameValue(papszIMD, szName, pszLine + j);
251 : }
252 : else
253 : {
254 0 : papszIMD = CSLAddNameValue(
255 : papszIMD, CPLSPrintf("%s.%s", soGroupName.c_str(), szName),
256 : pszLine + j);
257 : }
258 : }
259 :
260 2 : CSLDestroy(papszLines);
261 :
262 2 : return papszIMD;
263 : }
264 :
265 : /**
266 : * GetAcqisitionTimeFromString()
267 : */
268 : GIntBig
269 2 : GDALMDReaderKompsat::GetAcquisitionTimeFromString(const char *pszDateTime)
270 : {
271 2 : if (nullptr == pszDateTime)
272 0 : return 0;
273 :
274 : int iYear;
275 : int iMonth;
276 : int iDay;
277 : int iHours;
278 : int iMin;
279 : int iSec;
280 :
281 2 : int r = sscanf(pszDateTime, "%4d%2d%2dT%2d%2d%2d.%*s", &iYear, &iMonth,
282 : &iDay, &iHours, &iMin, &iSec);
283 :
284 2 : if (r != 6)
285 0 : return 0;
286 :
287 : struct tm tmDateTime;
288 2 : tmDateTime.tm_sec = iSec;
289 2 : tmDateTime.tm_min = iMin;
290 2 : tmDateTime.tm_hour = iHours;
291 2 : tmDateTime.tm_mday = iDay;
292 2 : tmDateTime.tm_mon = iMonth - 1;
293 2 : tmDateTime.tm_year = iYear - 1900;
294 2 : tmDateTime.tm_isdst = -1;
295 :
296 2 : return CPLYMDHMSToUnixTime(&tmDateTime);
297 : }
|