LCOV - code coverage report
Current view: top level - frmts/rmf - rmfdataset.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 1 1 100.0 %
Date: 2025-05-31 00:00:17 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  Raster Matrix Format
       4             :  * Purpose:  Private class declarations for the RMF classes used to read/write
       5             :  *           GIS "Integratsia" raster files (also known as "Panorama" GIS).
       6             :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2007, Andrey Kiselev <dron@ak4719.spb.edu>
      10             :  * Copyright (c) 2023, NextGIS <info@nextgis.com>
      11             :  *
      12             :  * SPDX-License-Identifier: MIT
      13             :  ****************************************************************************/
      14             : 
      15             : #ifndef RMFDATASET_H_INCLUDED
      16             : #define RMFDATASET_H_INCLUDED
      17             : 
      18             : #include <array>
      19             : #include <list>
      20             : #include "gdal_priv.h"
      21             : #include "cpl_worker_thread_pool.h"
      22             : 
      23             : #define RMF_HEADER_SIZE 320
      24             : #define RMF_EXT_HEADER_SIZE 320
      25             : #define RMF_MIN_EXT_HEADER_SIZE (36 + 4)
      26             : #define RMF_MAX_EXT_HEADER_SIZE 1000000
      27             : 
      28             : #define RMF_COMPRESSION_NONE 0
      29             : #define RMF_COMPRESSION_LZW 1
      30             : #define RMF_COMPRESSION_JPEG 2
      31             : #define RMF_COMPRESSION_DEM 32
      32             : 
      33             : enum RMFType
      34             : {
      35             :     RMFT_RSW,  // Raster map
      36             :     RMFT_MTW   // Digital elevation model
      37             : };
      38             : 
      39             : enum RMFVersion
      40             : {
      41             :     RMF_VERSION = 0x0200,      // Version for "small" files less than 4 Gb
      42             :     RMF_VERSION_HUGE = 0x0201  // Version for "huge" files less than 4 Tb. Since
      43             :                                // GIS Panorama v11
      44             : };
      45             : 
      46             : class RMFDataset;
      47             : 
      48             : #define RMF_HUGE_OFFSET_FACTOR 256
      49             : 
      50             : constexpr int RMF_JPEG_BAND_COUNT = 3;
      51             : constexpr int RMF_DEM_BAND_COUNT = 1;
      52             : 
      53             : /************************************************************************/
      54             : /*                            RMFHeader                                 */
      55             : /************************************************************************/
      56             : 
      57             : typedef struct
      58             : {
      59             : #define RMF_SIGNATURE_SIZE 4
      60             :     char bySignature[RMF_SIGNATURE_SIZE];  // "RSW" for raster
      61             :                                            // map or "MTW" for DEM
      62             :     GUInt32 iVersion;
      63             :     GUInt32 nSize;       // File size in bytes
      64             :     GUInt32 nOvrOffset;  // Offset to overview
      65             :     GUInt32 iUserID;
      66             : #define RMF_NAME_SIZE 32
      67             :     GByte byName[RMF_NAME_SIZE];
      68             :     GUInt32 nBitDepth;  // Number of bits per pixel
      69             :     GUInt32 nHeight;    // Image length
      70             :     GUInt32 nWidth;     // Image width
      71             :     GUInt32 nXTiles;    // Number of tiles in line
      72             :     GUInt32 nYTiles;    // Number of tiles in column
      73             :     GUInt32 nTileHeight;
      74             :     GUInt32 nTileWidth;
      75             :     GUInt32 nLastTileHeight;
      76             :     GUInt32 nLastTileWidth;
      77             :     GUInt32 nROIOffset;
      78             :     GUInt32 nROISize;
      79             :     GUInt32 nClrTblOffset;   // Position and size
      80             :     GUInt32 nClrTblSize;     // of the colour table
      81             :     GUInt32 nTileTblOffset;  // Position and size of the
      82             :     GUInt32 nTileTblSize;    // tile offsets/sizes table
      83             :     GInt32 iMapType;
      84             :     GInt32 iProjection;
      85             :     GInt32 iEPSGCode;
      86             :     double dfScale;
      87             :     double dfResolution;
      88             :     double dfPixelSize;
      89             :     double dfLLX;
      90             :     double dfLLY;
      91             :     double dfStdP1;
      92             :     double dfStdP2;
      93             :     double dfCenterLong;
      94             :     double dfCenterLat;
      95             :     GByte iCompression;
      96             :     GByte iMaskType;
      97             :     GByte iMaskStep;
      98             :     GByte iFrameFlag;
      99             :     GUInt32 nFlagsTblOffset;
     100             :     GUInt32 nFlagsTblSize;
     101             :     GUInt32 nFileSize0;
     102             :     GUInt32 nFileSize1;
     103             :     GByte iUnknown;
     104             :     GByte iGeorefFlag;
     105             :     GByte iInverse;
     106             :     GByte iJpegQuality;
     107             : #define RMF_INVISIBLE_COLORS_SIZE 32
     108             :     GByte abyInvisibleColors[RMF_INVISIBLE_COLORS_SIZE];
     109             :     double adfElevMinMax[2];
     110             :     double dfNoData;
     111             :     GUInt32 iElevationUnit;
     112             :     GByte iElevationType;
     113             :     GUInt32 nExtHdrOffset;
     114             :     GUInt32 nExtHdrSize;
     115             : } RMFHeader;
     116             : 
     117             : /************************************************************************/
     118             : /*                            RMFExtHeader                              */
     119             : /************************************************************************/
     120             : 
     121             : typedef struct
     122             : {
     123             :     GInt32 nEllipsoid;
     124             :     GInt32 nVertDatum;
     125             :     GInt32 nDatum;
     126             :     GInt32 nZone;
     127             : } RMFExtHeader;
     128             : 
     129             : /************************************************************************/
     130             : /*                              RSWFrame                                */
     131             : /************************************************************************/
     132             : 
     133             : typedef struct
     134             : {
     135             :     GInt32 nType;
     136             :     GInt32 nSize;
     137             :     GInt32 nSubCount;
     138             :     GInt32 nCoordsSize;
     139             : } RSWFrame;
     140             : 
     141             : typedef struct
     142             : {
     143             :     GInt32 nX, nY;
     144             : } RSWFrameCoord;
     145             : 
     146             : /************************************************************************/
     147             : /*                            RMFCompressionJob                         */
     148             : /************************************************************************/
     149             : 
     150             : struct RMFCompressionJob
     151             : {
     152             :     RMFDataset *poDS = nullptr;
     153             :     CPLErr eResult = CE_None;
     154             :     int nBlockXOff = -1;
     155             :     int nBlockYOff = -1;
     156             :     GByte *pabyUncompressedData = nullptr;
     157             :     size_t nUncompressedBytes = 0;
     158             :     GByte *pabyCompressedData = nullptr;
     159             :     size_t nCompressedBytes = 0;
     160             :     GUInt32 nXSize = 0;
     161             :     GUInt32 nYSize = 0;
     162             : 
     163          67 :     RMFCompressionJob() = default;
     164             :     RMFCompressionJob(const RMFCompressionJob &) = delete;
     165             :     RMFCompressionJob &operator=(const RMFCompressionJob &) = delete;
     166             :     RMFCompressionJob(RMFCompressionJob &&) = default;
     167             :     RMFCompressionJob &operator=(RMFCompressionJob &&) = default;
     168             : };
     169             : 
     170             : /************************************************************************/
     171             : /*                            RMFCompressData                           */
     172             : /************************************************************************/
     173             : 
     174             : struct RMFCompressData
     175             : {
     176             :     CPLWorkerThreadPool oThreadPool{};
     177             :     std::vector<RMFCompressionJob> asJobs{};
     178             :     std::list<RMFCompressionJob *> asReadyJobs{};
     179             :     GByte *pabyBuffers = nullptr;
     180             :     CPLMutex *hReadyJobMutex = nullptr;
     181             :     CPLMutex *hWriteTileMutex = nullptr;
     182             : 
     183             :     RMFCompressData(const RMFCompressData &) = delete;
     184             :     RMFCompressData &operator=(const RMFCompressData &) = delete;
     185             : 
     186             :     RMFCompressData();
     187             :     ~RMFCompressData();
     188             : };
     189             : 
     190             : /************************************************************************/
     191             : /*                            RMFTileData                               */
     192             : /************************************************************************/
     193             : 
     194             : struct RMFTileData
     195             : {
     196             :     std::vector<GByte> oData{};
     197             :     int nBandsWritten = 0;
     198             : };
     199             : 
     200             : /************************************************************************/
     201             : /*                              RMFDataset                              */
     202             : /************************************************************************/
     203             : 
     204             : class RMFDataset final : public GDALDataset
     205             : {
     206             :     friend class RMFRasterBand;
     207             : 
     208             :   private:
     209             :     RMFHeader sHeader{};
     210             :     RMFExtHeader sExtHeader{};
     211             :     RMFType eRMFType = RMFT_RSW;
     212             :     GUInt32 nXTiles = 0;
     213             :     GUInt32 nYTiles = 0;
     214             :     GUInt32 *paiTiles = nullptr;
     215             :     GByte *pabyDecompressBuffer = nullptr;
     216             :     GByte *pabyCurrentTile = nullptr;
     217             :     bool bCurrentTileIsNull = false;
     218             :     int nCurrentTileXOff = -1;
     219             :     int nCurrentTileYOff = -1;
     220             :     GUInt32 nCurrentTileBytes = 0;
     221             :     GUInt32 nColorTableSize = 0;
     222             :     GByte *pabyColorTable = nullptr;
     223             :     GDALColorTable *poColorTable = nullptr;
     224             :     std::array<double, 6> adfGeoTransform = {0, 1, 0, 0, 0, 1};
     225             :     OGRSpatialReference m_oSRS{};
     226             : 
     227             :     char *pszUnitType = nullptr;
     228             : 
     229             :     bool bBigEndian = false;
     230             :     bool bHeaderDirty = false;
     231             : 
     232             :     VSILFILE *fp = nullptr;
     233             : 
     234             :     std::shared_ptr<RMFCompressData> poCompressData{};
     235             :     std::map<GUInt32, RMFTileData> oUnfinishedTiles{};
     236             : 
     237             :     CPLErr WriteHeader();
     238             :     static size_t LZWDecompress(const GByte *, GUInt32, GByte *, GUInt32,
     239             :                                 GUInt32, GUInt32);
     240             :     static size_t LZWCompress(const GByte *, GUInt32, GByte *, GUInt32, GUInt32,
     241             :                               GUInt32, const RMFDataset *);
     242             : #ifdef HAVE_LIBJPEG
     243             :     static size_t JPEGDecompress(const GByte *, GUInt32, GByte *, GUInt32,
     244             :                                  GUInt32, GUInt32);
     245             :     static size_t JPEGCompress(const GByte *, GUInt32, GByte *, GUInt32,
     246             :                                GUInt32, GUInt32, const RMFDataset *);
     247             : #endif  // HAVE_LIBJPEG
     248             :     static size_t DEMDecompress(const GByte *, GUInt32, GByte *, GUInt32,
     249             :                                 GUInt32, GUInt32);
     250             :     static size_t DEMCompress(const GByte *, GUInt32, GByte *, GUInt32, GUInt32,
     251             :                               GUInt32, const RMFDataset *);
     252             : 
     253             :     /*!
     254             :         Tile decompress callback
     255             :         pabyIn - input compressed data
     256             :         nSizeIn - input compressed data size (in bytes)
     257             :         pabyOut - pointer to uncompressed data
     258             :         nSizeOut - maximum uncompressed data size
     259             :         nTileSx - width of uncompressed tile (in pixels)
     260             :         nTileSy - height of uncompressed tile (in pixels)
     261             : 
     262             :         Returns: actual uncompressed data size or 0 on error (if nSizeOut is
     263             :                  small returns 0 too).
     264             :     */
     265             :     size_t (*Decompress)(const GByte *pabyIn, GUInt32 nSizeIn, GByte *pabyOut,
     266             :                          GUInt32 nSizeOut, GUInt32 nTileSx,
     267             :                          GUInt32 nTileSy) = nullptr;
     268             : 
     269             :     /*!
     270             :         Tile compress callback
     271             :         pabyIn - input uncompressed data
     272             :         nSizeIn - input uncompressed data size (in bytes)
     273             :         pabyOut - pointer to compressed data
     274             :         nSizeOut - maximum compressed data size
     275             :         nTileSx - width of uncompressed tile (in pixels)
     276             :         nTileSy - height of uncompressed tile (in pixels)
     277             :         poDS - pointer to parent dataset
     278             : 
     279             :         Returns: actual compressed data size or 0 on error (if nSizeOut is
     280             :                  small returns 0 too).
     281             :     */
     282             :     size_t (*Compress)(const GByte *pabyIn, GUInt32 nSizeIn, GByte *pabyOut,
     283             :                        GUInt32 nSizeOut, GUInt32 nTileSx, GUInt32 nTileSy,
     284             :                        const RMFDataset *poDS) = nullptr;
     285             : 
     286             :     std::vector<RMFDataset *> poOvrDatasets{};
     287             :     vsi_l_offset nHeaderOffset = 0;
     288             :     RMFDataset *poParentDS = nullptr;
     289             : 
     290             :     RMFDataset(const RMFDataset &) = delete;
     291             :     RMFDataset &operator=(const RMFDataset &) = delete;
     292             : 
     293             :   public:
     294             :     RMFDataset();
     295             :     virtual ~RMFDataset();
     296             : 
     297             :     static int Identify(GDALOpenInfo *poOpenInfo);
     298             :     static GDALDataset *Open(GDALOpenInfo *);
     299             :     static RMFDataset *Open(GDALOpenInfo *, RMFDataset *poParentDS,
     300             :                             vsi_l_offset nNextHeaderOffset);
     301             :     static GDALDataset *Create(const char *, int, int, int, GDALDataType,
     302             :                                char **);
     303             :     static GDALDataset *Create(const char *, int, int, int, GDALDataType,
     304             :                                char **, RMFDataset *poParentDS,
     305             :                                double dfOvFactor);
     306             :     virtual CPLErr FlushCache(bool bAtClosing) override;
     307             : 
     308             :     virtual CPLErr GetGeoTransform(double *padfTransform) override;
     309             :     virtual CPLErr SetGeoTransform(double *) override;
     310             :     const OGRSpatialReference *GetSpatialRef() const override;
     311             :     CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
     312             : 
     313             :     virtual CPLErr IBuildOverviews(const char *pszResampling, int nOverviews,
     314             :                                    const int *panOverviewList, int nBandsIn,
     315             :                                    const int *panBandList,
     316             :                                    GDALProgressFunc pfnProgress,
     317             :                                    void *pProgressData,
     318             :                                    CSLConstList papszOptions) override;
     319             :     virtual CPLErr IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     320             :                              int nXSize, int nYSize, void *pData, int nBufXSize,
     321             :                              int nBufYSize, GDALDataType eBufType,
     322             :                              int nBandCount, BANDMAP_TYPE panBandMap,
     323             :                              GSpacing nPixelSpace, GSpacing nLineSpace,
     324             :                              GSpacing nBandSpace,
     325             :                              GDALRasterIOExtraArg *psExtraArg) override;
     326             :     virtual CPLErr SetMetadataItem(const char *pszName, const char *pszValue,
     327             :                                    const char *pszDomain = "") override;
     328             :     virtual CPLErr SetMetadata(char **papszMetadata,
     329             :                                const char *pszDomain = "") override;
     330             :     // cppcheck-suppress functionStatic
     331             :     vsi_l_offset GetFileOffset(GUInt32 iRMFOffset) const;
     332             :     GUInt32 GetRMFOffset(vsi_l_offset iFileOffset,
     333             :                          vsi_l_offset *piNewFileOffset) const;
     334             :     RMFDataset *OpenOverview(RMFDataset *poParentDS, GDALOpenInfo *);
     335             :     vsi_l_offset GetLastOffset() const;
     336             :     CPLErr CleanOverviews();
     337             :     static GByte GetCompressionType(const char *pszCompressName);
     338             :     int SetupCompression(GDALDataType eType, const char *pszFilename);
     339             :     static void WriteTileJobFunc(void *pData);
     340             :     CPLErr InitCompressorData(char **papszParamList);
     341             :     CPLErr WriteTile(int nBlockXOff, int nBlockYOff, GByte *pabyData,
     342             :                      size_t nBytes, GUInt32 nRawXSize, GUInt32 nRawYSize);
     343             :     CPLErr WriteRawTile(int nBlockXOff, int nBlockYOff, GByte *pabyData,
     344             :                         size_t nBytes);
     345             :     CPLErr ReadTile(int nBlockXOff, int nBlockYOff, GByte *pabyData,
     346             :                     size_t nBytes, GUInt32 nRawXSize, GUInt32 nRawYSize,
     347             :                     bool &bNullTile);
     348             :     void SetupNBits();
     349             : };
     350             : 
     351             : /************************************************************************/
     352             : /*                            RMFRasterBand                             */
     353             : /************************************************************************/
     354             : 
     355             : class RMFRasterBand final : public GDALRasterBand
     356             : {
     357             :     friend class RMFDataset;
     358             : 
     359             :   private:
     360             :     GUInt32 nBlockSize = 0;
     361             :     GUInt32 nBlockBytes = 0;
     362             :     GUInt32 nLastTileWidth = 0;
     363             :     GUInt32 nLastTileHeight = 0;
     364             :     GUInt32 nDataSize = 0;
     365             : 
     366             :   public:
     367             :     RMFRasterBand(RMFDataset *, int, GDALDataType);
     368             :     virtual ~RMFRasterBand();
     369             : 
     370             :     virtual CPLErr IReadBlock(int, int, void *) override;
     371             :     virtual CPLErr IWriteBlock(int, int, void *) override;
     372             :     virtual GDALSuggestedBlockAccessPattern
     373             :     GetSuggestedBlockAccessPattern() const override;
     374             :     virtual double GetNoDataValue(int *pbSuccess = nullptr) override;
     375             :     virtual CPLErr SetNoDataValue(double dfNoData) override;
     376             :     virtual const char *GetUnitType() override;
     377             :     virtual GDALColorInterp GetColorInterpretation() override;
     378             :     virtual GDALColorTable *GetColorTable() override;
     379             :     virtual CPLErr SetUnitType(const char *) override;
     380             :     virtual CPLErr SetColorTable(GDALColorTable *) override;
     381             :     virtual int GetOverviewCount() override;
     382             :     virtual GDALRasterBand *GetOverview(int i) override;
     383             :     virtual CPLErr IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     384             :                              int nXSize, int nYSize, void *pData, int nBufXSize,
     385             :                              int nBufYSize, GDALDataType eBufType,
     386             :                              GSpacing nPixelSpace, GSpacing nLineSpace,
     387             :                              GDALRasterIOExtraArg *psExtraArg) override;
     388             : };
     389             : 
     390             : #endif

Generated by: LCOV version 1.14