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