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