Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Core
4 : * Purpose: Read metadata from Alos 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 "reader_alos.h"
15 :
16 : #include <cstdio>
17 : #include <cstdlib>
18 :
19 : #include <string>
20 :
21 : #include "cpl_conv.h"
22 : #include "cpl_error.h"
23 : #include "cpl_string.h"
24 : #include "cpl_time.h"
25 : #include "gdal_mdreader.h"
26 :
27 : /**
28 : * GDALMDReaderALOS()
29 : */
30 5079 : GDALMDReaderALOS::GDALMDReaderALOS(const char *pszPath,
31 5079 : char **papszSiblingFiles)
32 5079 : : GDALMDReaderBase(pszPath, papszSiblingFiles)
33 : {
34 10158 : CPLString osDirName = CPLGetDirname(pszPath);
35 10158 : CPLString osBaseName = CPLGetBasename(pszPath);
36 :
37 : CPLString osIMDSourceFilename =
38 10158 : CPLFormFilename(osDirName, "summary", ".txt");
39 5079 : if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
40 : {
41 1 : m_osIMDSourceFilename = std::move(osIMDSourceFilename);
42 : }
43 : else
44 : {
45 5078 : osIMDSourceFilename = CPLFormFilename(osDirName, "SUMMARY", ".TXT");
46 5078 : if (CPLCheckForFile(&osIMDSourceFilename[0], papszSiblingFiles))
47 : {
48 0 : m_osIMDSourceFilename = std::move(osIMDSourceFilename);
49 : }
50 : }
51 :
52 5079 : if (osBaseName.size() >= 6)
53 : {
54 : // check if this is separate band or whole image
55 : // test without 6 symbols
56 : CPLString osHDRFileName = CPLFormFilename(
57 6268 : osDirName, CPLSPrintf("HDR%s", osBaseName + 6), "txt");
58 3134 : if (CPLCheckForFile(&osHDRFileName[0], papszSiblingFiles))
59 : {
60 0 : m_osHDRSourceFilename = std::move(osHDRFileName);
61 : }
62 : else
63 : {
64 : osHDRFileName = CPLFormFilename(
65 3134 : osDirName, CPLSPrintf("HDR%s", osBaseName + 6), "TXT");
66 3134 : if (CPLCheckForFile(&osHDRFileName[0], papszSiblingFiles))
67 : {
68 0 : m_osHDRSourceFilename = std::move(osHDRFileName);
69 : }
70 : }
71 : }
72 :
73 : // test without 3 symbols
74 5079 : if (osBaseName.size() >= 3 && m_osHDRSourceFilename.empty())
75 : {
76 : CPLString osHDRFileName = CPLFormFilename(
77 10122 : osDirName, CPLSPrintf("HDR%s", osBaseName + 3), "txt");
78 5061 : if (CPLCheckForFile(&osHDRFileName[0], papszSiblingFiles))
79 : {
80 0 : m_osHDRSourceFilename = std::move(osHDRFileName);
81 : }
82 : else
83 : {
84 : osHDRFileName = CPLFormFilename(
85 5061 : osDirName, CPLSPrintf("HDR%s", osBaseName + 3), "TXT");
86 5061 : if (CPLCheckForFile(&osHDRFileName[0], papszSiblingFiles))
87 : {
88 0 : m_osHDRSourceFilename = std::move(osHDRFileName);
89 : }
90 : }
91 : }
92 :
93 : // test without 6 symbols
94 5079 : if (osBaseName.size() >= 6)
95 : {
96 : CPLString osRPCFileName = CPLFormFilename(
97 6268 : osDirName, CPLSPrintf("RPC%s", osBaseName + 6), "txt");
98 3134 : if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
99 : {
100 0 : m_osRPBSourceFilename = std::move(osRPCFileName);
101 : }
102 : else
103 : {
104 : osRPCFileName = CPLFormFilename(
105 3134 : osDirName, CPLSPrintf("RPC%s", osBaseName + 6), "TXT");
106 3134 : if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
107 : {
108 0 : m_osRPBSourceFilename = std::move(osRPCFileName);
109 : }
110 : }
111 : }
112 :
113 : // test without 3 symbols
114 5079 : if (osBaseName.size() >= 3 && m_osRPBSourceFilename.empty())
115 : {
116 : CPLString osRPCFileName = CPLFormFilename(
117 10122 : osDirName, CPLSPrintf("RPC%s", osBaseName + 3), "txt");
118 5061 : if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
119 : {
120 1 : m_osRPBSourceFilename = std::move(osRPCFileName);
121 : }
122 : else
123 : {
124 : osRPCFileName = CPLFormFilename(
125 5060 : osDirName, CPLSPrintf("RPC%s", osBaseName + 3), "TXT");
126 5060 : if (CPLCheckForFile(&osRPCFileName[0], papszSiblingFiles))
127 : {
128 0 : m_osRPBSourceFilename = std::move(osRPCFileName);
129 : }
130 : }
131 : }
132 :
133 5079 : if (!m_osIMDSourceFilename.empty())
134 1 : CPLDebug("MDReaderALOS", "IMD Filename: %s",
135 : m_osIMDSourceFilename.c_str());
136 5079 : if (!m_osHDRSourceFilename.empty())
137 0 : CPLDebug("MDReaderALOS", "HDR Filename: %s",
138 : m_osHDRSourceFilename.c_str());
139 5079 : if (!m_osRPBSourceFilename.empty())
140 1 : CPLDebug("MDReaderALOS", "RPB Filename: %s",
141 : m_osRPBSourceFilename.c_str());
142 5079 : }
143 :
144 : /**
145 : * ~GDALMDReaderALOS()
146 : */
147 10158 : GDALMDReaderALOS::~GDALMDReaderALOS()
148 : {
149 10158 : }
150 :
151 : /**
152 : * HasRequiredFiles()
153 : */
154 5079 : bool GDALMDReaderALOS::HasRequiredFiles() const
155 : {
156 5079 : if (!m_osIMDSourceFilename.empty())
157 1 : return true;
158 :
159 5078 : if (!m_osHDRSourceFilename.empty() && !m_osRPBSourceFilename.empty())
160 0 : return true;
161 :
162 5078 : return false;
163 : }
164 :
165 : /**
166 : * GetMetadataFiles()
167 : */
168 1 : char **GDALMDReaderALOS::GetMetadataFiles() const
169 : {
170 1 : char **papszFileList = nullptr;
171 1 : if (!m_osIMDSourceFilename.empty())
172 1 : papszFileList = CSLAddString(papszFileList, m_osIMDSourceFilename);
173 1 : if (!m_osHDRSourceFilename.empty())
174 0 : papszFileList = CSLAddString(papszFileList, m_osHDRSourceFilename);
175 1 : if (!m_osRPBSourceFilename.empty())
176 1 : papszFileList = CSLAddString(papszFileList, m_osRPBSourceFilename);
177 :
178 1 : return papszFileList;
179 : }
180 :
181 : /**
182 : * LoadMetadata()
183 : */
184 2 : void GDALMDReaderALOS::LoadMetadata()
185 : {
186 2 : if (m_bIsMetadataLoad)
187 1 : return;
188 :
189 1 : if (!m_osIMDSourceFilename.empty())
190 : {
191 1 : m_papszIMDMD = CSLLoad(m_osIMDSourceFilename);
192 : }
193 :
194 1 : if (!m_osHDRSourceFilename.empty())
195 : {
196 0 : if (nullptr == m_papszIMDMD)
197 : {
198 0 : m_papszIMDMD = CSLLoad(m_osHDRSourceFilename);
199 : }
200 : else
201 : {
202 0 : char **papszHDR = CSLLoad(m_osHDRSourceFilename);
203 0 : m_papszIMDMD = CSLMerge(m_papszIMDMD, papszHDR);
204 0 : CSLDestroy(papszHDR);
205 : }
206 : }
207 :
208 1 : m_papszRPCMD = LoadRPCTxtFile();
209 :
210 1 : m_papszDEFAULTMD =
211 1 : CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "ALOS");
212 :
213 1 : m_bIsMetadataLoad = true;
214 :
215 1 : const char *pszSatId1 = CSLFetchNameValue(m_papszIMDMD, "Lbi_Satellite");
216 1 : const char *pszSatId2 = CSLFetchNameValue(m_papszIMDMD, "Lbi_Sensor");
217 1 : if (nullptr != pszSatId1 && nullptr != pszSatId2)
218 : {
219 2 : m_papszIMAGERYMD = CSLAddNameValue(
220 : m_papszIMAGERYMD, MD_NAME_SATELLITE,
221 2 : CPLSPrintf("%s %s", CPLStripQuotes(pszSatId1).c_str(),
222 2 : CPLStripQuotes(pszSatId2).c_str()));
223 : }
224 0 : else if (nullptr != pszSatId1 && nullptr == pszSatId2)
225 : {
226 0 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
227 0 : CPLStripQuotes(pszSatId1));
228 : }
229 0 : else if (nullptr == pszSatId1 && nullptr != pszSatId2)
230 : {
231 0 : m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
232 0 : CPLStripQuotes(pszSatId2));
233 : }
234 :
235 : const char *pszCloudCover =
236 1 : CSLFetchNameValue(m_papszIMDMD, "Img_CloudQuantityOfAllImage");
237 1 : if (nullptr != pszCloudCover)
238 : {
239 0 : int nCC = atoi(pszCloudCover);
240 0 : if (nCC >= 99)
241 : {
242 0 : m_papszIMAGERYMD = CSLAddNameValue(
243 : m_papszIMAGERYMD, MD_NAME_CLOUDCOVER, MD_CLOUDCOVER_NA);
244 : }
245 : else
246 : {
247 0 : m_papszIMAGERYMD =
248 0 : CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
249 : CPLSPrintf("%d", nCC * 10));
250 : }
251 : }
252 :
253 : const char *pszDate =
254 1 : CSLFetchNameValue(m_papszIMDMD, "Img_SceneCenterDateTime");
255 :
256 1 : if (nullptr != pszDate)
257 : {
258 : char buffer[80];
259 0 : GIntBig timeMid = GetAcquisitionTimeFromString(CPLStripQuotes(pszDate));
260 : struct tm tmBuf;
261 0 : strftime(buffer, 80, MD_DATETIMEFORMAT,
262 0 : CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
263 0 : m_papszIMAGERYMD =
264 0 : CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_ACQDATETIME, buffer);
265 : }
266 : else
267 : {
268 1 : pszDate = CSLFetchNameValue(m_papszIMDMD, "Lbi_ObservationDate");
269 1 : if (nullptr != pszDate)
270 : {
271 1 : const char *pszTime = "00:00:00.000";
272 :
273 : char buffer[80];
274 2 : GIntBig timeMid = GetAcquisitionTimeFromString(
275 2 : CPLSPrintf("%s %s", CPLStripQuotes(pszDate).c_str(),
276 2 : CPLStripQuotes(pszTime).c_str()));
277 : struct tm tmBuf;
278 1 : strftime(buffer, 80, MD_DATETIMEFORMAT,
279 1 : CPLUnixTimeToYMDHMS(timeMid, &tmBuf));
280 1 : m_papszIMAGERYMD =
281 1 : CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_ACQDATETIME, buffer);
282 : }
283 : }
284 : }
285 :
286 : /**
287 : * LoadRPCTxtFile
288 : */
289 1 : char **GDALMDReaderALOS::LoadRPCTxtFile()
290 : {
291 1 : if (m_osRPBSourceFilename.empty())
292 0 : return nullptr;
293 :
294 2 : const CPLStringList aosLines(CSLLoad(m_osRPBSourceFilename));
295 1 : if (aosLines.empty())
296 0 : return nullptr;
297 :
298 1 : const char *pszFirstRow = aosLines[0];
299 2 : CPLStringList aosRPB;
300 1 : if (nullptr != pszFirstRow)
301 : {
302 : static const struct
303 : {
304 : const char *pszName;
305 : int nSize;
306 : } apsFieldDescriptors[] = {
307 : {RPC_LINE_OFF, 6}, {RPC_SAMP_OFF, 5}, {RPC_LAT_OFF, 8},
308 : {RPC_LONG_OFF, 9}, {RPC_HEIGHT_OFF, 5}, {RPC_LINE_SCALE, 6},
309 : {RPC_SAMP_SCALE, 5}, {RPC_LAT_SCALE, 8}, {RPC_LONG_SCALE, 9},
310 : {RPC_HEIGHT_SCALE, 5},
311 : };
312 :
313 1 : int nRequiredSize = 0;
314 11 : for (const auto &sFieldDescriptor : apsFieldDescriptors)
315 : {
316 10 : nRequiredSize += sFieldDescriptor.nSize;
317 : }
318 :
319 : static const char *const apszRPCTXT20ValItems[] = {
320 : RPC_LINE_NUM_COEFF, RPC_LINE_DEN_COEFF, RPC_SAMP_NUM_COEFF,
321 : RPC_SAMP_DEN_COEFF};
322 :
323 1 : constexpr int RPC_COEFF_COUNT1 = CPL_ARRAYSIZE(apszRPCTXT20ValItems);
324 1 : constexpr int RPC_COEFF_COUNT2 = 20;
325 1 : constexpr int RPC_COEFF_SIZE = 12;
326 1 : nRequiredSize += RPC_COEFF_COUNT1 * RPC_COEFF_COUNT2 * RPC_COEFF_SIZE;
327 1 : if (strlen(pszFirstRow) < static_cast<size_t>(nRequiredSize))
328 : {
329 0 : CPLError(CE_Failure, CPLE_AppDefined,
330 : "%s has only %d bytes wherea %d are required",
331 0 : m_osRPBSourceFilename.c_str(), int(strlen(pszFirstRow)),
332 : nRequiredSize);
333 0 : return nullptr;
334 : }
335 :
336 1 : int nOffset = 0;
337 1 : char buff[16] = {0};
338 11 : for (const auto &sFieldDescriptor : apsFieldDescriptors)
339 : {
340 10 : CPLAssert(sFieldDescriptor.nSize < int(sizeof(buff)));
341 10 : memcpy(buff, pszFirstRow + nOffset, sFieldDescriptor.nSize);
342 10 : buff[sFieldDescriptor.nSize] = 0;
343 10 : aosRPB.SetNameValue(sFieldDescriptor.pszName, buff);
344 10 : nOffset += sFieldDescriptor.nSize;
345 : }
346 :
347 5 : for (const char *pszItem : apszRPCTXT20ValItems)
348 : {
349 8 : std::string osValue;
350 84 : for (int j = 0; j < RPC_COEFF_COUNT2; j++)
351 : {
352 80 : memcpy(buff, pszFirstRow + nOffset, RPC_COEFF_SIZE);
353 80 : buff[RPC_COEFF_SIZE] = 0;
354 80 : nOffset += RPC_COEFF_SIZE;
355 :
356 80 : if (!osValue.empty())
357 76 : osValue += " ";
358 80 : osValue += buff;
359 : }
360 4 : aosRPB.SetNameValue(pszItem, osValue.c_str());
361 : }
362 : }
363 :
364 1 : return aosRPB.StealList();
365 : }
366 :
367 : /**
368 : * GetAcqisitionTimeFromString()
369 : */
370 1 : GIntBig GDALMDReaderALOS::GetAcquisitionTimeFromString(const char *pszDateTime)
371 : {
372 1 : if (nullptr == pszDateTime)
373 0 : return 0;
374 :
375 : int iYear;
376 : int iMonth;
377 : int iDay;
378 : int iHours;
379 : int iMin;
380 : int iSec;
381 :
382 1 : int r = sscanf(pszDateTime, "%4d%2d%2d %d:%d:%d.%*d", &iYear, &iMonth,
383 : &iDay, &iHours, &iMin, &iSec);
384 :
385 1 : if (r != 6)
386 0 : return 0;
387 :
388 : struct tm tmDateTime;
389 1 : tmDateTime.tm_sec = iSec;
390 1 : tmDateTime.tm_min = iMin;
391 1 : tmDateTime.tm_hour = iHours;
392 1 : tmDateTime.tm_mday = iDay;
393 1 : tmDateTime.tm_mon = iMonth - 1;
394 1 : tmDateTime.tm_year = iYear - 1900;
395 1 : tmDateTime.tm_isdst = -1;
396 :
397 1 : return CPLYMDHMSToUnixTime(&tmDateTime);
398 : }
|