1 /******************************************************************************
2 *
3 * Project: GDAL Core
4 * Purpose: A dataset and raster band classes that act as proxy for underlying
5 * GDALDataset* and GDALRasterBand*
6 * Author: Even Rouault <even dot rouault at spatialys.com>
7 *
8 ******************************************************************************
9 * Copyright (c) 2008-2014, Even Rouault <even dot rouault at spatialys.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ****************************************************************************/
29
30 #include "cpl_port.h"
31 #include "gdal_proxy.h"
32
33 #include <cstddef>
34
35 #include "cpl_error.h"
36 #include "cpl_progress.h"
37 #include "cpl_virtualmem.h"
38 #include "gdal.h"
39 #include "gdal_priv.h"
40
41 CPL_CVSID("$Id: gdalproxydataset.cpp 355b41831cd2685c85d1aabe5b95665a2c6e99b7 2019-06-19 17:07:04 +0200 Even Rouault $")
42
43 /*! @cond Doxygen_Suppress */
44 /* ******************************************************************** */
45 /* GDALProxyDataset */
46 /* ******************************************************************** */
47
48 #define D_PROXY_METHOD_WITH_RET(retType, retErrValue, methodName, \
49 argList, argParams) \
50 retType GDALProxyDataset::methodName argList \
51 { \
52 retType ret; \
53 GDALDataset* poUnderlyingDataset = RefUnderlyingDataset(); \
54 if (poUnderlyingDataset) \
55 { \
56 ret = poUnderlyingDataset->methodName argParams; \
57 UnrefUnderlyingDataset(poUnderlyingDataset); \
58 } \
59 else \
60 { \
61 ret = retErrValue; \
62 } \
63 return ret; \
64 }
65
IRasterIO(GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,GSpacing nPixelSpace,GSpacing nLineSpace,GSpacing nBandSpace,GDALRasterIOExtraArg * psExtraArg)66 CPLErr GDALProxyDataset::IRasterIO( GDALRWFlag eRWFlag,
67 int nXOff, int nYOff, int nXSize, int nYSize,
68 void * pData, int nBufXSize, int nBufYSize,
69 GDALDataType eBufType,
70 int nBandCount, int *panBandMap,
71 GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
72 GDALRasterIOExtraArg* psExtraArg)
73 {
74 CPLErr ret;
75 GDALDataset* poUnderlyingDataset = RefUnderlyingDataset();
76 if (poUnderlyingDataset)
77 {
78 /* -------------------------------------------------------------------- */
79 /* Do some validation of parameters. */
80 /* -------------------------------------------------------------------- */
81 if( nXOff + nXSize > poUnderlyingDataset->GetRasterXSize() ||
82 nYOff + nYSize > poUnderlyingDataset->GetRasterYSize() )
83 {
84 ReportError( CE_Failure, CPLE_IllegalArg,
85 "Access window out of range in RasterIO(). Requested\n"
86 "(%d,%d) of size %dx%d on raster of %dx%d.",
87 nXOff, nYOff, nXSize, nYSize,
88 poUnderlyingDataset->GetRasterXSize(),
89 poUnderlyingDataset->GetRasterYSize() );
90 ret = CE_Failure;
91 }
92 else if( panBandMap == nullptr && nBandCount > poUnderlyingDataset->GetRasterCount() )
93 {
94 ReportError( CE_Failure, CPLE_IllegalArg,
95 "%s: nBandCount cannot be greater than %d",
96 "IRasterIO", poUnderlyingDataset->GetRasterCount() );
97 ret = CE_Failure;
98 }
99 else
100 {
101 ret = CE_None;
102 for( int i = 0; i < nBandCount && ret == CE_None; ++i )
103 {
104 int iBand = (panBandMap != nullptr) ? panBandMap[i] : i + 1;
105 if( iBand < 1 || iBand > poUnderlyingDataset->GetRasterCount() )
106 {
107 ReportError( CE_Failure, CPLE_IllegalArg,
108 "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
109 "IRasterIO", i, iBand );
110 ret = CE_Failure;
111 }
112
113 if( ret == CE_None && poUnderlyingDataset->GetRasterBand( iBand ) == nullptr )
114 {
115 ReportError( CE_Failure, CPLE_IllegalArg,
116 "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
117 "IRasterIO", i, iBand );
118 ret = CE_Failure;
119 }
120 }
121 if( ret != CE_Failure )
122 {
123 ret = poUnderlyingDataset->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
124 pData, nBufXSize, nBufYSize,
125 eBufType, nBandCount, panBandMap,
126 nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
127 }
128 }
129 UnrefUnderlyingDataset(poUnderlyingDataset);
130 }
131 else
132 {
133 ret = CE_Failure;
134 }
135 return ret;
136 }
137
138 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, IBuildOverviews,
139 ( const char *pszResampling,
140 int nOverviews, int *panOverviewList,
141 int nListBands, int *panBandList,
142 GDALProgressFunc pfnProgress,
143 void * pProgressData ),
144 ( pszResampling, nOverviews, panOverviewList,
145 nListBands, panBandList, pfnProgress, pProgressData ))
146
FlushCache()147 void GDALProxyDataset::FlushCache()
148 {
149 GDALDataset* poUnderlyingDataset = RefUnderlyingDataset();
150 if (poUnderlyingDataset)
151 {
152 poUnderlyingDataset->FlushCache();
153 UnrefUnderlyingDataset(poUnderlyingDataset);
154 }
155 }
156
157 D_PROXY_METHOD_WITH_RET(char**, nullptr, GetMetadataDomainList, (), ())
158 D_PROXY_METHOD_WITH_RET(char**, nullptr, GetMetadata, (const char * pszDomain), (pszDomain))
159 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetMetadata,
160 (char ** papszMetadata, const char * pszDomain),
161 (papszMetadata, pszDomain))
162 D_PROXY_METHOD_WITH_RET(const char*, nullptr, GetMetadataItem,
163 (const char * pszName, const char * pszDomain),
164 (pszName, pszDomain))
165 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetMetadataItem,
166 (const char * pszName, const char * pszValue, const char * pszDomain),
167 (pszName, pszValue, pszDomain))
168
169 D_PROXY_METHOD_WITH_RET(const char *, nullptr, _GetProjectionRef, (), ())
170 D_PROXY_METHOD_WITH_RET(const OGRSpatialReference *, nullptr, GetSpatialRef, () const, ())
171 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, _SetProjection, (const char* pszProjection), (pszProjection))
172 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetSpatialRef, (const OGRSpatialReference* poSRS), (poSRS))
173 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, GetGeoTransform, (double* padfGeoTransform), (padfGeoTransform))
174 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetGeoTransform, (double* padfGeoTransform), (padfGeoTransform))
175
176 D_PROXY_METHOD_WITH_RET(void *, nullptr, GetInternalHandle, ( const char * arg1), (arg1))
177 D_PROXY_METHOD_WITH_RET(GDALDriver *, nullptr, GetDriver, (), ())
178 D_PROXY_METHOD_WITH_RET(char **, nullptr, GetFileList, (), ())
179 D_PROXY_METHOD_WITH_RET(int, 0, GetGCPCount, (), ())
180 D_PROXY_METHOD_WITH_RET(const char *, nullptr, _GetGCPProjection, (), ())
181 D_PROXY_METHOD_WITH_RET(const OGRSpatialReference *, nullptr, GetGCPSpatialRef, () const, ())
182 D_PROXY_METHOD_WITH_RET(const GDAL_GCP *, nullptr, GetGCPs, (), ())
183 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, _SetGCPs,
184 (int nGCPCount, const GDAL_GCP *pasGCPList,
185 const char *pszGCPProjection),
186 (nGCPCount, pasGCPList, pszGCPProjection))
187 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetGCPs,
188 (int nGCPCount, const GDAL_GCP *pasGCPList,
189 const OGRSpatialReference *poGCP_SRS),
190 (nGCPCount, pasGCPList, poGCP_SRS))
191 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, AdviseRead,
192 ( int nXOff, int nYOff, int nXSize, int nYSize,
193 int nBufXSize, int nBufYSize,
194 GDALDataType eDT,
195 int nBandCount, int *panBandList,
196 char **papszOptions ),
197 (nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, nBandCount, panBandList, papszOptions))
198 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlagsIn ), (nFlagsIn))
199
200 /************************************************************************/
201 /* UnrefUnderlyingDataset() */
202 /************************************************************************/
203
UnrefUnderlyingDataset(GDALDataset *) const204 void GDALProxyDataset::UnrefUnderlyingDataset(
205 GDALDataset* /* poUnderlyingDataset */) const
206 {}
207
208 /* ******************************************************************** */
209 /* GDALProxyRasterBand */
210 /* ******************************************************************** */
211
212 #define RB_PROXY_METHOD_WITH_RET(retType, retErrValue, methodName, argList, argParams) \
213 retType GDALProxyRasterBand::methodName argList \
214 { \
215 retType ret; \
216 GDALRasterBand* poSrcBand = RefUnderlyingRasterBand(); \
217 if (poSrcBand) \
218 { \
219 ret = poSrcBand->methodName argParams; \
220 UnrefUnderlyingRasterBand(poSrcBand); \
221 } \
222 else \
223 { \
224 ret = retErrValue; \
225 } \
226 return ret; \
227 }
228
229 #define RB_PROXY_METHOD_WITH_RET_WITH_INIT_BLOCK(retType, retErrValue, methodName, argList, argParams) \
230 retType GDALProxyRasterBand::methodName argList \
231 { \
232 retType ret; \
233 GDALRasterBand* poSrcBand = RefUnderlyingRasterBand(); \
234 if (poSrcBand) \
235 { \
236 if( !poSrcBand->InitBlockInfo() ) \
237 ret = CE_Failure; \
238 else \
239 { \
240 int nSrcBlockXSize, nSrcBlockYSize; \
241 poSrcBand->GetBlockSize(&nSrcBlockXSize, &nSrcBlockYSize); \
242 if( poSrcBand->GetRasterDataType() != GetRasterDataType() ) \
243 { \
244 CPLError(CE_Failure, CPLE_AppDefined, "Inconsistent datatype between proxy and source"); \
245 ret = CE_Failure; \
246 } \
247 else if( nSrcBlockXSize != nBlockXSize || nSrcBlockYSize != nBlockYSize) \
248 { \
249 CPLError(CE_Failure, CPLE_AppDefined, "Inconsistent block dimensions between proxy and source"); \
250 ret = CE_Failure; \
251 } \
252 else \
253 { \
254 ret = poSrcBand->methodName argParams; \
255 } \
256 } \
257 UnrefUnderlyingRasterBand(poSrcBand); \
258 } \
259 else \
260 { \
261 ret = retErrValue; \
262 } \
263 return ret; \
264 }
265
266 RB_PROXY_METHOD_WITH_RET_WITH_INIT_BLOCK(CPLErr, CE_Failure, IReadBlock,
267 ( int nXBlockOff, int nYBlockOff, void* pImage),
268 (nXBlockOff, nYBlockOff, pImage) )
269 RB_PROXY_METHOD_WITH_RET_WITH_INIT_BLOCK(CPLErr, CE_Failure, IWriteBlock,
270 ( int nXBlockOff, int nYBlockOff, void* pImage),
271 (nXBlockOff, nYBlockOff, pImage) )
272
IRasterIO(GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,void * pData,int nBufXSize,int nBufYSize,GDALDataType eBufType,GSpacing nPixelSpace,GSpacing nLineSpace,GDALRasterIOExtraArg * psExtraArg)273 CPLErr GDALProxyRasterBand::IRasterIO( GDALRWFlag eRWFlag,
274 int nXOff, int nYOff, int nXSize, int nYSize,
275 void * pData, int nBufXSize, int nBufYSize,
276 GDALDataType eBufType,
277 GSpacing nPixelSpace,
278 GSpacing nLineSpace,
279 GDALRasterIOExtraArg* psExtraArg )
280 {
281 CPLErr ret;
282 GDALRasterBand* poSrcBand = RefUnderlyingRasterBand();
283 if (poSrcBand)
284 {
285 /* -------------------------------------------------------------------- */
286 /* Do some validation of parameters. */
287 /* -------------------------------------------------------------------- */
288 if( nXOff + nXSize > poSrcBand->GetXSize() || nYOff + nYSize > poSrcBand->GetYSize() )
289 {
290 ReportError( CE_Failure, CPLE_IllegalArg,
291 "Access window out of range in RasterIO(). Requested\n"
292 "(%d,%d) of size %dx%d on raster of %dx%d.",
293 nXOff, nYOff, nXSize, nYSize, poSrcBand->GetXSize(), poSrcBand->GetYSize() );
294 ret = CE_Failure;
295 }
296 else
297 {
298 ret = poSrcBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
299 pData, nBufXSize, nBufYSize, eBufType,
300 nPixelSpace, nLineSpace, psExtraArg );
301 }
302 UnrefUnderlyingRasterBand(poSrcBand);
303 }
304 else
305 {
306 ret = CE_Failure;
307 }
308 return ret;
309 }
310
311 RB_PROXY_METHOD_WITH_RET(char**, nullptr, GetMetadataDomainList, (), ())
312 RB_PROXY_METHOD_WITH_RET(char**, nullptr, GetMetadata, (const char * pszDomain), (pszDomain))
313 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetMetadata,
314 (char ** papszMetadata, const char * pszDomain),
315 (papszMetadata, pszDomain))
316 RB_PROXY_METHOD_WITH_RET(const char*, nullptr, GetMetadataItem,
317 (const char * pszName, const char * pszDomain),
318 (pszName, pszDomain))
319 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetMetadataItem,
320 (const char * pszName, const char * pszValue, const char * pszDomain),
321 (pszName, pszValue, pszDomain))
322
323
FlushCache()324 CPLErr GDALProxyRasterBand::FlushCache()
325 {
326 // We need to make sure that all cached bocks at the proxy level are
327 // first flushed
328 CPLErr ret = GDALRasterBand::FlushCache();
329 if( ret == CE_None )
330 {
331 GDALRasterBand* poSrcBand = RefUnderlyingRasterBand();
332 if (poSrcBand)
333 {
334 ret = poSrcBand->FlushCache();
335 UnrefUnderlyingRasterBand(poSrcBand);
336 }
337 else
338 {
339 ret = CE_Failure;
340 }
341 }
342 return ret;
343 }
344
345 RB_PROXY_METHOD_WITH_RET(char**, nullptr, GetCategoryNames, (), ())
346 RB_PROXY_METHOD_WITH_RET(double, 0, GetNoDataValue, (int *pbSuccess), (pbSuccess))
347 RB_PROXY_METHOD_WITH_RET(double, 0, GetMinimum, (int *pbSuccess), (pbSuccess))
348 RB_PROXY_METHOD_WITH_RET(double, 0, GetMaximum, (int *pbSuccess), (pbSuccess))
349 RB_PROXY_METHOD_WITH_RET(double, 0, GetOffset, (int *pbSuccess), (pbSuccess))
350 RB_PROXY_METHOD_WITH_RET(double, 0, GetScale, (int *pbSuccess), (pbSuccess))
351 RB_PROXY_METHOD_WITH_RET(const char*, nullptr, GetUnitType, (), ())
352 RB_PROXY_METHOD_WITH_RET(GDALColorInterp, GCI_Undefined, GetColorInterpretation, (), ())
353 RB_PROXY_METHOD_WITH_RET(GDALColorTable*, nullptr, GetColorTable, (), ())
354 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, Fill,
355 (double dfRealValue, double dfImaginaryValue),
356 (dfRealValue, dfImaginaryValue))
357
358 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetCategoryNames, ( char ** arg ), (arg))
359 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetNoDataValue, ( double arg ), (arg))
360 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, DeleteNoDataValue, (), ())
361 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetColorTable, ( GDALColorTable *arg ), (arg))
362 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetColorInterpretation,
363 ( GDALColorInterp arg ), (arg))
364 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetOffset, ( double arg ), (arg))
365 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetScale, ( double arg ), (arg))
366 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetUnitType, ( const char * arg ), (arg))
367
368 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, GetStatistics,
369 ( int bApproxOK, int bForce,
370 double *pdfMin, double *pdfMax,
371 double *pdfMean, double *padfStdDev ),
372 (bApproxOK, bForce, pdfMin, pdfMax, pdfMean, padfStdDev))
373 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, ComputeStatistics,
374 ( int bApproxOK,
375 double *pdfMin, double *pdfMax,
376 double *pdfMean, double *pdfStdDev,
377 GDALProgressFunc pfn, void *pProgressData ),
378 ( bApproxOK, pdfMin, pdfMax, pdfMean, pdfStdDev, pfn, pProgressData))
379 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetStatistics,
380 ( double dfMin, double dfMax,
381 double dfMean, double dfStdDev ),
382 (dfMin, dfMax, dfMean, dfStdDev))
383 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, ComputeRasterMinMax,
384 ( int arg1, double* arg2 ), (arg1, arg2))
385
386 RB_PROXY_METHOD_WITH_RET(int, 0, HasArbitraryOverviews, (), ())
387 RB_PROXY_METHOD_WITH_RET(int, 0, GetOverviewCount, (), ())
388 RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, nullptr, GetOverview, (int arg1), (arg1))
389 RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, nullptr, GetRasterSampleOverview,
390 (GUIntBig arg1), (arg1))
391
392 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, BuildOverviews,
393 (const char * arg1, int arg2, int *arg3,
394 GDALProgressFunc arg4, void * arg5),
395 (arg1, arg2, arg3, arg4, arg5))
396
397 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, AdviseRead,
398 ( int nXOff, int nYOff, int nXSize, int nYSize,
399 int nBufXSize, int nBufYSize,
400 GDALDataType eDT, char **papszOptions ),
401 (nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT, papszOptions))
402
403 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, GetHistogram,
404 ( double dfMin, double dfMax,
405 int nBuckets, GUIntBig * panHistogram,
406 int bIncludeOutOfRange, int bApproxOK,
407 GDALProgressFunc pfn, void *pProgressData ),
408 (dfMin, dfMax, nBuckets, panHistogram, bIncludeOutOfRange,
409 bApproxOK, pfn, pProgressData))
410
411 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, GetDefaultHistogram,
412 (double *pdfMin, double *pdfMax,
413 int *pnBuckets, GUIntBig ** ppanHistogram,
414 int bForce,
415 GDALProgressFunc pfn, void *pProgressData ),
416 (pdfMin, pdfMax, pnBuckets, ppanHistogram, bForce,
417 pfn, pProgressData))
418
419 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetDefaultHistogram,
420 ( double dfMin, double dfMax,
421 int nBuckets, GUIntBig * panHistogram ),
422 (dfMin, dfMax, nBuckets, panHistogram))
423
424 RB_PROXY_METHOD_WITH_RET(GDALRasterAttributeTable *, nullptr,
425 GetDefaultRAT, (), ())
426 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, SetDefaultRAT,
427 ( const GDALRasterAttributeTable * arg1), (arg1))
428
429 RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, nullptr, GetMaskBand, (), ())
430 RB_PROXY_METHOD_WITH_RET(int, 0, GetMaskFlags, (), ())
431 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlagsIn ), (nFlagsIn))
432
433 RB_PROXY_METHOD_WITH_RET(CPLVirtualMem*, nullptr, GetVirtualMemAuto,
434 ( GDALRWFlag eRWFlag, int *pnPixelSpace, GIntBig *pnLineSpace, char **papszOptions ),
435 (eRWFlag, pnPixelSpace, pnLineSpace, papszOptions) )
436
437 /************************************************************************/
438 /* UnrefUnderlyingRasterBand() */
439 /************************************************************************/
440
UnrefUnderlyingRasterBand(GDALRasterBand *)441 void GDALProxyRasterBand::UnrefUnderlyingRasterBand(
442 GDALRasterBand* /* poUnderlyingRasterBand */ )
443 {}
444
445 /*! @endcond */
446