1 /****************************************************************************** 2 * $Id: gribdataset.h d23b5a0d22b88657e4fc31f2513701842f0b0585 2019-08-11 03:09:59 +0200 Even Rouault $ 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 * 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 */ 32 33 #ifndef GRIBDATASET_H 34 #define GRIBDATASET_H 35 36 #include "cpl_port.h" 37 38 #include <cerrno> 39 #include <cmath> 40 #include <cstddef> 41 #include <cstdio> 42 #include <cstdlib> 43 #include <cstring> 44 #if HAVE_FCNTL_H 45 # include <fcntl.h> 46 #endif 47 48 #include <algorithm> 49 #include <memory> 50 #include <string> 51 52 #include "cpl_conv.h" 53 #include "cpl_error.h" 54 #include "cpl_multiproc.h" 55 #include "cpl_string.h" 56 #include "cpl_vsi.h" 57 #include "degrib/degrib/degrib2.h" 58 #include "degrib/degrib/inventory.h" 59 #include "degrib/degrib/meta.h" 60 #include "degrib/degrib/myerror.h" 61 #include "degrib/degrib/type.h" 62 #include "gdal.h" 63 #include "gdal_frmts.h" 64 #include "gdal_pam.h" 65 #include "gdal_priv.h" 66 #include "ogr_spatialref.h" 67 68 /************************************************************************/ 69 /* ==================================================================== */ 70 /* GRIBDataset */ 71 /* ==================================================================== */ 72 /************************************************************************/ 73 74 class GRIBArray; 75 class GRIBRasterBand; 76 77 class GRIBDataset final: public GDALPamDataset 78 { 79 friend class GRIBArray; 80 friend class GRIBRasterBand; 81 82 public: 83 GRIBDataset(); 84 ~GRIBDataset(); 85 86 static GDALDataset *Open( GDALOpenInfo * ); 87 static int Identify( GDALOpenInfo * ); 88 static GDALDataset *CreateCopy( const char * pszFilename, 89 GDALDataset *poSrcDS, 90 int bStrict, char ** papszOptions, 91 GDALProgressFunc pfnProgress, 92 void * pProgressData ); 93 94 CPLErr GetGeoTransform( double *padfTransform ) override; GetSpatialRef()95 const OGRSpatialReference* GetSpatialRef() const override { 96 return m_poSRS.get(); 97 } 98 GetRootGroup()99 std::shared_ptr<GDALGroup> GetRootGroup() const override { return m_poRootGroup; } 100 101 private: 102 void SetGribMetaData(grib_MetaData *meta); 103 static GDALDataset *OpenMultiDim( GDALOpenInfo * ); 104 105 VSILFILE *fp; 106 // Calculate and store once as GetGeoTransform may be called multiple times. 107 double adfGeoTransform[6]; 108 109 GIntBig nCachedBytes; 110 GIntBig nCachedBytesThreshold; 111 int bCacheOnlyOneBand; 112 GRIBRasterBand *poLastUsedBand; 113 std::shared_ptr<GDALGroup> m_poRootGroup{}; 114 std::shared_ptr<OGRSpatialReference> m_poSRS{}; 115 std::unique_ptr<OGRSpatialReference> m_poLL{}; 116 std::unique_ptr<OGRCoordinateTransformation> m_poCT{}; 117 }; 118 119 /************************************************************************/ 120 /* ==================================================================== */ 121 /* GRIBRasterBand */ 122 /* ==================================================================== */ 123 /************************************************************************/ 124 125 class GRIBRasterBand final: public GDALPamRasterBand 126 { 127 friend class GRIBArray; 128 friend class GRIBDataset; 129 130 public: 131 GRIBRasterBand( GRIBDataset *, int, inventoryType * ); 132 virtual ~GRIBRasterBand(); 133 virtual CPLErr IReadBlock( int, int, void * ) override; 134 virtual const char *GetDescription() const override; 135 136 virtual double GetNoDataValue( int *pbSuccess = nullptr ) override; 137 138 void FindPDSTemplate(); 139 140 void UncacheData(); 141 142 static void ReadGribData( VSILFILE *, vsi_l_offset, int, double **, 143 grib_MetaData ** ); 144 private: 145 CPLErr LoadData(); 146 void FindNoDataGrib2(bool bSeekToStart = true); 147 148 vsi_l_offset start; 149 int subgNum; 150 char *longFstLevel; 151 152 double *m_Grib_Data; 153 grib_MetaData *m_Grib_MetaData; 154 155 int nGribDataXSize; 156 int nGribDataYSize; 157 int m_nGribVersion; 158 159 bool m_bHasLookedForNoData; 160 double m_dfNoData; 161 bool m_bHasNoData; 162 163 int m_nDisciplineCode = -1; 164 std::string m_osDisciplineName{}; 165 int m_nCenter = -1; 166 std::string m_osCenterName{}; 167 int m_nSubCenter = -1; 168 std::string m_osSubCenterName{}; 169 std::string m_osSignRefTimeName{}; 170 std::string m_osRefTime{}; 171 std::string m_osProductionStatus{}; 172 std::string m_osType{}; 173 int m_nPDTN = -1; 174 std::vector<GUInt32> m_anPDSTemplateAssembledValues{}; 175 }; 176 177 namespace gdal { 178 namespace grib { 179 180 // Thin layer to manage allocation and deallocation. 181 class InventoryWrapper { 182 public: 183 InventoryWrapper(VSILFILE * fp)184 explicit InventoryWrapper(VSILFILE * fp) 185 : inv_(nullptr), inv_len_(0), num_messages_(0), result_(0) { 186 result_ = GRIB2Inventory(fp, &inv_, &inv_len_, 187 0 /* all messages */, &num_messages_); 188 } 189 ~InventoryWrapper()190 ~InventoryWrapper() { 191 if (inv_ == nullptr) return; 192 for (uInt4 i = 0; i < inv_len_; i++) { 193 GRIB2InventoryFree(inv_ + i); 194 } 195 free(inv_); 196 } 197 198 // Modifying the contents pointed to by the return is allowed. get(int i)199 inventoryType * get(int i) const { 200 if (i < 0 || i >= static_cast<int>(inv_len_)) return nullptr; 201 return inv_ + i; 202 } 203 length()204 uInt4 length() const { return inv_len_; } num_messages()205 size_t num_messages() const { return num_messages_; } result()206 int result() const { return result_; } 207 208 private: 209 inventoryType *inv_; 210 uInt4 inv_len_; 211 int num_messages_; 212 int result_; 213 }; 214 215 } // namespace grib 216 } // namespace gdal 217 218 const char* const apszJ2KDrivers[] = 219 { "JP2KAK", "JP2OPENJPEG", "JPEG2000", "JP2ECW" }; 220 221 #endif // GRIBDATASET_H 222