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