1 /******************************************************************************
2  * $Id: gdal_mdreader.h d8114610ec3abbffbfce3dfbd353ea53ac81c013 2021-03-04 05:38:17 -0500 John Papadakis $
3  *
4  * Project:  GDAL Core
5  * Purpose:  Read metadata (mainly the remote sensing imagery) from files of
6  *           different providers like DigitalGlobe, GeoEye etc.
7  * Author:   Dmitry Baryshnikov, polimax@mail.ru
8  *
9  ******************************************************************************
10  * Copyright (c) 2014-2015, NextGIS info@nextgis.ru
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  ****************************************************************************/
30 
31 #ifndef GDAL_MDREADER_H_INCLUDED
32 #define GDAL_MDREADER_H_INCLUDED
33 
34 #include "cpl_port.h"
35 #include "gdal_priv.h"
36 
37 #define MD_DOMAIN_IMD "IMD"              /**< image metadata section */
38 #define MD_DOMAIN_RPC "RPC"              /**< rpc metadata section */
39 #define MD_DOMAIN_IMAGERY "IMAGERY"      /**< imagery metadata section */
40 #define MD_DOMAIN_DEFAULT ""             /**< default metadata section */
41 
42 #define MD_NAME_ACQDATETIME "ACQUISITIONDATETIME"  /**< Acquisition Date Time property name. The time should be in UTC */
43 #define MD_NAME_SATELLITE   "SATELLITEID"          /**< Satellite identificator property name */
44 #define MD_NAME_CLOUDCOVER  "CLOUDCOVER"           /**< Cloud coverage property name. The value between 0 - 100 or 999 if n/a */
45 #define MD_NAME_MDTYPE      "METADATATYPE"         /**< Metadata reader type property name. The reader processed this metadata */
46 
47 #define MD_DATETIMEFORMAT "%Y-%m-%d %H:%M:%S"      /**< Date time format */
48 #define MD_CLOUDCOVER_NA "999"           /**< The value if cloud cover is n/a */
49 
50 /**
51  * RPC/RPB specific defines
52  */
53 
54 #define RPC_ERR_BIAS        "ERR_BIAS"
55 #define RPC_ERR_RAND        "ERR_RAND"
56 #define RPC_LINE_OFF        "LINE_OFF"
57 #define RPC_SAMP_OFF        "SAMP_OFF"
58 #define RPC_LAT_OFF         "LAT_OFF"
59 #define RPC_LONG_OFF        "LONG_OFF"
60 #define RPC_HEIGHT_OFF      "HEIGHT_OFF"
61 #define RPC_LINE_SCALE      "LINE_SCALE"
62 #define RPC_SAMP_SCALE      "SAMP_SCALE"
63 #define RPC_LAT_SCALE       "LAT_SCALE"
64 #define RPC_LONG_SCALE      "LONG_SCALE"
65 #define RPC_HEIGHT_SCALE    "HEIGHT_SCALE"
66 #define RPC_LINE_NUM_COEFF  "LINE_NUM_COEFF"
67 #define RPC_LINE_DEN_COEFF  "LINE_DEN_COEFF"
68 #define RPC_SAMP_NUM_COEFF  "SAMP_NUM_COEFF"
69 #define RPC_SAMP_DEN_COEFF  "SAMP_DEN_COEFF"
70 
71 /* Optional */
72 #define RPC_MIN_LONG        "MIN_LONG"
73 #define RPC_MIN_LAT         "MIN_LAT"
74 #define RPC_MAX_LONG        "MAX_LONG"
75 #define RPC_MAX_LAT         "MAX_LAT"
76 
77 /**
78  * Enumerator of metadata readers
79  */
80 
81 typedef enum {
82     MDR_None     = 0x00000000,    /**< no reader */
83     MDR_DG       = 0x00000001,    /**< Digital Globe, METADATATYPE=DG */
84     MDR_GE       = 0x00000002,    /**< Geo Eye,       METADATATYPE=GE */
85     MDR_OV       = 0x00000004,    /**< Orb View,      METADATATYPE=OV */
86     MDR_PLEIADES = 0x00000008,    /**< Pleiades,      METADATATYPE=DIMAP */
87     MDR_SPOT     = 0x00000010,    /**< Spot,          METADATATYPE=DIMAP */
88     MDR_RDK1     = 0x00000020,    /**< Resurs DK1,    METADATATYPE=MSP */
89     MDR_LS       = 0x00000040,    /**< Landsat,       METADATATYPE=ODL */
90     MDR_RE       = 0x00000080,    /**< RapidEye,      METADATATYPE=RE */
91     MDR_KOMPSAT  = 0x00000100,    /**< Kompsat,       METADATATYPE=KARI */
92     MDR_EROS     = 0x00000200,    /**< EROS,          METADATATYPE=EROS */
93     MDR_ALOS     = 0x00000400,    /**< ALOS,          METADATATYPE=ALOS */
94     MDR_ANY  = MDR_DG | MDR_GE | MDR_OV | MDR_PLEIADES | MDR_SPOT | MDR_RDK1 |
95                MDR_LS | MDR_RE | MDR_KOMPSAT | MDR_EROS | MDR_ALOS /**< any reader */
96 } MDReaders;
97 
98 /**
99  * The base class for all metadata readers
100  */
101 class GDALMDReaderBase{
102 
103     CPL_DISALLOW_COPY_ASSIGN(GDALMDReaderBase)
104 
105 public:
106     GDALMDReaderBase(const char *pszPath, char **papszSiblingFiles);
107     virtual ~GDALMDReaderBase();
108 
109     /**
110      * @brief Get specified metadata domain
111      * @param pszDomain The metadata domain to return
112      * @return List of metadata items
113      */
114     virtual char ** GetMetadataDomain(const char *pszDomain);
115     /**
116      * @brief Fill provided metadata store class
117      * @param poMDMD Metadata store class
118      * @return true on success or false
119      */
120     virtual bool FillMetadata(GDALMultiDomainMetadata* poMDMD);
121     /**
122       * @brief Determine whether the input parameter correspond to the particular
123       *        provider of remote sensing data completely
124       * @return True if all needed sources files found
125       */
126     virtual bool HasRequiredFiles() const = 0;
127     /**
128      * @brief Get metadata file names. The caller become owner of returned list
129      *        and have to free it via CSLDestroy.
130      * @return A file name list
131      */
132     virtual char** GetMetadataFiles() const = 0;
133 protected:
134     /**
135      * @brief Load metadata to the correspondent IMD, RPB, IMAGERY and DEFAULT
136      *        domains
137      */
138     virtual void LoadMetadata();
139     /**
140      * @brief Convert string like 2012-02-25T00:25:59.9440000Z to time
141      * @param pszDateTime String to convert
142      * @return value in time_t
143      */
144     virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
145     /**
146      * @brief ReadXMLToList Transform xml to list of NULL terminated name=value
147      *        strings
148      * @param psNode A xml node to process
149      * @param papszList A list to fill with name=value strings
150      * @param pszName A name of parent node. For root xml node should be empty.
151      *        If name is not empty, the sibling nodes will not proceed
152      * @return An input list filled with values
153      */
154     virtual char** ReadXMLToList(CPLXMLNode* psNode, char** papszList,
155                          const char* pszName = "");
156     /**
157      * @brief AddXMLNameValueToList Execute from ReadXMLToList to add name and
158      *        value to list. One can override this function for special
159      *        processing input values before add to list.
160      * @param papszList A list to fill with name=value strings
161      * @param pszName A name to add
162      * @param pszValue A value to add
163      * @return An input list filled with values
164      */
165     virtual char** AddXMLNameValueToList(char** papszList, const char *pszName,
166                                          const char *pszValue);
167 protected:
168 //! @cond Doxygen_Suppress
169     char **m_papszIMDMD = nullptr;
170     char **m_papszRPCMD = nullptr;
171     char **m_papszIMAGERYMD = nullptr;
172     char **m_papszDEFAULTMD = nullptr;
173     bool m_bIsMetadataLoad = false;
174 //! @endcond
175 };
176 
177 /**
178  * The metadata reader main class.
179  * The main purpose of this class is to provide an correspondent reader
180  * for provided path.
181  */
182 class CPL_DLL GDALMDReaderManager{
183 
184     CPL_DISALLOW_COPY_ASSIGN(GDALMDReaderManager)
185 
186 public:
187     GDALMDReaderManager();
188     virtual ~GDALMDReaderManager();
189 
190     /**
191      * @brief Try to detect metadata reader correspondent to the provided
192      *        datasource path
193      * @param pszPath a path to GDALDataset
194      * @param papszSiblingFiles file list for metadata search purposes
195      * @param nType a preferable reader type (may be the OR of MDReaders)
196      * @return an appropriate reader or NULL if no such reader or error.
197      * The pointer delete by the GDALMDReaderManager, so the user have not
198      * delete it.
199      */
200     virtual GDALMDReaderBase* GetReader(const char *pszPath,
201                                         char **papszSiblingFiles,
202                                         GUInt32 nType = MDR_ANY);
203 protected:
204 //! @cond Doxygen_Suppress
205     GDALMDReaderBase *m_pReader = nullptr;
206 //! @endcond
207 };
208 
209 // misc
210 CPLString CPLStrip(const CPLString& osString, const char cChar);
211 CPLString CPLStripQuotes(const CPLString& osString);
212 char** GDALLoadRPBFile( const CPLString& osFilePath );
213 char** GDALLoadRPCFile( const CPLString& osFilePath );
214 char** GDALLoadIMDFile( const CPLString& osFilePath );
215 bool GDALCheckFileHeader(const CPLString& soFilePath,
216                                const char * pszTestString,
217                                int nBufferSize = 256);
218 
219 CPLErr GDALWriteRPBFile( const char *pszFilename, char **papszMD );
220 CPLErr GDALWriteRPCTXTFile( const char *pszFilename, char **papszMD );
221 CPLErr GDALWriteIMDFile( const char *pszFilename, char **papszMD );
222 
223 #endif //GDAL_MDREADER_H_INCLUDED
224