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