1 /******************************************************************************
2 *
3 * Project: GDAL Core
4 * Purpose: Read metadata from Resurs-DK1 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_rdk1.h"
32
33 #include <cstdio>
34
35 #include "cpl_error.h"
36 #include "cpl_minixml.h"
37 #include "cpl_string.h"
38 #include "gdal_priv.h"
39
40 CPL_CVSID("$Id: reader_rdk1.cpp 7e07230bbff24eb333608de4dbd460b7312839d0 2017-12-11 19:08:47Z Even Rouault $")
41
42 /**
43 * GDALMDReaderResursDK1()
44 */
GDALMDReaderResursDK1(const char * pszPath,char ** papszSiblingFiles)45 GDALMDReaderResursDK1::GDALMDReaderResursDK1(const char *pszPath,
46 char **papszSiblingFiles) :
47 GDALMDReaderBase(pszPath, papszSiblingFiles),
48 m_osXMLSourceFilename( GDALFindAssociatedFile( pszPath, "XML",
49 papszSiblingFiles, 0 ) )
50 {
51 if( !m_osXMLSourceFilename.empty() )
52 CPLDebug( "MDReaderResursDK1", "XML Filename: %s",
53 m_osXMLSourceFilename.c_str() );
54 }
55
56 /**
57 * ~GDALMDReaderResursDK1()
58 */
~GDALMDReaderResursDK1()59 GDALMDReaderResursDK1::~GDALMDReaderResursDK1()
60 {
61 }
62
63 /**
64 * HasRequiredFiles()
65 */
HasRequiredFiles() const66 bool GDALMDReaderResursDK1::HasRequiredFiles() const
67 {
68 // check <MSP_ROOT>
69 if (!m_osXMLSourceFilename.empty() &&
70 GDALCheckFileHeader(m_osXMLSourceFilename, "<MSP_ROOT>"))
71 return true;
72
73 return false;
74 }
75
76 /**
77 * GetMetadataFiles()
78 */
GetMetadataFiles() const79 char** GDALMDReaderResursDK1::GetMetadataFiles() const
80 {
81 char **papszFileList = nullptr;
82 if(!m_osXMLSourceFilename.empty())
83 papszFileList= CSLAddString( papszFileList, m_osXMLSourceFilename );
84
85 return papszFileList;
86 }
87
88 /**
89 * LoadMetadata()
90 */
LoadMetadata()91 void GDALMDReaderResursDK1::LoadMetadata()
92 {
93 if(m_bIsMetadataLoad)
94 return;
95
96 if (!m_osXMLSourceFilename.empty())
97 {
98 CPLXMLNode* psNode = CPLParseXMLFile(m_osXMLSourceFilename);
99
100 if(psNode != nullptr)
101 {
102 CPLXMLNode* pMSPRootNode = CPLSearchXMLNode(psNode, "=MSP_ROOT");
103
104 if(pMSPRootNode != nullptr)
105 {
106 m_papszIMDMD = ReadXMLToList(pMSPRootNode, m_papszIMDMD, "MSP_ROOT");
107 }
108 CPLDestroyXMLNode(psNode);
109 }
110 }
111
112 m_papszDEFAULTMD = CSLAddNameValue(m_papszDEFAULTMD, MD_NAME_MDTYPE, "MSP");
113
114 m_bIsMetadataLoad = true;
115
116 if(nullptr == m_papszIMDMD)
117 {
118 return;
119 }
120
121 //extract imagery metadata
122 const char* pszSatId = CSLFetchNameValue(m_papszIMDMD, "MSP_ROOT.cCodeKA");
123 if(nullptr != pszSatId)
124 {
125 m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_SATELLITE,
126 CPLStripQuotes(pszSatId));
127 }
128
129 const char* pszDate = CSLFetchNameValue(m_papszIMDMD,
130 "MSP_ROOT.Normal.dSceneDate");
131
132 if(nullptr != pszDate)
133 {
134 const char* pszTime = CSLFetchNameValue(m_papszIMDMD,
135 "MSP_ROOT.Normal.tSceneTime");
136 if(nullptr == pszTime)
137 pszTime = "00:00:00.000000";
138
139 char buffer[80];
140 time_t timeMid = GetAcquisitionTimeFromString(CPLSPrintf( "%s %s",
141 pszDate, pszTime));
142 strftime (buffer, 80, MD_DATETIMEFORMAT, localtime(&timeMid));
143 m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
144 MD_NAME_ACQDATETIME, buffer);
145 }
146
147 m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD, MD_NAME_CLOUDCOVER,
148 MD_CLOUDCOVER_NA);
149 }
150
151 /**
152 * GetAcqisitionTimeFromString()
153 */
GetAcquisitionTimeFromString(const char * pszDateTime)154 time_t GDALMDReaderResursDK1::GetAcquisitionTimeFromString(
155 const char* pszDateTime)
156 {
157 if(nullptr == pszDateTime)
158 return 0;
159
160 int iYear;
161 int iMonth;
162 int iDay;
163 int iHours;
164 int iMin;
165 int iSec;
166
167 // string example <Normal>
168 // tSceneTime = 10:21:36.000000
169 // dSceneDate = 16/9/2008
170 // </Normal>
171
172 int r = sscanf ( pszDateTime, "%d/%d/%d %d:%d:%d.%*s",
173 &iDay, &iMonth, &iYear, &iHours, &iMin, &iSec);
174
175 if (r != 6)
176 return 0;
177
178 struct tm tmDateTime;
179 tmDateTime.tm_sec = iSec;
180 tmDateTime.tm_min = iMin;
181 tmDateTime.tm_hour = iHours;
182 tmDateTime.tm_mday = iDay;
183 tmDateTime.tm_mon = iMonth - 1;
184 tmDateTime.tm_year = iYear - 1900;
185 tmDateTime.tm_isdst = -1;
186
187 return mktime(&tmDateTime) - 10800; // int UTC+3 MSK
188 }
189
AddXMLNameValueToList(char ** papszList,const char * pszName,const char * pszValue)190 char** GDALMDReaderResursDK1::AddXMLNameValueToList(char** papszList,
191 const char *pszName,
192 const char *pszValue)
193 {
194 char** papszTokens = CSLTokenizeString2( pszValue, "\n",
195 CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
196
197 for(int i = 0; papszTokens[i] != nullptr; i++ )
198 {
199
200 char** papszSubTokens = CSLTokenizeString2( papszTokens[i], "=",
201 CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
202 if(CSLCount(papszSubTokens) < 2)
203 {
204 CSLDestroy( papszSubTokens );
205 continue;
206 }
207
208 papszList = CSLAddNameValue(papszList, CPLSPrintf("%s.%s", pszName,
209 papszSubTokens[0]),
210 papszSubTokens[1]);
211 CSLDestroy( papszSubTokens );
212 }
213
214 CSLDestroy( papszTokens );
215
216 return papszList;
217 }
218