Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GRIB Driver 4 : * Purpose: GDALDataset driver for GRIB translator for read support 5 : * Author: Bas Retsios, retsios@itc.nl 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2007, ITC 9 : * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com> 10 : * 11 : * SPDX-License-Identifier: MIT 12 : ****************************************************************************** 13 : * 14 : */ 15 : 16 : #ifndef GRIBDATASET_H 17 : #define GRIBDATASET_H 18 : 19 : #include "cpl_port.h" 20 : 21 : #include <cerrno> 22 : #include <cmath> 23 : #include <cstddef> 24 : #include <cstdio> 25 : #include <cstdlib> 26 : #include <cstring> 27 : #if HAVE_FCNTL_H 28 : #include <fcntl.h> 29 : #endif 30 : #include <time.h> 31 : 32 : #include <algorithm> 33 : #include <memory> 34 : #include <string> 35 : 36 : #include "cpl_conv.h" 37 : #include "cpl_error.h" 38 : #include "cpl_multiproc.h" 39 : #include "cpl_string.h" 40 : #include "cpl_vsi.h" 41 : #include "degrib/degrib/degrib2.h" 42 : #include "degrib/degrib/inventory.h" 43 : #include "degrib/degrib/meta.h" 44 : #include "degrib/degrib/myerror.h" 45 : #include "degrib/degrib/type.h" 46 : #include "gdal.h" 47 : #include "gdal_frmts.h" 48 : #include "gdal_pam.h" 49 : #include "gdal_priv.h" 50 : #include "ogr_spatialref.h" 51 : 52 : /************************************************************************/ 53 : /* ==================================================================== */ 54 : /* GRIBDataset */ 55 : /* ==================================================================== */ 56 : /************************************************************************/ 57 : 58 : class GRIBArray; 59 : class GRIBRasterBand; 60 : 61 : namespace gdal 62 : { 63 : namespace grib 64 : { 65 : class InventoryWrapper; 66 : } 67 : } // namespace gdal 68 : 69 : class GRIBDataset final : public GDALPamDataset 70 : { 71 : friend class GRIBArray; 72 : friend class GRIBRasterBand; 73 : 74 : public: 75 : GRIBDataset(); 76 : ~GRIBDataset(); 77 : 78 : static GDALDataset *Open(GDALOpenInfo *); 79 : static int Identify(GDALOpenInfo *); 80 : static GDALDataset *CreateCopy(const char *pszFilename, 81 : GDALDataset *poSrcDS, int bStrict, 82 : char **papszOptions, 83 : GDALProgressFunc pfnProgress, 84 : void *pProgressData); 85 : 86 : CPLErr GetGeoTransform(double *padfTransform) override; 87 : 88 74 : const OGRSpatialReference *GetSpatialRef() const override 89 : { 90 74 : return m_poSRS.get(); 91 : } 92 : 93 23 : std::shared_ptr<GDALGroup> GetRootGroup() const override 94 : { 95 23 : return m_poRootGroup; 96 : } 97 : 98 : private: 99 : void SetGribMetaData(grib_MetaData *meta); 100 : static GDALDataset *OpenMultiDim(GDALOpenInfo *); 101 : std::unique_ptr<gdal::grib::InventoryWrapper> Inventory(GDALOpenInfo *); 102 : 103 : VSILFILE *fp; 104 : // Calculate and store once as GetGeoTransform may be called multiple times. 105 : double adfGeoTransform[6]; 106 : 107 : GIntBig nCachedBytes; 108 : GIntBig nCachedBytesThreshold; 109 : int bCacheOnlyOneBand; 110 : 111 : // Split&Swap: transparent rewrap around the prime meridian instead of the 112 : // antimeridian rows after nSplitAndSwapColumn are placed at the beginning 113 : // while rows before are placed at the end 114 : int nSplitAndSwapColumn; 115 : 116 : GRIBRasterBand *poLastUsedBand; 117 : std::shared_ptr<GDALGroup> m_poRootGroup{}; 118 : std::shared_ptr<OGRSpatialReference> m_poSRS{}; 119 : std::unique_ptr<OGRSpatialReference> m_poLL{}; 120 : std::unique_ptr<OGRCoordinateTransformation> m_poCT{}; 121 : 122 : #ifdef BUILD_APPS 123 : bool m_bSideCarIdxUsed = false; 124 : bool m_bWarnedGdalinfoNomd = false; 125 : time_t m_nFirstMetadataQueriedTimeStamp = 0; 126 : bool m_bWarnedGdalinfoNonodata = false; 127 : time_t m_nFirstNodataQueriedTimeStamp = 0; 128 : #endif 129 : }; 130 : 131 : /************************************************************************/ 132 : /* ==================================================================== */ 133 : /* GRIBRasterBand */ 134 : /* ==================================================================== */ 135 : /************************************************************************/ 136 : 137 : class GRIBRasterBand final : public GDALPamRasterBand 138 : { 139 : friend class GRIBArray; 140 : friend class GRIBDataset; 141 : 142 : public: 143 : GRIBRasterBand(GRIBDataset *, int, inventoryType *); 144 : virtual ~GRIBRasterBand(); 145 : virtual CPLErr IReadBlock(int, int, void *) override; 146 : virtual const char *GetDescription() const override; 147 : 148 : virtual double GetNoDataValue(int *pbSuccess = nullptr) override; 149 : virtual char **GetMetadata(const char *pszDomain = "") override; 150 : virtual const char *GetMetadataItem(const char *pszName, 151 : const char *pszDomain = "") override; 152 : 153 : void FindPDSTemplateGRIB2(); 154 : 155 : void UncacheData(); 156 : 157 : static void ReadGribData(VSILFILE *, vsi_l_offset, int, double **, 158 : grib_MetaData **); 159 : 160 : private: 161 : CPLErr LoadData(); 162 : void FindNoDataGrib2(bool bSeekToStart = true); 163 : void FindMetaData(); 164 : // Heuristic search for the start of the message 165 : static vsi_l_offset FindTrueStart(VSILFILE *, vsi_l_offset); 166 : 167 : vsi_l_offset start; 168 : int subgNum; 169 : char *longFstLevel; 170 : 171 : double *m_Grib_Data; 172 : grib_MetaData *m_Grib_MetaData; 173 : 174 : int nGribDataXSize; 175 : int nGribDataYSize; 176 : int m_nGribVersion; 177 : 178 : bool m_bHasLookedForNoData; 179 : double m_dfNoData; 180 : bool m_bHasNoData; 181 : 182 : int m_nDisciplineCode = -1; 183 : std::string m_osDisciplineName{}; 184 : int m_nCenter = -1; 185 : std::string m_osCenterName{}; 186 : int m_nSubCenter = -1; 187 : std::string m_osSubCenterName{}; 188 : std::string m_osSignRefTimeName{}; 189 : std::string m_osRefTime{}; 190 : std::string m_osProductionStatus{}; 191 : std::string m_osType{}; 192 : int m_nPDTN = -1; 193 : std::vector<GUInt32> m_anPDSTemplateAssembledValues{}; 194 : bool bLoadedPDS = false; 195 : bool bLoadedMetadata = false; 196 : }; 197 : 198 : namespace gdal 199 : { 200 : namespace grib 201 : { 202 : 203 : // Thin layer to manage allocation and deallocation. 204 : class InventoryWrapper 205 : { 206 : public: 207 314 : InventoryWrapper() 208 314 : { 209 314 : } 210 : 211 314 : virtual ~InventoryWrapper() 212 314 : { 213 314 : } 214 : 215 : // Modifying the contents pointed to by the return is allowed. 216 466 : inventoryType *get(int i) const 217 : { 218 466 : if (i < 0 || i >= static_cast<int>(inv_len_)) 219 0 : return nullptr; 220 466 : return inv_ + i; 221 : } 222 : 223 758 : uInt4 length() const 224 : { 225 758 : return inv_len_; 226 : } 227 : 228 : size_t num_messages() const 229 : { 230 : return num_messages_; 231 : } 232 : 233 320 : int result() const 234 : { 235 320 : return result_; 236 : } 237 : 238 : protected: 239 : inventoryType *inv_ = nullptr; 240 : uInt4 inv_len_ = 0; 241 : int num_messages_ = 0; 242 : int result_ = 0; 243 : }; 244 : 245 : } // namespace grib 246 : } // namespace gdal 247 : 248 : const char *const apszJ2KDrivers[] = {"JP2KAK", "JP2OPENJPEG", "JPEG2000", 249 : "JP2ECW"}; 250 : 251 : #endif // GRIBDATASET_H