Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Core
4 : * Purpose: Read metadata (mainly the remote sensing imagery) from files of
5 : * different providers like DigitalGlobe, GeoEye etc.
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 : #ifndef GDAL_MDREADER_H_INCLUDED
15 : #define GDAL_MDREADER_H_INCLUDED
16 :
17 : #include "cpl_port.h"
18 : #include "gdal_priv.h"
19 :
20 : #include <map>
21 :
22 : #define MD_DOMAIN_IMD "IMD" /**< image metadata section */
23 : #define MD_DOMAIN_RPC "RPC" /**< rpc metadata section */
24 : #define MD_DOMAIN_IMAGERY "IMAGERY" /**< imagery metadata section */
25 : #define MD_DOMAIN_DEFAULT "" /**< default metadata section */
26 :
27 : #define MD_NAME_ACQDATETIME \
28 : "ACQUISITIONDATETIME" /**< Acquisition Date Time property name. The time \
29 : should be in UTC */
30 : #define MD_NAME_SATELLITE \
31 : "SATELLITEID" /**< Satellite identificator property name */
32 : #define MD_NAME_CLOUDCOVER \
33 : "CLOUDCOVER" /**< Cloud coverage property name. The value between 0 - 100 \
34 : or 999 if n/a */
35 : #define MD_NAME_MDTYPE \
36 : "METADATATYPE" /**< Metadata reader type property name. The reader \
37 : processed this metadata */
38 :
39 : #define MD_DATETIMEFORMAT "%Y-%m-%d %H:%M:%S" /**< Date time format */
40 : #define MD_CLOUDCOVER_NA "999" /**< The value if cloud cover is n/a */
41 :
42 : /**
43 : * RPC/RPB specific defines
44 : */
45 :
46 : #define RPC_ERR_BIAS "ERR_BIAS"
47 : #define RPC_ERR_RAND "ERR_RAND"
48 : #define RPC_LINE_OFF "LINE_OFF"
49 : #define RPC_SAMP_OFF "SAMP_OFF"
50 : #define RPC_LAT_OFF "LAT_OFF"
51 : #define RPC_LONG_OFF "LONG_OFF"
52 : #define RPC_HEIGHT_OFF "HEIGHT_OFF"
53 : #define RPC_LINE_SCALE "LINE_SCALE"
54 : #define RPC_SAMP_SCALE "SAMP_SCALE"
55 : #define RPC_LAT_SCALE "LAT_SCALE"
56 : #define RPC_LONG_SCALE "LONG_SCALE"
57 : #define RPC_HEIGHT_SCALE "HEIGHT_SCALE"
58 : #define RPC_LINE_NUM_COEFF "LINE_NUM_COEFF"
59 : #define RPC_LINE_DEN_COEFF "LINE_DEN_COEFF"
60 : #define RPC_SAMP_NUM_COEFF "SAMP_NUM_COEFF"
61 : #define RPC_SAMP_DEN_COEFF "SAMP_DEN_COEFF"
62 :
63 : /* Optional */
64 : #define RPC_MIN_LONG "MIN_LONG"
65 : #define RPC_MIN_LAT "MIN_LAT"
66 : #define RPC_MAX_LONG "MAX_LONG"
67 : #define RPC_MAX_LAT "MAX_LAT"
68 :
69 : /* Pleiades Neo nomenclature */
70 : #define RPC_LAT_NUM_COEFF "LAT_NUM_COEFF"
71 : #define RPC_LAT_DEN_COEFF "LAT_DEN_COEFF"
72 : #define RPC_LON_NUM_COEFF "LON_NUM_COEFF"
73 : #define RPC_LON_DEN_COEFF "LON_DEN_COEFF"
74 :
75 : /**
76 : * Enumerator of metadata readers
77 : */
78 :
79 : typedef enum
80 : {
81 : MDR_None = 0x00000000, /**< no reader */
82 : MDR_DG = 0x00000001, /**< Digital Globe, METADATATYPE=DG */
83 : MDR_GE = 0x00000002, /**< Geo Eye, METADATATYPE=GE */
84 : MDR_OV = 0x00000004, /**< Orb View, METADATATYPE=OV */
85 : MDR_PLEIADES = 0x00000008, /**< Pleiades, METADATATYPE=DIMAP */
86 : MDR_SPOT = 0x00000010, /**< Spot, METADATATYPE=DIMAP */
87 : MDR_RDK1 = 0x00000020, /**< Resurs DK1, METADATATYPE=MSP */
88 : MDR_LS = 0x00000040, /**< Landsat, METADATATYPE=ODL */
89 : MDR_RE = 0x00000080, /**< RapidEye, METADATATYPE=RE */
90 : MDR_KOMPSAT = 0x00000100, /**< Kompsat, METADATATYPE=KARI */
91 : MDR_EROS = 0x00000200, /**< EROS, METADATATYPE=EROS */
92 : MDR_ALOS = 0x00000400, /**< ALOS, METADATATYPE=ALOS */
93 : MDR_ANY = MDR_DG | MDR_GE | MDR_OV | MDR_PLEIADES | MDR_SPOT | MDR_RDK1 |
94 : MDR_LS | MDR_RE | MDR_KOMPSAT | MDR_EROS |
95 : MDR_ALOS /**< any reader */
96 : } MDReaders;
97 :
98 : /**
99 : * The base class for all metadata readers
100 : */
101 : class CPL_DLL GDALMDReaderBase
102 : {
103 :
104 : CPL_DISALLOW_COPY_ASSIGN(GDALMDReaderBase)
105 :
106 : static bool
107 : ReadXMLToListFirstPass(const CPLXMLNode *psNode,
108 : std::map<std::string, int> &oMapCountKeysFull,
109 : const std::string &osPrefixFull, int nDepth);
110 :
111 : char **ReadXMLToList(const CPLXMLNode *psNode, char **papszList,
112 : const std::map<std::string, int> &oMapCountKeysFullRef,
113 : std::map<std::string, int> &oMapCountKeysFull,
114 : std::map<std::string, int> &oMapCountKeys,
115 : const std::string &osPrefix,
116 : const std::string &osPrefixFull);
117 :
118 : public:
119 : GDALMDReaderBase(const char *pszPath, char **papszSiblingFiles);
120 : virtual ~GDALMDReaderBase();
121 :
122 : /**
123 : * @brief Get specified metadata domain
124 : * @param pszDomain The metadata domain to return
125 : * @return List of metadata items
126 : */
127 : virtual char **GetMetadataDomain(const char *pszDomain);
128 : /**
129 : * @brief Fill provided metadata store class
130 : * @param poMDMD Metadata store class
131 : * @return true on success or false
132 : */
133 : virtual bool FillMetadata(GDALMultiDomainMetadata *poMDMD);
134 : /**
135 : * @brief Determine whether the input parameter correspond to the particular
136 : * provider of remote sensing data completely
137 : * @return True if all needed sources files found
138 : */
139 : virtual bool HasRequiredFiles() const = 0;
140 : /**
141 : * @brief Get metadata file names. The caller become owner of returned list
142 : * and have to free it via CSLDestroy.
143 : * @return A file name list
144 : */
145 : virtual char **GetMetadataFiles() const = 0;
146 :
147 : protected:
148 : /**
149 : * @brief Load metadata to the correspondent IMD, RPB, IMAGERY and DEFAULT
150 : * domains
151 : */
152 : virtual void LoadMetadata();
153 : /**
154 : * @brief Convert string like 2012-02-25T00:25:59.9440000Z to time
155 : * @param pszDateTime String to convert
156 : * @return value in second sinc epoch 1970-01-01 00:00:00
157 : */
158 : virtual GIntBig GetAcquisitionTimeFromString(const char *pszDateTime);
159 : /**
160 : * @brief ReadXMLToList Transform xml to list of NULL terminated name=value
161 : * strings
162 : * @param psNode A xml node to process
163 : * @param papszList A list to fill with name=value strings
164 : * @param pszName A name of parent node. For root xml node should be empty.
165 : * If name is not empty, the sibling nodes will not proceed
166 : * @return An input list filled with values
167 : */
168 : virtual char **ReadXMLToList(CPLXMLNode *psNode, char **papszList,
169 : const char *pszName = "");
170 : /**
171 : * @brief AddXMLNameValueToList Execute from ReadXMLToList to add name and
172 : * value to list. One can override this function for special
173 : * processing input values before add to list.
174 : * @param papszList A list to fill with name=value strings
175 : * @param pszName A name to add
176 : * @param pszValue A value to add
177 : * @return An input list filled with values
178 : */
179 : virtual char **AddXMLNameValueToList(char **papszList, const char *pszName,
180 : const char *pszValue);
181 :
182 : protected:
183 : //! @cond Doxygen_Suppress
184 : char **m_papszIMDMD = nullptr;
185 : char **m_papszRPCMD = nullptr;
186 : char **m_papszIMAGERYMD = nullptr;
187 : char **m_papszDEFAULTMD = nullptr;
188 : bool m_bIsMetadataLoad = false;
189 : //! @endcond
190 : };
191 :
192 : /**
193 : * The metadata reader main class.
194 : * The main purpose of this class is to provide an correspondent reader
195 : * for provided path.
196 : */
197 5502 : class CPL_DLL GDALMDReaderManager
198 : {
199 :
200 : CPL_DISALLOW_COPY_ASSIGN(GDALMDReaderManager)
201 :
202 : public:
203 : GDALMDReaderManager();
204 : virtual ~GDALMDReaderManager();
205 :
206 : /**
207 : * @brief Try to detect metadata reader correspondent to the provided
208 : * datasource path
209 : * @param pszPath a path to GDALDataset
210 : * @param papszSiblingFiles file list for metadata search purposes
211 : * @param nType a preferable reader type (may be the OR of MDReaders)
212 : * @return an appropriate reader or NULL if no such reader or error.
213 : * The pointer delete by the GDALMDReaderManager, so the user have not
214 : * delete it.
215 : */
216 : virtual GDALMDReaderBase *GetReader(const char *pszPath,
217 : char **papszSiblingFiles,
218 : GUInt32 nType = MDR_ANY);
219 :
220 : protected:
221 : //! @cond Doxygen_Suppress
222 : GDALMDReaderBase *m_pReader = nullptr;
223 : //! @endcond
224 : };
225 :
226 : // misc
227 : CPLString CPLStrip(const CPLString &osString, const char cChar);
228 : CPLString CPLStripQuotes(const CPLString &osString);
229 : char **GDALLoadRPBFile(const CPLString &osFilePath);
230 : char CPL_DLL **GDALLoadRPCFile(const CPLString &osFilePath);
231 : char **GDALLoadIMDFile(const CPLString &osFilePath);
232 : bool GDALCheckFileHeader(const CPLString &soFilePath, const char *pszTestString,
233 : int nBufferSize = 256);
234 :
235 : CPLErr GDALWriteRPBFile(const char *pszFilename, char **papszMD);
236 : CPLErr CPL_DLL GDALWriteRPCTXTFile(const char *pszFilename, char **papszMD);
237 : CPLErr GDALWriteIMDFile(const char *pszFilename, char **papszMD);
238 :
239 : #endif // GDAL_MDREADER_H_INCLUDED
|