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
|