/****************************************************************************** * $Id$ * * Project: GDAL High Performance Warper * Purpose: Prototypes, and definitions for warping related work. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2003, Frank Warmerdam * Copyright (c) 2009-2012, Even Rouault * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef GDALWARPER_H_INCLUDED #define GDALWARPER_H_INCLUDED /** * \file gdalwarper.h * * GDAL warper related entry points and definitions. Eventually it is * expected that this file will be mostly private to the implementation, * and the public C entry points will be available in gdal_alg.h. */ #include "gdal_alg.h" #include "cpl_minixml.h" #include "cpl_multiproc.h" CPL_C_START /* Note: values are selected to be consistent with GDALRIOResampleAlg of gcore/gdal.h */ /*! Warp Resampling Algorithm */ typedef enum { /*! Nearest neighbour (select on one input pixel) */ GRA_NearestNeighbour=0, /*! Bilinear (2x2 kernel) */ GRA_Bilinear=1, /*! Cubic Convolution Approximation (4x4 kernel) */ GRA_Cubic=2, /*! Cubic B-Spline Approximation (4x4 kernel) */ GRA_CubicSpline=3, /*! Lanczos windowed sinc interpolation (6x6 kernel) */ GRA_Lanczos=4, /*! Average (computes the weighted average of all non-NODATA contributing pixels) */ GRA_Average=5, /*! Mode (selects the value which appears most often of all the sampled points) */ GRA_Mode=6, /* GRA_Gauss=7 reserved. */ /*! Max (selects maximum of all non-NODATA contributing pixels) */ GRA_Max=8, /*! Min (selects minimum of all non-NODATA contributing pixels) */ GRA_Min=9, /*! Med (selects median of all non-NODATA contributing pixels) */ GRA_Med=10, /*! Q1 (selects first quartile of all non-NODATA contributing pixels) */ GRA_Q1=11, /*! Q3 (selects third quartile of all non-NODATA contributing pixels) */ GRA_Q3=12, /*! Sum (weighed sum of all non-NODATA contributing pixels). Added in GDAL 3.1 */ GRA_Sum=13, /*! RMS (weighted root mean square (quadratic mean) of all non-NODATA contributing pixels) */ GRA_RMS=14, /*! @cond Doxygen_Suppress */ GRA_LAST_VALUE=GRA_RMS /*! @endcond */ } GDALResampleAlg; /*! GWKAverageOrMode Algorithm */ typedef enum { /*! Average */ GWKAOM_Average=1, /*! Mode */ GWKAOM_Fmode=2, /*! Mode of GDT_Byte, GDT_UInt16, or GDT_Int16 */ GWKAOM_Imode=3, /*! Maximum */ GWKAOM_Max=4, /*! Minimum */ GWKAOM_Min=5, /*! Quantile */ GWKAOM_Quant=6, /*! Sum */ GWKAOM_Sum=7, /*! RMS */ GWKAOM_RMS=8 } GWKAverageOrModeAlg; /*! @cond Doxygen_Suppress */ typedef int (*GDALMaskFunc)( void *pMaskFuncArg, int nBandCount, GDALDataType eType, int nXOff, int nYOff, int nXSize, int nYSize, GByte **papabyImageData, int bMaskIsFloat, void *pMask ); CPLErr CPL_DLL GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType, int nXOff, int nYOff, int nXSize, int nYSize, GByte **papabyImageData, int bMaskIsFloat, void *pValidityMask, int* pbOutAllValid ); CPLErr CPL_DLL GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType, int nXOff, int nYOff, int nXSize, int nYSize, GByte ** /*ppImageData */, int bMaskIsFloat, void *pValidityMask ); CPLErr CPL_DLL GDALWarpSrcAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType, int nXOff, int nYOff, int nXSize, int nYSize, GByte ** /*ppImageData */, int bMaskIsFloat, void *pValidityMask, int* pbOutAllOpaque ); CPLErr CPL_DLL GDALWarpSrcMaskMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType, int nXOff, int nYOff, int nXSize, int nYSize, GByte ** /*ppImageData */, int bMaskIsFloat, void *pValidityMask ); CPLErr CPL_DLL GDALWarpCutlineMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType, int nXOff, int nYOff, int nXSize, int nYSize, GByte ** /* ppImageData */, int bMaskIsFloat, void *pValidityMask ); /*! @endcond */ /************************************************************************/ /* GDALWarpOptions */ /************************************************************************/ /** Warp control options for use with GDALWarpOperation::Initialize() */ typedef struct { char **papszWarpOptions; /*! In bytes, 0.0 for internal default */ double dfWarpMemoryLimit; /*! Resampling algorithm to use */ GDALResampleAlg eResampleAlg; /*! data type to use during warp operation, GDT_Unknown lets the algorithm select the type */ GDALDataType eWorkingDataType; /*! Source image dataset. */ GDALDatasetH hSrcDS; /*! Destination image dataset - may be NULL if only using GDALWarpOperation::WarpRegionToBuffer(). */ GDALDatasetH hDstDS; /*! Number of bands to process, may be 0 to select all bands. */ int nBandCount; /*! The band numbers for the source bands to process (1 based) */ int *panSrcBands; /*! The band numbers for the destination bands to process (1 based) */ int *panDstBands; /*! The source band so use as an alpha (transparency) value, 0=disabled */ int nSrcAlphaBand; /*! The dest. band so use as an alpha (transparency) value, 0=disabled */ int nDstAlphaBand; /*! The "nodata" value real component for each input band, if NULL there isn't one */ double *padfSrcNoDataReal; /*! The "nodata" value imaginary component - may be NULL even if real component is provided. This value is not used to flag invalid values. Only the real component is used. */ double *padfSrcNoDataImag; /*! The "nodata" value real component for each output band, if NULL there isn't one */ double *padfDstNoDataReal; /*! The "nodata" value imaginary component - may be NULL even if real component is provided. Note that warp operations only use real component for flagging invalid data.*/ double *padfDstNoDataImag; /*! GDALProgressFunc() compatible progress reporting function, or NULL if there isn't one. */ GDALProgressFunc pfnProgress; /*! Callback argument to be passed to pfnProgress. */ void *pProgressArg; /*! Type of spatial point transformer function */ GDALTransformerFunc pfnTransformer; /*! Handle to image transformer setup structure */ void *pTransformerArg; /** Unused. Must be NULL */ GDALMaskFunc *papfnSrcPerBandValidityMaskFunc; /** Unused. Must be NULL */ void **papSrcPerBandValidityMaskFuncArg; /** Unused. Must be NULL */ GDALMaskFunc pfnSrcValidityMaskFunc; /** Unused. Must be NULL */ void *pSrcValidityMaskFuncArg; /** Unused. Must be NULL */ GDALMaskFunc pfnSrcDensityMaskFunc; /** Unused. Must be NULL */ void *pSrcDensityMaskFuncArg; /** Unused. Must be NULL */ GDALMaskFunc pfnDstDensityMaskFunc; /** Unused. Must be NULL */ void *pDstDensityMaskFuncArg; /** Unused. Must be NULL */ GDALMaskFunc pfnDstValidityMaskFunc; /** Unused. Must be NULL */ void *pDstValidityMaskFuncArg; /** Unused. Must be NULL */ CPLErr (*pfnPreWarpChunkProcessor)( void *pKern, void *pArg ); /** Unused. Must be NULL */ void *pPreWarpProcessorArg; /** Unused. Must be NULL */ CPLErr (*pfnPostWarpChunkProcessor)( void *pKern, void *pArg); /** Unused. Must be NULL */ void *pPostWarpProcessorArg; /*! Optional OGRPolygonH for a masking cutline. */ void *hCutline; /*! Optional blending distance to apply across cutline in pixels, default is zero. */ double dfCutlineBlendDist; } GDALWarpOptions; GDALWarpOptions CPL_DLL * CPL_STDCALL GDALCreateWarpOptions(void); void CPL_DLL CPL_STDCALL GDALDestroyWarpOptions( GDALWarpOptions * ); GDALWarpOptions CPL_DLL * CPL_STDCALL GDALCloneWarpOptions( const GDALWarpOptions * ); void CPL_DLL CPL_STDCALL GDALWarpInitDstNoDataReal( GDALWarpOptions *, double dNoDataReal ); void CPL_DLL CPL_STDCALL GDALWarpInitSrcNoDataReal( GDALWarpOptions *, double dNoDataReal ); void CPL_DLL CPL_STDCALL GDALWarpInitNoDataReal( GDALWarpOptions *, double dNoDataReal ); void CPL_DLL CPL_STDCALL GDALWarpInitDstNoDataImag( GDALWarpOptions *, double dNoDataImag ); void CPL_DLL CPL_STDCALL GDALWarpInitSrcNoDataImag( GDALWarpOptions *, double dNoDataImag ); void CPL_DLL CPL_STDCALL GDALWarpResolveWorkingDataType( GDALWarpOptions * ); void CPL_DLL CPL_STDCALL GDALWarpInitDefaultBandMapping( GDALWarpOptions *, int nBandCount ); /*! @cond Doxygen_Suppress */ CPLXMLNode CPL_DLL * CPL_STDCALL GDALSerializeWarpOptions( const GDALWarpOptions * ); GDALWarpOptions CPL_DLL * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode * ); /*! @endcond */ /************************************************************************/ /* GDALReprojectImage() */ /************************************************************************/ CPLErr CPL_DLL CPL_STDCALL GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT, GDALDatasetH hDstDS, const char *pszDstWKT, GDALResampleAlg eResampleAlg, double dfWarpMemoryLimit, double dfMaxError, GDALProgressFunc pfnProgress, void *pProgressArg, GDALWarpOptions *psOptions ); CPLErr CPL_DLL CPL_STDCALL GDALCreateAndReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT, const char *pszDstFilename, const char *pszDstWKT, GDALDriverH hDstDriver, char **papszCreateOptions, GDALResampleAlg eResampleAlg, double dfWarpMemoryLimit, double dfMaxError, GDALProgressFunc pfnProgress, void *pProgressArg, GDALWarpOptions *psOptions ); /************************************************************************/ /* VRTWarpedDataset */ /************************************************************************/ GDALDatasetH CPL_DLL CPL_STDCALL GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS, const char *pszSrcWKT, const char *pszDstWKT, GDALResampleAlg eResampleAlg, double dfMaxError, const GDALWarpOptions *psOptions ); GDALDatasetH CPL_DLL CPL_STDCALL GDALAutoCreateWarpedVRTEx( GDALDatasetH hSrcDS, const char *pszSrcWKT, const char *pszDstWKT, GDALResampleAlg eResampleAlg, double dfMaxError, const GDALWarpOptions *psOptions, CSLConstList papszTransformerOptions ); GDALDatasetH CPL_DLL CPL_STDCALL GDALCreateWarpedVRT( GDALDatasetH hSrcDS, int nPixels, int nLines, double *padfGeoTransform, GDALWarpOptions *psOptions ); CPLErr CPL_DLL CPL_STDCALL GDALInitializeWarpedVRT( GDALDatasetH hDS, GDALWarpOptions *psWO ); CPL_C_END #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) /************************************************************************/ /* GDALWarpKernel */ /* */ /** This is the number of dummy pixels that must be reserved in source arrays * in order to satisfy assumptions made in GWKResample(), and more specifically * by GWKGetPixelRow() that always read a even number of pixels. So if we are * in the situation to read the last pixel of the source array, we need 1 extra * dummy pixel to avoid reading out of bounds. */ #define WARP_EXTRA_ELTS 1 /** This class represents the lowest level of abstraction of warping. * * It holds the imagery for one "chunk" of a warp, and the * pre-prepared masks. All IO is done before and after its * operation. This class is not normally used by the * application. */ class CPL_DLL GDALWarpKernel { CPL_DISALLOW_COPY_ASSIGN(GDALWarpKernel) public: /** Warp options */ char **papszWarpOptions; /** Resample algorithm */ GDALResampleAlg eResample; /** Working data type */ GDALDataType eWorkingDataType; /** Number of input and output bands (excluding alpha bands) */ int nBands; /** Width of the source image */ int nSrcXSize; /** Height of the source image */ int nSrcYSize; /** Extra pixels (included in nSrcXSize) reserved for filter window. Should be ignored in scale computation */ double dfSrcXExtraSize; /** Extra pixels (included in nSrcYSize) reserved for filter window. Should be ignored in scale computation */ double dfSrcYExtraSize; /** Array of nBands source images of size nSrcXSize * nSrcYSize. Each subarray must have WARP_EXTRA_ELTS at the end */ GByte **papabySrcImage; /** Array of nBands validity mask of size (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) / 8 */ GUInt32 **papanBandSrcValid; /** Unified validity mask of size (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) / 8 */ GUInt32 *panUnifiedSrcValid; /** Unified source density of size nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS */ float *pafUnifiedSrcDensity; /** Width of the destination image */ int nDstXSize; /** Height of the destination image */ int nDstYSize; /** Array of nBands destination images of size nDstXSize * nDstYSize */ GByte **papabyDstImage; /** Validify mask of size (nDstXSize * nDstYSize) / 8 */ GUInt32 *panDstValid; /** Destination density of size nDstXSize * nDstYSize */ float *pafDstDensity; /** X resampling scale, i.e. nDstXSize / nSrcXSize */ double dfXScale; /** Y resampling scale, i.e. nDstYSize / nSrcYSize */ double dfYScale; /** X size of filter kernel */ double dfXFilter; /** Y size of filter kernel */ double dfYFilter; /** X size of window to filter */ int nXRadius; /** Y size of window to filter */ int nYRadius; /** X filtering offset */ int nFiltInitX; /** Y filtering offset */ int nFiltInitY; /** X offset of the source buffer regarding the top-left corner of the image */ int nSrcXOff; /** Y offset of the source buffer regarding the top-left corner of the image */ int nSrcYOff; /** X offset of the destination buffer regarding the top-left corner of the image */ int nDstXOff; /** Y offset of the destination buffer regarding the top-left corner of the image */ int nDstYOff; /** Pixel transformation function */ GDALTransformerFunc pfnTransformer; /** User data provided to pfnTransformer */ void *pTransformerArg; /** Progress function */ GDALProgressFunc pfnProgress; /** User data provided to pfnProgress */ void *pProgress; /** Base/offset value for progress computation */ double dfProgressBase; /** Scale value for progress computation */ double dfProgressScale; /** Array of nBands value for destination nodata */ double *padfDstNoDataReal; /*! @cond Doxygen_Suppress */ /** Per-thread data. Internally set */ void *psThreadData; /*! @endcond */ GDALWarpKernel(); virtual ~GDALWarpKernel(); CPLErr Validate(); CPLErr PerformWarp(); }; /*! @cond Doxygen_Suppress */ void* GWKThreadsCreate(char** papszWarpOptions, GDALTransformerFunc pfnTransformer, void* pTransformerArg); void GWKThreadsEnd(void* psThreadDataIn); /*! @endcond */ /************************************************************************/ /* GDALWarpOperation() */ /* */ /* This object is application created, or created by a higher */ /* level convenience function. It is responsible for */ /* subdividing the operation into chunks, loading and saving */ /* imagery, and establishing the varios validity and density */ /* masks. Actual resampling is done by the GDALWarpKernel. */ /************************************************************************/ /*! @cond Doxygen_Suppress */ typedef struct _GDALWarpChunk GDALWarpChunk; /*! @endcond */ class CPL_DLL GDALWarpOperation { CPL_DISALLOW_COPY_ASSIGN(GDALWarpOperation) private: GDALWarpOptions *psOptions; void WipeOptions(); int ValidateOptions(); CPLErr ComputeSourceWindow( int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize, int *pnSrcXOff, int *pnSrcYOff, int *pnSrcXSize, int *pnSrcYSize, double *pdfSrcXExtraSize, double *pdfSrcYExtraSize, double* pdfSrcFillRatio ); void ComputeSourceWindowStartingFromSource( int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize, double* padfSrcMinX, double* padfSrcMinY, double* padfSrcMaxX, double* padfSrcMaxY); static CPLErr CreateKernelMask( GDALWarpKernel *, int iBand, const char *pszType ); CPLMutex *hIOMutex; CPLMutex *hWarpMutex; int nChunkListCount; int nChunkListMax; GDALWarpChunk *pasChunkList; int bReportTimings; unsigned long nLastTimeReported; void *psThreadData; void WipeChunkList(); CPLErr CollectChunkListInternal( int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize ); void CollectChunkList( int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize ); void ReportTiming( const char * ); public: GDALWarpOperation(); virtual ~GDALWarpOperation(); CPLErr Initialize( const GDALWarpOptions *psNewOptions ); void* CreateDestinationBuffer( int nDstXSize, int nDstYSize, int *pbWasInitialized = nullptr ); static void DestroyDestinationBuffer(void* pDstBuffer); const GDALWarpOptions *GetOptions(); CPLErr ChunkAndWarpImage( int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize ); CPLErr ChunkAndWarpMulti( int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize ); CPLErr WarpRegion( int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize, int nSrcXOff=0, int nSrcYOff=0, int nSrcXSize=0, int nSrcYSize=0, double dfProgressBase=0.0, double dfProgressScale=1.0); CPLErr WarpRegion( int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize, int nSrcXOff, int nSrcYOff, int nSrcXSize, int nSrcYSize, double dfSrcXExtraSize, double dfSrcYExtraSize, double dfProgressBase, double dfProgressScale); CPLErr WarpRegionToBuffer( int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize, void *pDataBuf, GDALDataType eBufDataType, int nSrcXOff=0, int nSrcYOff=0, int nSrcXSize=0, int nSrcYSize=0, double dfProgressBase=0.0, double dfProgressScale=1.0); CPLErr WarpRegionToBuffer( int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize, void *pDataBuf, GDALDataType eBufDataType, int nSrcXOff, int nSrcYOff, int nSrcXSize, int nSrcYSize, double dfSrcXExtraSize, double dfSrcYExtraSize, double dfProgressBase, double dfProgressScale); }; #endif /* def __cplusplus */ CPL_C_START /** Opaque type representing a GDALWarpOperation object */ typedef void * GDALWarpOperationH; GDALWarpOperationH CPL_DLL GDALCreateWarpOperation(const GDALWarpOptions* ); void CPL_DLL GDALDestroyWarpOperation( GDALWarpOperationH ); CPLErr CPL_DLL GDALChunkAndWarpImage( GDALWarpOperationH, int, int, int, int ); CPLErr CPL_DLL GDALChunkAndWarpMulti( GDALWarpOperationH, int, int, int, int ); CPLErr CPL_DLL GDALWarpRegion( GDALWarpOperationH, int, int, int, int, int, int, int, int ); CPLErr CPL_DLL GDALWarpRegionToBuffer( GDALWarpOperationH, int, int, int, int, void *, GDALDataType, int, int, int, int ); /************************************************************************/ /* Warping kernel functions */ /************************************************************************/ /*! @cond Doxygen_Suppress */ int GWKGetFilterRadius(GDALResampleAlg eResampleAlg); typedef double (*FilterFuncType)(double dfX); FilterFuncType GWKGetFilterFunc(GDALResampleAlg eResampleAlg); // TODO(schwehr): Can padfVals be a const pointer? typedef double (*FilterFunc4ValuesType)(double* padfVals); FilterFunc4ValuesType GWKGetFilterFunc4Values(GDALResampleAlg eResampleAlg); /*! @endcond */ CPL_C_END #endif /* ndef GDAL_ALG_H_INCLUDED */