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