LCOV - code coverage report
Current view: directory - alg - gdalwarpkernel.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1337 1171 87.6 %
Date: 2012-04-28 Functions: 41 38 92.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalwarpkernel.cpp 24161 2012-03-25 22:01:34Z rouault $
       3                 :  *
       4                 :  * Project:  High Performance Image Reprojector
       5                 :  * Purpose:  Implementation of the GDALWarpKernel class.  Implements the actual
       6                 :  *           image warping for a "chunk" of input and output imagery already
       7                 :  *           loaded into memory.
       8                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       9                 :  *
      10                 :  ******************************************************************************
      11                 :  * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "gdalwarper.h"
      33                 : #include "cpl_string.h"
      34                 : #include "gdalwarpkernel_opencl.h"
      35                 : 
      36                 : CPL_CVSID("$Id: gdalwarpkernel.cpp 24161 2012-03-25 22:01:34Z rouault $");
      37                 : 
      38                 : static const int anGWKFilterRadius[] =
      39                 : {
      40                 :     0,      // Nearest neighbour
      41                 :     1,      // Bilinear
      42                 :     2,      // Cubic Convolution
      43                 :     2,      // Cubic B-Spline
      44                 :     3       // Lanczos windowed sinc
      45                 : };
      46                 : 
      47                 : /* Used in gdalwarpoperation.cpp */
      48            1540 : int GWKGetFilterRadius(GDALResampleAlg eResampleAlg)
      49                 : {
      50            1540 :     return anGWKFilterRadius[eResampleAlg];
      51                 : }
      52                 : 
      53                 : #ifdef HAVE_OPENCL
      54                 : static CPLErr GWKOpenCLCase( GDALWarpKernel * );
      55                 : #endif
      56                 : 
      57                 : static CPLErr GWKGeneralCase( GDALWarpKernel * );
      58                 : static CPLErr GWKNearestNoMasksByte( GDALWarpKernel *poWK );
      59                 : static CPLErr GWKBilinearNoMasksByte( GDALWarpKernel *poWK );
      60                 : static CPLErr GWKCubicNoMasksByte( GDALWarpKernel *poWK );
      61                 : static CPLErr GWKCubicSplineNoMasksByte( GDALWarpKernel *poWK );
      62                 : static CPLErr GWKNearestByte( GDALWarpKernel *poWK );
      63                 : static CPLErr GWKNearestNoMasksShort( GDALWarpKernel *poWK );
      64                 : static CPLErr GWKBilinearNoMasksShort( GDALWarpKernel *poWK );
      65                 : static CPLErr GWKCubicNoMasksShort( GDALWarpKernel *poWK );
      66                 : static CPLErr GWKCubicSplineNoMasksShort( GDALWarpKernel *poWK );
      67                 : static CPLErr GWKNearestShort( GDALWarpKernel *poWK );
      68                 : static CPLErr GWKNearestNoMasksFloat( GDALWarpKernel *poWK );
      69                 : static CPLErr GWKNearestFloat( GDALWarpKernel *poWK );
      70                 : 
      71                 : /************************************************************************/
      72                 : /* ==================================================================== */
      73                 : /*                            GDALWarpKernel                            */
      74                 : /* ==================================================================== */
      75                 : /************************************************************************/
      76                 : 
      77                 : /**
      78                 :  * \class GDALWarpKernel "gdalwarper.h"
      79                 :  *
      80                 :  * Low level image warping class.
      81                 :  *
      82                 :  * This class is responsible for low level image warping for one
      83                 :  * "chunk" of imagery.  The class is essentially a structure with all
      84                 :  * data members public - primarily so that new special-case functions 
      85                 :  * can be added without changing the class declaration.  
      86                 :  *
      87                 :  * Applications are normally intended to interactive with warping facilities
      88                 :  * through the GDALWarpOperation class, though the GDALWarpKernel can in
      89                 :  * theory be used directly if great care is taken in setting up the 
      90                 :  * control data. 
      91                 :  *
      92                 :  * <h3>Design Issues</h3>
      93                 :  *
      94                 :  * My intention is that PerformWarp() would analyse the setup in terms
      95                 :  * of the datatype, resampling type, and validity/density mask usage and
      96                 :  * pick one of many specific implementations of the warping algorithm over
      97                 :  * a continuim of optimization vs. generality.  At one end there will be a
      98                 :  * reference general purpose implementation of the algorithm that supports
      99                 :  * any data type (working internally in double precision complex), all three
     100                 :  * resampling types, and any or all of the validity/density masks.  At the
     101                 :  * other end would be highly optimized algorithms for common cases like
     102                 :  * nearest neighbour resampling on GDT_Byte data with no masks.  
     103                 :  *
     104                 :  * The full set of optimized versions have not been decided but we should 
     105                 :  * expect to have at least:
     106                 :  *  - One for each resampling algorithm for 8bit data with no masks. 
     107                 :  *  - One for each resampling algorithm for float data with no masks.
     108                 :  *  - One for each resampling algorithm for float data with any/all masks
     109                 :  *    (essentially the generic case for just float data). 
     110                 :  *  - One for each resampling algorithm for 8bit data with support for
     111                 :  *    input validity masks (per band or per pixel).  This handles the common 
     112                 :  *    case of nodata masking.
     113                 :  *  - One for each resampling algorithm for float data with support for
     114                 :  *    input validity masks (per band or per pixel).  This handles the common 
     115                 :  *    case of nodata masking.
     116                 :  *
     117                 :  * Some of the specializations would operate on all bands in one pass
     118                 :  * (especially the ones without masking would do this), while others might
     119                 :  * process each band individually to reduce code complexity.
     120                 :  *
     121                 :  * <h3>Masking Semantics</h3>
     122                 :  * 
     123                 :  * A detailed explanation of the semantics of the validity and density masks,
     124                 :  * and their effects on resampling kernels is needed here. 
     125                 :  */
     126                 : 
     127                 : /************************************************************************/
     128                 : /*                     GDALWarpKernel Data Members                      */
     129                 : /************************************************************************/
     130                 : 
     131                 : /**
     132                 :  * \var GDALResampleAlg GDALWarpKernel::eResample;
     133                 :  * 
     134                 :  * Resampling algorithm.
     135                 :  *
     136                 :  * The resampling algorithm to use.  One of GRA_NearestNeighbour, 
     137                 :  * GRA_Bilinear, or GRA_Cubic. 
     138                 :  *
     139                 :  * This field is required. GDT_NearestNeighbour may be used as a default
     140                 :  * value. 
     141                 :  */
     142                 :                                   
     143                 : /**
     144                 :  * \var GDALDataType GDALWarpKernel::eWorkingDataType;
     145                 :  * 
     146                 :  * Working pixel data type.
     147                 :  *
     148                 :  * The datatype of pixels in the source image (papabySrcimage) and
     149                 :  * destination image (papabyDstImage) buffers.  Note that operations on 
     150                 :  * some data types (such as GDT_Byte) may be much better optimized than other
     151                 :  * less common cases. 
     152                 :  *
     153                 :  * This field is required.  It may not be GDT_Unknown.
     154                 :  */
     155                 :                                   
     156                 : /**
     157                 :  * \var int GDALWarpKernel::nBands;
     158                 :  * 
     159                 :  * Number of bands.
     160                 :  *
     161                 :  * The number of bands (layers) of imagery being warped.  Determines the
     162                 :  * number of entries in the papabySrcImage, papanBandSrcValid, 
     163                 :  * and papabyDstImage arrays. 
     164                 :  *
     165                 :  * This field is required.
     166                 :  */
     167                 : 
     168                 : /**
     169                 :  * \var int GDALWarpKernel::nSrcXSize;
     170                 :  * 
     171                 :  * Source image width in pixels.
     172                 :  *
     173                 :  * This field is required.
     174                 :  */
     175                 : 
     176                 : /**
     177                 :  * \var int GDALWarpKernel::nSrcYSize;
     178                 :  * 
     179                 :  * Source image height in pixels.
     180                 :  *
     181                 :  * This field is required.
     182                 :  */
     183                 : 
     184                 : /**
     185                 :  * \var int GDALWarpKernel::papabySrcImage;
     186                 :  * 
     187                 :  * Array of source image band data.
     188                 :  *
     189                 :  * This is an array of pointers (of size GDALWarpKernel::nBands) pointers
     190                 :  * to image data.  Each individual band of image data is organized as a single 
     191                 :  * block of image data in left to right, then bottom to top order.  The actual
     192                 :  * type of the image data is determined by GDALWarpKernel::eWorkingDataType.
     193                 :  *
     194                 :  * To access the the pixel value for the (x=3,y=4) pixel (zero based) of
     195                 :  * the second band with eWorkingDataType set to GDT_Float32 use code like
     196                 :  * this:
     197                 :  *
     198                 :  * \code 
     199                 :  *   float dfPixelValue;
     200                 :  *   int   nBand = 1;  // band indexes are zero based.
     201                 :  *   int   nPixel = 3; // zero based
     202                 :  *   int   nLine = 4;  // zero based
     203                 :  *
     204                 :  *   assert( nPixel >= 0 && nPixel < poKern->nSrcXSize );
     205                 :  *   assert( nLine >= 0 && nLine < poKern->nSrcYSize );
     206                 :  *   assert( nBand >= 0 && nBand < poKern->nBands );
     207                 :  *   dfPixelValue = ((float *) poKern->papabySrcImage[nBand-1])
     208                 :  *                                  [nPixel + nLine * poKern->nSrcXSize];
     209                 :  * \endcode
     210                 :  *
     211                 :  * This field is required.
     212                 :  */
     213                 : 
     214                 : /**
     215                 :  * \var GUInt32 **GDALWarpKernel::papanBandSrcValid;
     216                 :  *
     217                 :  * Per band validity mask for source pixels. 
     218                 :  *
     219                 :  * Array of pixel validity mask layers for each source band.   Each of
     220                 :  * the mask layers is the same size (in pixels) as the source image with
     221                 :  * one bit per pixel.  Note that it is legal (and common) for this to be
     222                 :  * NULL indicating that none of the pixels are invalidated, or for some
     223                 :  * band validity masks to be NULL in which case all pixels of the band are
     224                 :  * valid.  The following code can be used to test the validity of a particular
     225                 :  * pixel.
     226                 :  *
     227                 :  * \code 
     228                 :  *   int   bIsValid = TRUE;
     229                 :  *   int   nBand = 1;  // band indexes are zero based.
     230                 :  *   int   nPixel = 3; // zero based
     231                 :  *   int   nLine = 4;  // zero based
     232                 :  *
     233                 :  *   assert( nPixel >= 0 && nPixel < poKern->nSrcXSize );
     234                 :  *   assert( nLine >= 0 && nLine < poKern->nSrcYSize );
     235                 :  *   assert( nBand >= 0 && nBand < poKern->nBands );
     236                 :  * 
     237                 :  *   if( poKern->papanBandSrcValid != NULL
     238                 :  *       && poKern->papanBandSrcValid[nBand] != NULL )
     239                 :  *   {
     240                 :  *       GUInt32 *panBandMask = poKern->papanBandSrcValid[nBand];
     241                 :  *       int    iPixelOffset = nPixel + nLine * poKern->nSrcXSize;
     242                 :  * 
     243                 :  *       bIsValid = panBandMask[iPixelOffset>>5] 
     244                 :  *                  & (0x01 << (iPixelOffset & 0x1f));
     245                 :  *   }
     246                 :  * \endcode
     247                 :  */
     248                 : 
     249                 : /**
     250                 :  * \var GUInt32 *GDALWarpKernel::panUnifiedSrcValid;
     251                 :  *
     252                 :  * Per pixel validity mask for source pixels. 
     253                 :  *
     254                 :  * A single validity mask layer that applies to the pixels of all source
     255                 :  * bands.  It is accessed similarly to papanBandSrcValid, but without the
     256                 :  * extra level of band indirection.
     257                 :  *
     258                 :  * This pointer may be NULL indicating that all pixels are valid. 
     259                 :  * 
     260                 :  * Note that if both panUnifiedSrcValid, and papanBandSrcValid are available,
     261                 :  * the pixel isn't considered to be valid unless both arrays indicate it is
     262                 :  * valid.  
     263                 :  */
     264                 : 
     265                 : /**
     266                 :  * \var float *GDALWarpKernel::pafUnifiedSrcDensity;
     267                 :  *
     268                 :  * Per pixel density mask for source pixels. 
     269                 :  *
     270                 :  * A single density mask layer that applies to the pixels of all source
     271                 :  * bands.  It contains values between 0.0 and 1.0 indicating the degree to 
     272                 :  * which this pixel should be allowed to contribute to the output result. 
     273                 :  *
     274                 :  * This pointer may be NULL indicating that all pixels have a density of 1.0.
     275                 :  *
     276                 :  * The density for a pixel may be accessed like this:
     277                 :  *
     278                 :  * \code 
     279                 :  *   float fDensity = 1.0;
     280                 :  *   int   nPixel = 3; // zero based
     281                 :  *   int   nLine = 4;  // zero based
     282                 :  *
     283                 :  *   assert( nPixel >= 0 && nPixel < poKern->nSrcXSize );
     284                 :  *   assert( nLine >= 0 && nLine < poKern->nSrcYSize );
     285                 :  *   if( poKern->pafUnifiedSrcDensity != NULL )
     286                 :  *     fDensity = poKern->pafUnifiedSrcDensity
     287                 :  *                                  [nPixel + nLine * poKern->nSrcXSize];
     288                 :  * \endcode
     289                 :  */
     290                 : 
     291                 : /**
     292                 :  * \var int GDALWarpKernel::nDstXSize;
     293                 :  *
     294                 :  * Width of destination image in pixels.
     295                 :  *
     296                 :  * This field is required.
     297                 :  */
     298                 : 
     299                 : /**
     300                 :  * \var int GDALWarpKernel::nDstYSize;
     301                 :  *
     302                 :  * Height of destination image in pixels.
     303                 :  *
     304                 :  * This field is required.
     305                 :  */
     306                 : 
     307                 : /**
     308                 :  * \var GByte **GDALWarpKernel::papabyDstImage;
     309                 :  * 
     310                 :  * Array of destination image band data.
     311                 :  *
     312                 :  * This is an array of pointers (of size GDALWarpKernel::nBands) pointers
     313                 :  * to image data.  Each individual band of image data is organized as a single 
     314                 :  * block of image data in left to right, then bottom to top order.  The actual
     315                 :  * type of the image data is determined by GDALWarpKernel::eWorkingDataType.
     316                 :  *
     317                 :  * To access the the pixel value for the (x=3,y=4) pixel (zero based) of
     318                 :  * the second band with eWorkingDataType set to GDT_Float32 use code like
     319                 :  * this:
     320                 :  *
     321                 :  * \code 
     322                 :  *   float dfPixelValue;
     323                 :  *   int   nBand = 1;  // band indexes are zero based.
     324                 :  *   int   nPixel = 3; // zero based
     325                 :  *   int   nLine = 4;  // zero based
     326                 :  *
     327                 :  *   assert( nPixel >= 0 && nPixel < poKern->nDstXSize );
     328                 :  *   assert( nLine >= 0 && nLine < poKern->nDstYSize );
     329                 :  *   assert( nBand >= 0 && nBand < poKern->nBands );
     330                 :  *   dfPixelValue = ((float *) poKern->papabyDstImage[nBand-1])
     331                 :  *                                  [nPixel + nLine * poKern->nSrcYSize];
     332                 :  * \endcode
     333                 :  *
     334                 :  * This field is required.
     335                 :  */
     336                 : 
     337                 : /**
     338                 :  * \var GUInt32 *GDALWarpKernel::panDstValid;
     339                 :  *
     340                 :  * Per pixel validity mask for destination pixels. 
     341                 :  *
     342                 :  * A single validity mask layer that applies to the pixels of all destination
     343                 :  * bands.  It is accessed similarly to papanUnitifiedSrcValid, but based
     344                 :  * on the size of the destination image.
     345                 :  *
     346                 :  * This pointer may be NULL indicating that all pixels are valid. 
     347                 :  */
     348                 : 
     349                 : /**
     350                 :  * \var float *GDALWarpKernel::pafDstDensity;
     351                 :  *
     352                 :  * Per pixel density mask for destination pixels. 
     353                 :  *
     354                 :  * A single density mask layer that applies to the pixels of all destination
     355                 :  * bands.  It contains values between 0.0 and 1.0.
     356                 :  *
     357                 :  * This pointer may be NULL indicating that all pixels have a density of 1.0.
     358                 :  *
     359                 :  * The density for a pixel may be accessed like this:
     360                 :  *
     361                 :  * \code 
     362                 :  *   float fDensity = 1.0;
     363                 :  *   int   nPixel = 3; // zero based
     364                 :  *   int   nLine = 4;  // zero based
     365                 :  *
     366                 :  *   assert( nPixel >= 0 && nPixel < poKern->nDstXSize );
     367                 :  *   assert( nLine >= 0 && nLine < poKern->nDstYSize );
     368                 :  *   if( poKern->pafDstDensity != NULL )
     369                 :  *     fDensity = poKern->pafDstDensity[nPixel + nLine * poKern->nDstXSize];
     370                 :  * \endcode
     371                 :  */
     372                 : 
     373                 : /**
     374                 :  * \var int GDALWarpKernel::nSrcXOff;
     375                 :  *
     376                 :  * X offset to source pixel coordinates for transformation.
     377                 :  *
     378                 :  * See pfnTransformer.
     379                 :  *
     380                 :  * This field is required.
     381                 :  */
     382                 : 
     383                 : /**
     384                 :  * \var int GDALWarpKernel::nSrcYOff;
     385                 :  *
     386                 :  * Y offset to source pixel coordinates for transformation.
     387                 :  *
     388                 :  * See pfnTransformer.
     389                 :  *
     390                 :  * This field is required.
     391                 :  */
     392                 : 
     393                 : /**
     394                 :  * \var int GDALWarpKernel::nDstXOff;
     395                 :  *
     396                 :  * X offset to destination pixel coordinates for transformation.
     397                 :  *
     398                 :  * See pfnTransformer.
     399                 :  *
     400                 :  * This field is required.
     401                 :  */
     402                 : 
     403                 : /**
     404                 :  * \var int GDALWarpKernel::nDstYOff;
     405                 :  *
     406                 :  * Y offset to destination pixel coordinates for transformation.
     407                 :  *
     408                 :  * See pfnTransformer.
     409                 :  *
     410                 :  * This field is required.
     411                 :  */
     412                 : 
     413                 : /**
     414                 :  * \var GDALTransformerFunc GDALWarpKernel::pfnTransformer;
     415                 :  *
     416                 :  * Source/destination location transformer.
     417                 :  *
     418                 :  * The function to call to transform coordinates between source image 
     419                 :  * pixel/line coordinates and destination image pixel/line coordinates.  
     420                 :  * See GDALTransformerFunc() for details of the semantics of this function. 
     421                 :  *
     422                 :  * The GDALWarpKern algorithm will only ever use this transformer in 
     423                 :  * "destination to source" mode (bDstToSrc=TRUE), and will always pass 
     424                 :  * partial or complete scanlines of points in the destination image as
     425                 :  * input.  This means, amoung other things, that it is safe to the the
     426                 :  * approximating transform GDALApproxTransform() as the transformation 
     427                 :  * function. 
     428                 :  *
     429                 :  * Source and destination images may be subsets of a larger overall image.
     430                 :  * The transformation algorithms will expect and return pixel/line coordinates
     431                 :  * in terms of this larger image, so coordinates need to be offset by
     432                 :  * the offsets specified in nSrcXOff, nSrcYOff, nDstXOff, and nDstYOff before
     433                 :  * passing to pfnTransformer, and after return from it. 
     434                 :  * 
     435                 :  * The GDALWarpKernel::pfnTransformerArg value will be passed as the callback
     436                 :  * data to this function when it is called.
     437                 :  *
     438                 :  * This field is required.
     439                 :  */
     440                 : 
     441                 : /**
     442                 :  * \var void *GDALWarpKernel::pTransformerArg;
     443                 :  *
     444                 :  * Callback data for pfnTransformer.
     445                 :  *
     446                 :  * This field may be NULL if not required for the pfnTransformer being used.
     447                 :  */
     448                 : 
     449                 : /**
     450                 :  * \var GDALProgressFunc GDALWarpKernel::pfnProgress;
     451                 :  *
     452                 :  * The function to call to report progress of the algorithm, and to check
     453                 :  * for a requested termination of the operation.  It operates according to
     454                 :  * GDALProgressFunc() semantics. 
     455                 :  *
     456                 :  * Generally speaking the progress function will be invoked for each 
     457                 :  * scanline of the destination buffer that has been processed. 
     458                 :  *
     459                 :  * This field may be NULL (internally set to GDALDummyProgress()). 
     460                 :  */
     461                 : 
     462                 : /**
     463                 :  * \var void *GDALWarpKernel::pProgress;
     464                 :  *
     465                 :  * Callback data for pfnProgress.
     466                 :  *
     467                 :  * This field may be NULL if not required for the pfnProgress being used.
     468                 :  */
     469                 : 
     470                 : 
     471                 : /************************************************************************/
     472                 : /*                           GDALWarpKernel()                           */
     473                 : /************************************************************************/
     474                 : 
     475            1156 : GDALWarpKernel::GDALWarpKernel()
     476                 : 
     477                 : {
     478            1156 :     eResample = GRA_NearestNeighbour;
     479            1156 :     eWorkingDataType = GDT_Unknown;
     480            1156 :     nBands = 0;
     481            1156 :     nDstXOff = 0;
     482            1156 :     nDstYOff = 0;
     483            1156 :     nDstXSize = 0;
     484            1156 :     nDstYSize = 0;
     485            1156 :     nSrcXOff = 0;
     486            1156 :     nSrcYOff = 0;
     487            1156 :     nSrcXSize = 0;
     488            1156 :     nSrcYSize = 0;
     489            1156 :     dfXScale = 1.0;
     490            1156 :     dfYScale = 1.0;
     491            1156 :     dfXFilter = 0.0;
     492            1156 :     dfYFilter = 0.0;
     493            1156 :     nXRadius = 0;
     494            1156 :     nYRadius = 0;
     495            1156 :     nFiltInitX = 0;
     496            1156 :     nFiltInitY = 0;
     497            1156 :     pafDstDensity = NULL;
     498            1156 :     pafUnifiedSrcDensity = NULL;
     499            1156 :     panDstValid = NULL;
     500            1156 :     panUnifiedSrcValid = NULL;
     501            1156 :     papabyDstImage = NULL;
     502            1156 :     papabySrcImage = NULL;
     503            1156 :     papanBandSrcValid = NULL;
     504            1156 :     pfnProgress = GDALDummyProgress;
     505            1156 :     pProgress = NULL;
     506            1156 :     dfProgressBase = 0.0;
     507            1156 :     dfProgressScale = 1.0;
     508            1156 :     pfnTransformer = NULL;
     509            1156 :     pTransformerArg = NULL;
     510            1156 :     papszWarpOptions = NULL;
     511            1156 : }
     512                 : 
     513                 : /************************************************************************/
     514                 : /*                          ~GDALWarpKernel()                           */
     515                 : /************************************************************************/
     516                 : 
     517            1156 : GDALWarpKernel::~GDALWarpKernel()
     518                 : 
     519                 : {
     520            1156 : }
     521                 : 
     522                 : /************************************************************************/
     523                 : /*                            PerformWarp()                             */
     524                 : /************************************************************************/
     525                 : 
     526                 : /**
     527                 :  * \fn CPLErr GDALWarpKernel::PerformWarp();
     528                 :  * 
     529                 :  * This method performs the warp described in the GDALWarpKernel.
     530                 :  *
     531                 :  * @return CE_None on success or CE_Failure if an error occurs.
     532                 :  */
     533                 : 
     534            1154 : CPLErr GDALWarpKernel::PerformWarp()
     535                 : 
     536                 : {
     537                 :     CPLErr eErr;
     538                 : 
     539            1154 :     if( (eErr = Validate()) != CE_None )
     540               0 :         return eErr;
     541                 : 
     542                 :     // See #2445 and #3079
     543            1154 :     if (nSrcXSize <= 0 || nSrcYSize <= 0)
     544                 :     {
     545               2 :         if ( !pfnProgress( dfProgressBase + dfProgressScale,
     546                 :                            "", pProgress ) )
     547                 :         {
     548               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
     549               0 :             return CE_Failure;
     550                 :         }
     551               2 :         return CE_None;
     552                 :     }
     553                 : 
     554                 : /* -------------------------------------------------------------------- */
     555                 : /*      Pre-calculate resampling scales and window sizes for filtering. */
     556                 : /* -------------------------------------------------------------------- */
     557                 : 
     558            1152 :     dfXScale = (double)nDstXSize / nSrcXSize;
     559            1152 :     dfYScale = (double)nDstYSize / nSrcYSize;
     560                 : 
     561            1152 :     dfXFilter = anGWKFilterRadius[eResample];
     562            1152 :     dfYFilter = anGWKFilterRadius[eResample];
     563                 : 
     564                 :     nXRadius = ( dfXScale < 1.0 ) ?
     565            1152 :         (int)ceil( dfXFilter / dfXScale ) :(int)dfXFilter;
     566                 :     nYRadius = ( dfYScale < 1.0 ) ?
     567            1152 :         (int)ceil( dfYFilter / dfYScale ) : (int)dfYFilter;
     568                 : 
     569                 :     // Filter window offset depends on the parity of the kernel radius
     570            1152 :     nFiltInitX = ((anGWKFilterRadius[eResample] + 1) % 2) - nXRadius;
     571            1152 :     nFiltInitY = ((anGWKFilterRadius[eResample] + 1) % 2) - nYRadius;
     572                 : 
     573                 : /* -------------------------------------------------------------------- */
     574                 : /*      Set up resampling functions.                                    */
     575                 : /* -------------------------------------------------------------------- */
     576            1152 :     if( CSLFetchBoolean( papszWarpOptions, "USE_GENERAL_CASE", FALSE ) )
     577               0 :         return GWKGeneralCase( this );
     578                 : 
     579                 : #if defined(HAVE_OPENCL)
     580                 :     if((eWorkingDataType == GDT_Byte
     581                 :         || eWorkingDataType == GDT_CInt16
     582                 :         || eWorkingDataType == GDT_UInt16
     583                 :         || eWorkingDataType == GDT_Int16
     584                 :         || eWorkingDataType == GDT_CFloat32
     585                 :         || eWorkingDataType == GDT_Float32) &&
     586                 :        (eResample == GRA_Bilinear
     587                 :         || eResample == GRA_Cubic
     588                 :         || eResample == GRA_CubicSpline
     589                 :         || eResample == GRA_Lanczos) &&
     590                 :         CSLFetchBoolean( papszWarpOptions, "USE_OPENCL", TRUE ))
     591                 :     {
     592                 :         CPLErr eResult = GWKOpenCLCase( this );
     593                 :         
     594                 :         // CE_Warning tells us a suitable OpenCL environment was not available
     595                 :         // so we fall through to other CPU based methods.
     596                 :         if( eResult != CE_Warning )
     597                 :             return eResult;
     598                 :     }
     599                 : #endif /* defined HAVE_OPENCL */
     600                 : 
     601            1152 :     if( eWorkingDataType == GDT_Byte
     602                 :         && eResample == GRA_NearestNeighbour
     603                 :         && papanBandSrcValid == NULL
     604                 :         && panUnifiedSrcValid == NULL
     605                 :         && pafUnifiedSrcDensity == NULL
     606                 :         && panDstValid == NULL
     607                 :         && pafDstDensity == NULL )
     608             506 :         return GWKNearestNoMasksByte( this );
     609                 : 
     610             646 :     if( eWorkingDataType == GDT_Byte
     611                 :         && eResample == GRA_Bilinear
     612                 :         && papanBandSrcValid == NULL
     613                 :         && panUnifiedSrcValid == NULL
     614                 :         && pafUnifiedSrcDensity == NULL
     615                 :         && panDstValid == NULL
     616                 :         && pafDstDensity == NULL )
     617              28 :         return GWKBilinearNoMasksByte( this );
     618                 : 
     619             618 :     if( eWorkingDataType == GDT_Byte
     620                 :         && eResample == GRA_Cubic
     621                 :         && papanBandSrcValid == NULL
     622                 :         && panUnifiedSrcValid == NULL
     623                 :         && pafUnifiedSrcDensity == NULL
     624                 :         && panDstValid == NULL
     625                 :         && pafDstDensity == NULL )
     626              20 :         return GWKCubicNoMasksByte( this );
     627                 : 
     628             598 :     if( eWorkingDataType == GDT_Byte
     629                 :         && eResample == GRA_CubicSpline
     630                 :         && papanBandSrcValid == NULL
     631                 :         && panUnifiedSrcValid == NULL
     632                 :         && pafUnifiedSrcDensity == NULL
     633                 :         && panDstValid == NULL
     634                 :         && pafDstDensity == NULL )
     635              20 :         return GWKCubicSplineNoMasksByte( this );
     636                 : 
     637             578 :     if( eWorkingDataType == GDT_Byte
     638                 :         && eResample == GRA_NearestNeighbour )
     639              50 :         return GWKNearestByte( this );
     640                 : 
     641             528 :     if( (eWorkingDataType == GDT_Int16 || eWorkingDataType == GDT_UInt16)
     642                 :         && eResample == GRA_NearestNeighbour
     643                 :         && papanBandSrcValid == NULL
     644                 :         && panUnifiedSrcValid == NULL
     645                 :         && pafUnifiedSrcDensity == NULL
     646                 :         && panDstValid == NULL
     647                 :         && pafDstDensity == NULL )
     648              28 :         return GWKNearestNoMasksShort( this );
     649                 : 
     650             500 :     if( (eWorkingDataType == GDT_Int16 )
     651                 :         && eResample == GRA_Cubic
     652                 :         && papanBandSrcValid == NULL
     653                 :         && panUnifiedSrcValid == NULL
     654                 :         && pafUnifiedSrcDensity == NULL
     655                 :         && panDstValid == NULL
     656                 :         && pafDstDensity == NULL )
     657              16 :         return GWKCubicNoMasksShort( this );
     658                 : 
     659             484 :     if( (eWorkingDataType == GDT_Int16 )
     660                 :         && eResample == GRA_CubicSpline
     661                 :         && papanBandSrcValid == NULL
     662                 :         && panUnifiedSrcValid == NULL
     663                 :         && pafUnifiedSrcDensity == NULL
     664                 :         && panDstValid == NULL
     665                 :         && pafDstDensity == NULL )
     666              16 :         return GWKCubicSplineNoMasksShort( this );
     667                 : 
     668             468 :     if( (eWorkingDataType == GDT_Int16 )
     669                 :         && eResample == GRA_Bilinear
     670                 :         && papanBandSrcValid == NULL
     671                 :         && panUnifiedSrcValid == NULL
     672                 :         && pafUnifiedSrcDensity == NULL
     673                 :         && panDstValid == NULL
     674                 :         && pafDstDensity == NULL )
     675              40 :         return GWKBilinearNoMasksShort( this );
     676                 : 
     677             428 :     if( (eWorkingDataType == GDT_Int16 || eWorkingDataType == GDT_UInt16)
     678                 :         && eResample == GRA_NearestNeighbour )
     679              14 :         return GWKNearestShort( this );
     680                 : 
     681             414 :     if( eWorkingDataType == GDT_Float32
     682                 :         && eResample == GRA_NearestNeighbour
     683                 :         && papanBandSrcValid == NULL
     684                 :         && panUnifiedSrcValid == NULL
     685                 :         && pafUnifiedSrcDensity == NULL
     686                 :         && panDstValid == NULL
     687                 :         && pafDstDensity == NULL )
     688              16 :         return GWKNearestNoMasksFloat( this );
     689                 : 
     690             398 :     if( eWorkingDataType == GDT_Float32
     691                 :         && eResample == GRA_NearestNeighbour )
     692              12 :         return GWKNearestFloat( this );
     693                 : 
     694             386 :     return GWKGeneralCase( this );
     695                 : }
     696                 :                                   
     697                 : /************************************************************************/
     698                 : /*                              Validate()                              */
     699                 : /************************************************************************/
     700                 : 
     701                 : /**
     702                 :  * \fn CPLErr GDALWarpKernel::Validate()
     703                 :  * 
     704                 :  * Check the settings in the GDALWarpKernel, and issue a CPLError()
     705                 :  * (and return CE_Failure) if the configuration is considered to be
     706                 :  * invalid for some reason.  
     707                 :  *
     708                 :  * This method will also do some standard defaulting such as setting
     709                 :  * pfnProgress to GDALDummyProgress() if it is NULL. 
     710                 :  *
     711                 :  * @return CE_None on success or CE_Failure if an error is detected.
     712                 :  */
     713                 : 
     714            1154 : CPLErr GDALWarpKernel::Validate()
     715                 : 
     716                 : {
     717            1154 :     if ( (size_t)eResample >=
     718                 :          (sizeof(anGWKFilterRadius) / sizeof(anGWKFilterRadius[0])) )
     719                 :     {
     720                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     721               0 :                   "Unsupported resampling method %d.", (int) eResample );
     722               0 :         return CE_Failure;
     723                 :     }
     724                 : 
     725            1154 :     return CE_None;
     726                 : }
     727                 : 
     728                 : /************************************************************************/
     729                 : /*                         GWKOverlayDensity()                          */
     730                 : /*                                                                      */
     731                 : /*      Compute the final density for the destination pixel.  This      */
     732                 : /*      is a function of the overlay density (passed in) and the        */
     733                 : /*      original density.                                               */
     734                 : /************************************************************************/
     735                 : 
     736         4473094 : static void GWKOverlayDensity( GDALWarpKernel *poWK, int iDstOffset, 
     737                 :                                double dfDensity )
     738                 : {
     739         4473094 :     if( dfDensity < 0.0001 || poWK->pafDstDensity == NULL )
     740         3578016 :         return;
     741                 : 
     742          895078 :     poWK->pafDstDensity[iDstOffset] = (float)
     743          895078 :         ( 1.0 - (1.0 - dfDensity) * (1.0 - poWK->pafDstDensity[iDstOffset]) );
     744                 : }
     745                 : 
     746                 : /************************************************************************/
     747                 : /*                          GWKSetPixelValue()                          */
     748                 : /************************************************************************/
     749                 : 
     750          581734 : static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand, 
     751                 :                              int iDstOffset, double dfDensity, 
     752                 :                              double dfReal, double dfImag )
     753                 : 
     754                 : {
     755          581734 :     GByte *pabyDst = poWK->papabyDstImage[iBand];
     756                 : 
     757                 : /* -------------------------------------------------------------------- */
     758                 : /*      If the source density is less than 100% we need to fetch the    */
     759                 : /*      existing destination value, and mix it with the source to       */
     760                 : /*      get the new "to apply" value.  Also compute composite           */
     761                 : /*      density.                                                        */
     762                 : /*                                                                      */
     763                 : /*      We avoid mixing if density is very near one or risk mixing      */
     764                 : /*      in very extreme nodata values and causing odd results (#1610)   */
     765                 : /* -------------------------------------------------------------------- */
     766          581734 :     if( dfDensity < 0.9999 )
     767                 :     {
     768            2944 :         double dfDstReal, dfDstImag, dfDstDensity = 1.0;
     769                 : 
     770            2944 :         if( dfDensity < 0.0001 )
     771               0 :             return TRUE;
     772                 : 
     773            2944 :         if( poWK->pafDstDensity != NULL )
     774               0 :             dfDstDensity = poWK->pafDstDensity[iDstOffset];
     775            2944 :         else if( poWK->panDstValid != NULL 
     776               0 :                  && !((poWK->panDstValid[iDstOffset>>5]
     777                 :                        & (0x01 << (iDstOffset & 0x1f))) ) )
     778               0 :             dfDstDensity = 0.0;
     779                 : 
     780                 :         // It seems like we also ought to be testing panDstValid[] here!
     781                 : 
     782            2944 :         switch( poWK->eWorkingDataType )
     783                 :         {
     784                 :           case GDT_Byte:
     785            2944 :             dfDstReal = pabyDst[iDstOffset];
     786            2944 :             dfDstImag = 0.0;
     787            2944 :             break;
     788                 : 
     789                 :           case GDT_Int16:
     790               0 :             dfDstReal = ((GInt16 *) pabyDst)[iDstOffset];
     791               0 :             dfDstImag = 0.0;
     792               0 :             break;
     793                 : 
     794                 :           case GDT_UInt16:
     795               0 :             dfDstReal = ((GUInt16 *) pabyDst)[iDstOffset];
     796               0 :             dfDstImag = 0.0;
     797               0 :             break;
     798                 :  
     799                 :           case GDT_Int32:
     800               0 :             dfDstReal = ((GInt32 *) pabyDst)[iDstOffset];
     801               0 :             dfDstImag = 0.0;
     802               0 :             break;
     803                 :  
     804                 :           case GDT_UInt32:
     805               0 :             dfDstReal = ((GUInt32 *) pabyDst)[iDstOffset];
     806               0 :             dfDstImag = 0.0;
     807               0 :             break;
     808                 :  
     809                 :           case GDT_Float32:
     810               0 :             dfDstReal = ((float *) pabyDst)[iDstOffset];
     811               0 :             dfDstImag = 0.0;
     812               0 :             break;
     813                 :  
     814                 :           case GDT_Float64:
     815               0 :             dfDstReal = ((double *) pabyDst)[iDstOffset];
     816               0 :             dfDstImag = 0.0;
     817               0 :             break;
     818                 :  
     819                 :           case GDT_CInt16:
     820               0 :             dfDstReal = ((GInt16 *) pabyDst)[iDstOffset*2];
     821               0 :             dfDstImag = ((GInt16 *) pabyDst)[iDstOffset*2+1];
     822               0 :             break;
     823                 :  
     824                 :           case GDT_CInt32:
     825               0 :             dfDstReal = ((GInt32 *) pabyDst)[iDstOffset*2];
     826               0 :             dfDstImag = ((GInt32 *) pabyDst)[iDstOffset*2+1];
     827               0 :             break;
     828                 :  
     829                 :           case GDT_CFloat32:
     830               0 :             dfDstReal = ((float *) pabyDst)[iDstOffset*2];
     831               0 :             dfDstImag = ((float *) pabyDst)[iDstOffset*2+1];
     832               0 :             break;
     833                 :  
     834                 :           case GDT_CFloat64:
     835               0 :             dfDstReal = ((double *) pabyDst)[iDstOffset*2];
     836               0 :             dfDstImag = ((double *) pabyDst)[iDstOffset*2+1];
     837               0 :             break;
     838                 : 
     839                 :           default:
     840               0 :             CPLAssert( FALSE );
     841               0 :             dfDstDensity = 0.0;
     842               0 :             return FALSE;
     843                 :         }
     844                 : 
     845                 :         // the destination density is really only relative to the portion
     846                 :         // not occluded by the overlay.
     847            2944 :         double dfDstInfluence = (1.0 - dfDensity) * dfDstDensity;
     848                 : 
     849                 :         dfReal = (dfReal * dfDensity + dfDstReal * dfDstInfluence) 
     850            2944 :             / (dfDensity + dfDstInfluence);
     851                 : 
     852                 :         dfImag = (dfImag * dfDensity + dfDstImag * dfDstInfluence) 
     853            2944 :             / (dfDensity + dfDstInfluence);
     854                 :     }
     855                 : 
     856                 : /* -------------------------------------------------------------------- */
     857                 : /*      Actually apply the destination value.                           */
     858                 : /*                                                                      */
     859                 : /*      Avoid using the destination nodata value for integer datatypes  */
     860                 : /*      if by chance it is equal to the computed pixel value.           */
     861                 : /* -------------------------------------------------------------------- */
     862                 : 
     863                 : #define CLAMP(type,minval,maxval) \
     864                 :     do { \
     865                 :     if (dfReal < minval) ((type *) pabyDst)[iDstOffset] = (type)minval; \
     866                 :     else if (dfReal > maxval) ((type *) pabyDst)[iDstOffset] = (type)maxval; \
     867                 :     else ((type *) pabyDst)[iDstOffset] = (minval < 0) ? (type)floor(dfReal + 0.5) : (type)(dfReal + 0.5);  \
     868                 :     if (poWK->padfDstNoDataReal != NULL && \
     869                 :         poWK->padfDstNoDataReal[iBand] == (double)((type *) pabyDst)[iDstOffset]) \
     870                 :     { \
     871                 :         if (((type *) pabyDst)[iDstOffset] == minval)  \
     872                 :             ((type *) pabyDst)[iDstOffset] = (type)(minval + 1); \
     873                 :         else \
     874                 :             ((type *) pabyDst)[iDstOffset] --; \
     875                 :     } } while(0)
     876                 : 
     877          581734 :     switch( poWK->eWorkingDataType )
     878                 :     {
     879                 :       case GDT_Byte:
     880          574590 :         CLAMP(GByte, 0.0, 255.0);
     881          574590 :         break;
     882                 : 
     883                 :       case GDT_Int16:
     884             126 :         CLAMP(GInt16, -32768.0, 32767.0);
     885             126 :         break;
     886                 : 
     887                 :       case GDT_UInt16:
     888             504 :         CLAMP(GUInt16, 0.0, 65535.0);
     889             504 :         break;
     890                 : 
     891                 :       case GDT_UInt32:
     892             630 :         CLAMP(GUInt32, 0.0, 4294967295.0);
     893             630 :         break;
     894                 : 
     895                 :       case GDT_Int32:
     896            2230 :         CLAMP(GInt32, -2147483648.0, 2147483647.0);
     897            2230 :         break;
     898                 : 
     899                 :       case GDT_Float32:
     900             504 :         ((float *) pabyDst)[iDstOffset] = (float) dfReal;
     901             504 :         break;
     902                 : 
     903                 :       case GDT_Float64:
     904             630 :         ((double *) pabyDst)[iDstOffset] = dfReal;
     905             630 :         break;
     906                 : 
     907                 :       case GDT_CInt16:
     908             630 :         if( dfReal < -32768 )
     909               0 :             ((GInt16 *) pabyDst)[iDstOffset*2] = -32768;
     910             630 :         else if( dfReal > 32767 )
     911               0 :             ((GInt16 *) pabyDst)[iDstOffset*2] = 32767;
     912                 :         else
     913             630 :             ((GInt16 *) pabyDst)[iDstOffset*2] = (GInt16) floor(dfReal+0.5);
     914             630 :         if( dfImag < -32768 )
     915               0 :             ((GInt16 *) pabyDst)[iDstOffset*2+1] = -32768;
     916             630 :         else if( dfImag > 32767 )
     917               0 :             ((GInt16 *) pabyDst)[iDstOffset*2+1] = 32767;
     918                 :         else
     919             630 :             ((GInt16 *) pabyDst)[iDstOffset*2+1] = (GInt16) floor(dfImag+0.5);
     920             630 :         break;
     921                 : 
     922                 :       case GDT_CInt32:
     923             630 :         if( dfReal < -2147483648.0 )
     924               0 :             ((GInt32 *) pabyDst)[iDstOffset*2] = (GInt32) -2147483648.0;
     925             630 :         else if( dfReal > 2147483647.0 )
     926               0 :             ((GInt32 *) pabyDst)[iDstOffset*2] = (GInt32) 2147483647.0;
     927                 :         else
     928             630 :             ((GInt32 *) pabyDst)[iDstOffset*2] = (GInt32) floor(dfReal+0.5);
     929             630 :         if( dfImag < -2147483648.0 )
     930               0 :             ((GInt32 *) pabyDst)[iDstOffset*2+1] = (GInt32) -2147483648.0;
     931             630 :         else if( dfImag > 2147483647.0 )
     932               0 :             ((GInt32 *) pabyDst)[iDstOffset*2+1] = (GInt32) 2147483647.0;
     933                 :         else
     934             630 :             ((GInt32 *) pabyDst)[iDstOffset*2+1] = (GInt32) floor(dfImag+0.5);
     935             630 :         break;
     936                 : 
     937                 :       case GDT_CFloat32:
     938             630 :         ((float *) pabyDst)[iDstOffset*2] = (float) dfReal;
     939             630 :         ((float *) pabyDst)[iDstOffset*2+1] = (float) dfImag;
     940             630 :         break;
     941                 : 
     942                 :       case GDT_CFloat64:
     943             630 :         ((double *) pabyDst)[iDstOffset*2] = (double) dfReal;
     944             630 :         ((double *) pabyDst)[iDstOffset*2+1] = (double) dfImag;
     945             630 :         break;
     946                 : 
     947                 :       default:
     948               0 :         return FALSE;
     949                 :     }
     950                 : 
     951          581734 :     return TRUE;
     952                 : }
     953                 : 
     954                 : /************************************************************************/
     955                 : /*                          GWKGetPixelValue()                          */
     956                 : /************************************************************************/
     957                 : 
     958            2558 : static int GWKGetPixelValue( GDALWarpKernel *poWK, int iBand, 
     959                 :                              int iSrcOffset, double *pdfDensity, 
     960                 :                              double *pdfReal, double *pdfImag )
     961                 : 
     962                 : {
     963            2558 :     GByte *pabySrc = poWK->papabySrcImage[iBand];
     964                 : 
     965            2558 :     if( poWK->panUnifiedSrcValid != NULL
     966               0 :         && !((poWK->panUnifiedSrcValid[iSrcOffset>>5]
     967                 :               & (0x01 << (iSrcOffset & 0x1f))) ) )
     968                 :     {
     969               0 :         *pdfDensity = 0.0;
     970               0 :         return FALSE;
     971                 :     }
     972                 : 
     973            5758 :     if( poWK->papanBandSrcValid != NULL
     974            1600 :         && poWK->papanBandSrcValid[iBand] != NULL
     975            1600 :         && !((poWK->papanBandSrcValid[iBand][iSrcOffset>>5]
     976                 :               & (0x01 << (iSrcOffset & 0x1f)))) )
     977                 :     {
     978               0 :         *pdfDensity = 0.0;
     979               0 :         return FALSE;
     980                 :     }
     981                 : 
     982            2558 :     switch( poWK->eWorkingDataType )
     983                 :     {
     984                 :       case GDT_Byte:
     985               2 :         *pdfReal = pabySrc[iSrcOffset];
     986               2 :         *pdfImag = 0.0;
     987               2 :         break;
     988                 : 
     989                 :       case GDT_Int16:
     990               2 :         *pdfReal = ((GInt16 *) pabySrc)[iSrcOffset];
     991               2 :         *pdfImag = 0.0;
     992               2 :         break;
     993                 : 
     994                 :       case GDT_UInt16:
     995               8 :         *pdfReal = ((GUInt16 *) pabySrc)[iSrcOffset];
     996               8 :         *pdfImag = 0.0;
     997               8 :         break;
     998                 :  
     999                 :       case GDT_Int32:
    1000            1734 :         *pdfReal = ((GInt32 *) pabySrc)[iSrcOffset];
    1001            1734 :         *pdfImag = 0.0;
    1002            1734 :         break;
    1003                 :  
    1004                 :       case GDT_UInt32:
    1005             134 :         *pdfReal = ((GUInt32 *) pabySrc)[iSrcOffset];
    1006             134 :         *pdfImag = 0.0;
    1007             134 :         break;
    1008                 :  
    1009                 :       case GDT_Float32:
    1010               8 :         *pdfReal = ((float *) pabySrc)[iSrcOffset];
    1011               8 :         *pdfImag = 0.0;
    1012               8 :         break;
    1013                 :  
    1014                 :       case GDT_Float64:
    1015             134 :         *pdfReal = ((double *) pabySrc)[iSrcOffset];
    1016             134 :         *pdfImag = 0.0;
    1017             134 :         break;
    1018                 :  
    1019                 :       case GDT_CInt16:
    1020             134 :         *pdfReal = ((GInt16 *) pabySrc)[iSrcOffset*2];
    1021             134 :         *pdfImag = ((GInt16 *) pabySrc)[iSrcOffset*2+1];
    1022             134 :         break;
    1023                 :  
    1024                 :       case GDT_CInt32:
    1025             134 :         *pdfReal = ((GInt32 *) pabySrc)[iSrcOffset*2];
    1026             134 :         *pdfImag = ((GInt32 *) pabySrc)[iSrcOffset*2+1];
    1027             134 :         break;
    1028                 :  
    1029                 :       case GDT_CFloat32:
    1030             134 :         *pdfReal = ((float *) pabySrc)[iSrcOffset*2];
    1031             134 :         *pdfImag = ((float *) pabySrc)[iSrcOffset*2+1];
    1032             134 :         break;
    1033                 :  
    1034                 :       case GDT_CFloat64:
    1035             134 :         *pdfReal = ((double *) pabySrc)[iSrcOffset*2];
    1036             134 :         *pdfImag = ((double *) pabySrc)[iSrcOffset*2+1];
    1037             134 :         break;
    1038                 : 
    1039                 :       default:
    1040               0 :         *pdfDensity = 0.0;
    1041               0 :         return FALSE;
    1042                 :     }
    1043                 : 
    1044            2558 :     if( poWK->pafUnifiedSrcDensity != NULL )
    1045               0 :         *pdfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
    1046                 :     else
    1047            2558 :         *pdfDensity = 1.0;
    1048                 : 
    1049            2558 :     return *pdfDensity != 0.0;
    1050                 : }
    1051                 : 
    1052                 : /************************************************************************/
    1053                 : /*                          GWKGetPixelRow()                            */
    1054                 : /************************************************************************/
    1055                 : 
    1056         3883140 : static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand, 
    1057                 :                            int iSrcOffset, int nHalfSrcLen,
    1058                 :                            double adfDensity[],
    1059                 :                            double adfReal[], double adfImag[] )
    1060                 : {
    1061                 :     // We know that nSrcLen is even, so we can *always* unroll loops 2x
    1062         3883140 :     int     nSrcLen = nHalfSrcLen * 2;
    1063         3883140 :     int     bHasValid = FALSE;
    1064                 :     int     i;
    1065                 :     
    1066                 :     // Init the density
    1067        19299416 :     for ( i = 0; i < nSrcLen; i += 2 )
    1068                 :     {
    1069        15416276 :         adfDensity[i] = 1.0;
    1070        15416276 :         adfDensity[i+1] = 1.0;
    1071                 :     }
    1072                 :     
    1073         3883140 :     if ( poWK->panUnifiedSrcValid != NULL )
    1074                 :     {
    1075               0 :         for ( i = 0; i < nSrcLen; i += 2 )
    1076                 :         {
    1077               0 :             if(poWK->panUnifiedSrcValid[(iSrcOffset+i)>>5]
    1078                 :                & (0x01 << ((iSrcOffset+i) & 0x1f)))
    1079               0 :                 bHasValid = TRUE;
    1080                 :             else
    1081               0 :                 adfDensity[i] = 0.0;
    1082                 :             
    1083               0 :             if(poWK->panUnifiedSrcValid[(iSrcOffset+i+1)>>5]
    1084                 :                & (0x01 << ((iSrcOffset+i+1) & 0x1f)))
    1085               0 :                 bHasValid = TRUE;
    1086                 :             else
    1087               0 :                 adfDensity[i+1] = 0.0;
    1088                 :         }
    1089                 : 
    1090                 :         // Reset or fail as needed
    1091               0 :         if ( bHasValid )
    1092               0 :             bHasValid = FALSE;
    1093                 :         else
    1094               0 :             return FALSE;
    1095                 :     }
    1096                 :     
    1097         3913140 :     if ( poWK->papanBandSrcValid != NULL
    1098           30000 :          && poWK->papanBandSrcValid[iBand] != NULL)
    1099                 :     {
    1100           60000 :         for ( i = 0; i < nSrcLen; i += 2 )
    1101                 :         {
    1102           30000 :             if(poWK->papanBandSrcValid[iBand][(iSrcOffset+i)>>5]
    1103                 :                & (0x01 << ((iSrcOffset+i) & 0x1f)))
    1104           30000 :                 bHasValid = TRUE;
    1105                 :             else
    1106               0 :                 adfDensity[i] = 0.0;
    1107                 :             
    1108           30000 :             if(poWK->papanBandSrcValid[iBand][(iSrcOffset+i+1)>>5]
    1109                 :                & (0x01 << ((iSrcOffset+i+1) & 0x1f)))
    1110           30000 :                 bHasValid = TRUE;
    1111                 :             else
    1112               0 :                 adfDensity[i+1] = 0.0;
    1113                 :         }
    1114                 :         
    1115                 :         // Reset or fail as needed
    1116           30000 :         if ( bHasValid )
    1117           30000 :             bHasValid = FALSE;
    1118                 :         else
    1119               0 :             return FALSE;
    1120                 :     }
    1121                 :     
    1122                 :     // Fetch data
    1123         3883140 :     switch( poWK->eWorkingDataType )
    1124                 :     {
    1125                 :         case GDT_Byte:
    1126                 :         {
    1127         3869052 :             GByte* pSrc = (GByte*) poWK->papabySrcImage[iBand];
    1128         3869052 :             pSrc += iSrcOffset;
    1129        19250748 :             for ( i = 0; i < nSrcLen; i += 2 )
    1130                 :             {
    1131        15381696 :                 adfReal[i] = pSrc[i];
    1132        15381696 :                 adfReal[i+1] = pSrc[i+1];
    1133                 :             }
    1134         3869052 :             memset( adfImag, 0, nSrcLen * sizeof(double) );
    1135         3869052 :             break;
    1136                 :         }
    1137                 : 
    1138                 :         case GDT_Int16:
    1139                 :         {
    1140             588 :             GInt16* pSrc = (GInt16*) poWK->papabySrcImage[iBand];
    1141             588 :             pSrc += iSrcOffset;
    1142            2768 :             for ( i = 0; i < nSrcLen; i += 2 )
    1143                 :             {
    1144            2180 :                 adfReal[i] = pSrc[i];
    1145            2180 :                 adfReal[i+1] = pSrc[i+1];
    1146                 :             }
    1147             588 :             memset( adfImag, 0, nSrcLen * sizeof(double) );
    1148             588 :             break;
    1149                 :         }
    1150                 : 
    1151                 :          case GDT_UInt16:
    1152                 :          {
    1153            1500 :             GUInt16* pSrc = (GUInt16*) poWK->papabySrcImage[iBand];
    1154            1500 :             pSrc += iSrcOffset;
    1155            5100 :             for ( i = 0; i < nSrcLen; i += 2 )
    1156                 :             {
    1157            3600 :                 adfReal[i] = pSrc[i];
    1158            3600 :                 adfReal[i+1] = pSrc[i+1];
    1159                 :             }
    1160            1500 :             memset( adfImag, 0, nSrcLen * sizeof(double) );
    1161            1500 :             break;
    1162                 :          }
    1163                 : 
    1164                 :         case GDT_Int32:
    1165                 :         {
    1166            1500 :             GInt32* pSrc = (GInt32*) poWK->papabySrcImage[iBand];
    1167            1500 :             pSrc += iSrcOffset;
    1168            5100 :             for ( i = 0; i < nSrcLen; i += 2 )
    1169                 :             {
    1170            3600 :                 adfReal[i] = pSrc[i];
    1171            3600 :                 adfReal[i+1] = pSrc[i+1];
    1172                 :             }
    1173            1500 :             memset( adfImag, 0, nSrcLen * sizeof(double) );
    1174            1500 :             break;
    1175                 :         }
    1176                 : 
    1177                 :         case GDT_UInt32:
    1178                 :         {
    1179            1500 :             GUInt32* pSrc = (GUInt32*) poWK->papabySrcImage[iBand];
    1180            1500 :             pSrc += iSrcOffset;
    1181            5100 :             for ( i = 0; i < nSrcLen; i += 2 )
    1182                 :             {
    1183            3600 :                 adfReal[i] = pSrc[i];
    1184            3600 :                 adfReal[i+1] = pSrc[i+1];
    1185                 :             }
    1186            1500 :             memset( adfImag, 0, nSrcLen * sizeof(double) );
    1187            1500 :             break;
    1188                 :         }
    1189                 : 
    1190                 :         case GDT_Float32:
    1191                 :         {
    1192            1500 :             float* pSrc = (float*) poWK->papabySrcImage[iBand];
    1193            1500 :             pSrc += iSrcOffset;
    1194            5100 :             for ( i = 0; i < nSrcLen; i += 2 )
    1195                 :             {
    1196            3600 :                 adfReal[i] = pSrc[i];
    1197            3600 :                 adfReal[i+1] = pSrc[i+1];
    1198                 :             }
    1199            1500 :             memset( adfImag, 0, nSrcLen * sizeof(double) );
    1200            1500 :             break;
    1201                 :         }
    1202                 : 
    1203                 :        case GDT_Float64:
    1204                 :        {
    1205            1500 :             double* pSrc = (double*) poWK->papabySrcImage[iBand];
    1206            1500 :             pSrc += iSrcOffset;
    1207            5100 :             for ( i = 0; i < nSrcLen; i += 2 )
    1208                 :             {
    1209            3600 :                 adfReal[i] = pSrc[i];
    1210            3600 :                 adfReal[i+1] = pSrc[i+1];
    1211                 :             }
    1212            1500 :             memset( adfImag, 0, nSrcLen * sizeof(double) );
    1213            1500 :             break;
    1214                 :        }
    1215                 : 
    1216                 :         case GDT_CInt16:
    1217                 :         {
    1218            1500 :             GInt16* pSrc = (GInt16*) poWK->papabySrcImage[iBand];
    1219            1500 :             pSrc += 2 * iSrcOffset;
    1220            5100 :             for ( i = 0; i < nSrcLen; i += 2 )
    1221                 :             {
    1222            3600 :                 adfReal[i] = pSrc[2*i];
    1223            3600 :                 adfImag[i] = pSrc[2*i+1];
    1224                 : 
    1225            3600 :                 adfReal[i+1] = pSrc[2*i+2];
    1226            3600 :                 adfImag[i+1] = pSrc[2*i+3];
    1227                 :             }
    1228            1500 :             break;
    1229                 :         }
    1230                 : 
    1231                 :         case GDT_CInt32:
    1232                 :         {
    1233            1500 :             GInt32* pSrc = (GInt32*) poWK->papabySrcImage[iBand];
    1234            1500 :             pSrc += 2 * iSrcOffset;
    1235            5100 :             for ( i = 0; i < nSrcLen; i += 2 )
    1236                 :             {
    1237            3600 :                 adfReal[i] = pSrc[2*i];
    1238            3600 :                 adfImag[i] = pSrc[2*i+1];
    1239                 : 
    1240            3600 :                 adfReal[i+1] = pSrc[2*i+2];
    1241            3600 :                 adfImag[i+1] = pSrc[2*i+3];
    1242                 :             }
    1243            1500 :             break;
    1244                 :         }
    1245                 : 
    1246                 :         case GDT_CFloat32:
    1247                 :         {
    1248            1500 :             float* pSrc = (float*) poWK->papabySrcImage[iBand];
    1249            1500 :             pSrc += 2 * iSrcOffset;
    1250            5100 :             for ( i = 0; i < nSrcLen; i += 2 )
    1251                 :             {
    1252            3600 :                 adfReal[i] = pSrc[2*i];
    1253            3600 :                 adfImag[i] = pSrc[2*i+1];
    1254                 : 
    1255            3600 :                 adfReal[i+1] = pSrc[2*i+2];
    1256            3600 :                 adfImag[i+1] = pSrc[2*i+3];
    1257                 :             }
    1258            1500 :             break;
    1259                 :         }
    1260                 : 
    1261                 : 
    1262                 :         case GDT_CFloat64:
    1263                 :         {
    1264            1500 :             double* pSrc = (double*) poWK->papabySrcImage[iBand];
    1265            1500 :             pSrc += 2 * iSrcOffset;
    1266            5100 :             for ( i = 0; i < nSrcLen; i += 2 )
    1267                 :             {
    1268            3600 :                 adfReal[i] = pSrc[2*i];
    1269            3600 :                 adfImag[i] = pSrc[2*i+1];
    1270                 : 
    1271            3600 :                 adfReal[i+1] = pSrc[2*i+2];
    1272            3600 :                 adfImag[i+1] = pSrc[2*i+3];
    1273                 :             }
    1274            1500 :             break;
    1275                 :         }
    1276                 : 
    1277                 :         default:
    1278               0 :             CPLAssert(FALSE);
    1279               0 :             memset( adfDensity, 0, nSrcLen * sizeof(double) );
    1280               0 :             return FALSE;
    1281                 :     }
    1282                 :     
    1283         3883140 :     if( poWK->pafUnifiedSrcDensity == NULL )
    1284                 :     {
    1285        19298488 :         for ( i = 0; i < nSrcLen; i += 2 )
    1286                 :         {
    1287                 :             // Take into account earlier calcs
    1288        15415812 :             if(adfDensity[i] > 0.000000001)
    1289                 :             {
    1290        15415812 :                 adfDensity[i] = 1.0;
    1291        15415812 :                 bHasValid = TRUE;
    1292                 :             }
    1293                 :             
    1294        15415812 :             if(adfDensity[i+1] > 0.000000001)
    1295                 :             {
    1296        15415812 :                 adfDensity[i+1] = 1.0;
    1297        15415812 :                 bHasValid = TRUE;
    1298                 :             }
    1299                 :         }
    1300                 :     }
    1301                 :     else
    1302                 :     {
    1303             928 :         for ( i = 0; i < nSrcLen; i += 2 )
    1304                 :         {
    1305             464 :             if(adfDensity[i] > 0.000000001)
    1306             464 :                 adfDensity[i] = poWK->pafUnifiedSrcDensity[iSrcOffset+i];
    1307             464 :             if(adfDensity[i] > 0.000000001)
    1308             352 :                 bHasValid = TRUE;
    1309                 :             
    1310             464 :             if(adfDensity[i+1] > 0.000000001)
    1311             464 :                 adfDensity[i+1] = poWK->pafUnifiedSrcDensity[iSrcOffset+i+1];
    1312             464 :             if(adfDensity[i+1] > 0.000000001)
    1313             424 :                 bHasValid = TRUE;
    1314                 :         }
    1315                 :     }
    1316                 :     
    1317         3883140 :     return bHasValid;
    1318                 : }
    1319                 : 
    1320                 : /************************************************************************/
    1321                 : /*                          GWKGetPixelByte()                           */
    1322                 : /************************************************************************/
    1323                 : 
    1324         1448458 : static int GWKGetPixelByte( GDALWarpKernel *poWK, int iBand, 
    1325                 :                             int iSrcOffset, double *pdfDensity, 
    1326                 :                             GByte *pbValue )
    1327                 : 
    1328                 : {
    1329         1448458 :     GByte *pabySrc = poWK->papabySrcImage[iBand];
    1330                 : 
    1331         2198328 :     if ( ( poWK->panUnifiedSrcValid != NULL
    1332          749870 :            && !((poWK->panUnifiedSrcValid[iSrcOffset>>5]
    1333                 :                  & (0x01 << (iSrcOffset & 0x1f))) ) )
    1334                 :          || ( poWK->papanBandSrcValid != NULL
    1335               0 :               && poWK->papanBandSrcValid[iBand] != NULL
    1336               0 :               && !((poWK->papanBandSrcValid[iBand][iSrcOffset>>5]
    1337                 :                     & (0x01 << (iSrcOffset & 0x1f)))) ) )
    1338                 :     {
    1339               0 :         *pdfDensity = 0.0;
    1340               0 :         return FALSE;
    1341                 :     }
    1342                 : 
    1343         1448458 :     *pbValue = pabySrc[iSrcOffset];
    1344                 : 
    1345         1448458 :     if ( poWK->pafUnifiedSrcDensity == NULL )
    1346         1418252 :         *pdfDensity = 1.0;
    1347                 :     else
    1348           30206 :         *pdfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
    1349                 : 
    1350         1448458 :     return *pdfDensity != 0.0;
    1351                 : }
    1352                 : 
    1353                 : /************************************************************************/
    1354                 : /*                          GWKGetPixelShort()                          */
    1355                 : /************************************************************************/
    1356                 : 
    1357         2976934 : static int GWKGetPixelShort( GDALWarpKernel *poWK, int iBand, 
    1358                 :                              int iSrcOffset, double *pdfDensity, 
    1359                 :                              GInt16 *piValue )
    1360                 : 
    1361                 : {
    1362         2976934 :     GInt16 *pabySrc = (GInt16 *)poWK->papabySrcImage[iBand];
    1363                 : 
    1364         8925990 :     if ( ( poWK->panUnifiedSrcValid != NULL
    1365               0 :            && !((poWK->panUnifiedSrcValid[iSrcOffset>>5]
    1366                 :                  & (0x01 << (iSrcOffset & 0x1f))) ) )
    1367                 :          || ( poWK->papanBandSrcValid != NULL
    1368         2974528 :               && poWK->papanBandSrcValid[iBand] != NULL
    1369         2974528 :               && !((poWK->papanBandSrcValid[iBand][iSrcOffset>>5]
    1370                 :                     & (0x01 << (iSrcOffset & 0x1f)))) ) )
    1371                 :     {
    1372            1430 :         *pdfDensity = 0.0;
    1373            1430 :         return FALSE;
    1374                 :     }
    1375                 : 
    1376         2975504 :     *piValue = pabySrc[iSrcOffset];
    1377                 : 
    1378         2975504 :     if ( poWK->pafUnifiedSrcDensity == NULL )
    1379         2973098 :         *pdfDensity = 1.0;
    1380                 :     else
    1381            2406 :         *pdfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
    1382                 : 
    1383         2975504 :     return *pdfDensity != 0.0;
    1384                 : }
    1385                 : 
    1386                 : /************************************************************************/
    1387                 : /*                          GWKGetPixelFloat()                          */
    1388                 : /************************************************************************/
    1389                 : 
    1390            3206 : static int GWKGetPixelFloat( GDALWarpKernel *poWK, int iBand, 
    1391                 :                              int iSrcOffset, double *pdfDensity, 
    1392                 :                              float *pfValue )
    1393                 : 
    1394                 : {
    1395            3206 :     float *pabySrc = (float *)poWK->papabySrcImage[iBand];
    1396                 : 
    1397            4806 :     if ( ( poWK->panUnifiedSrcValid != NULL
    1398               0 :            && !((poWK->panUnifiedSrcValid[iSrcOffset>>5]
    1399                 :                  & (0x01 << (iSrcOffset & 0x1f))) ) )
    1400                 :          || ( poWK->papanBandSrcValid != NULL
    1401             800 :               && poWK->papanBandSrcValid[iBand] != NULL
    1402             800 :               && !((poWK->papanBandSrcValid[iBand][iSrcOffset>>5]
    1403                 :                     & (0x01 << (iSrcOffset & 0x1f)))) ) )
    1404                 :     {
    1405              80 :         *pdfDensity = 0.0;
    1406              80 :         return FALSE;
    1407                 :     }
    1408                 : 
    1409            3126 :     *pfValue = pabySrc[iSrcOffset];
    1410                 : 
    1411            3126 :     if ( poWK->pafUnifiedSrcDensity == NULL )
    1412             720 :         *pdfDensity = 1.0;
    1413                 :     else
    1414            2406 :         *pdfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
    1415                 : 
    1416            3126 :     return *pdfDensity != 0.0;
    1417                 : }
    1418                 : 
    1419                 : /************************************************************************/
    1420                 : /*                        GWKBilinearResample()                         */
    1421                 : /*     Set of bilinear interpolators                                    */
    1422                 : /************************************************************************/
    1423                 : 
    1424           17176 : static int GWKBilinearResample( GDALWarpKernel *poWK, int iBand, 
    1425                 :                                 double dfSrcX, double dfSrcY,
    1426                 :                                 double *pdfDensity, 
    1427                 :                                 double *pdfReal, double *pdfImag )
    1428                 : 
    1429                 : {
    1430                 :     // Save as local variables to avoid following pointers
    1431           17176 :     int     nSrcXSize = poWK->nSrcXSize;
    1432           17176 :     int     nSrcYSize = poWK->nSrcYSize;
    1433                 :     
    1434           17176 :     int     iSrcX = (int) floor(dfSrcX - 0.5);
    1435           17176 :     int     iSrcY = (int) floor(dfSrcY - 0.5);
    1436                 :     int     iSrcOffset;
    1437           17176 :     double  dfRatioX = 1.5 - (dfSrcX - iSrcX);
    1438           17176 :     double  dfRatioY = 1.5 - (dfSrcY - iSrcY);
    1439                 :     double  adfDensity[2], adfReal[2], adfImag[2];
    1440           17176 :     double  dfAccumulatorReal = 0.0, dfAccumulatorImag = 0.0;
    1441           17176 :     double  dfAccumulatorDensity = 0.0;
    1442           17176 :     double  dfAccumulatorDivisor = 0.0;
    1443           17176 :     int     bShifted = FALSE;
    1444                 : 
    1445           17176 :     if (iSrcX == -1)
    1446                 :     {
    1447               0 :         iSrcX = 0;
    1448               0 :         dfRatioX = 1;
    1449                 :     }
    1450           17176 :     if (iSrcY == -1)
    1451                 :     {
    1452             300 :         iSrcY = 0;
    1453             300 :         dfRatioY = 1;
    1454                 :     }
    1455           17176 :     iSrcOffset = iSrcX + iSrcY * nSrcXSize;
    1456                 : 
    1457                 :     // Shift so we don't overrun the array
    1458           17176 :     if( nSrcXSize * nSrcYSize == iSrcOffset + 1
    1459                 :         || nSrcXSize * nSrcYSize == iSrcOffset + nSrcXSize + 1 )
    1460                 :     {
    1461             222 :         bShifted = TRUE;
    1462             222 :         --iSrcOffset;
    1463                 :     }
    1464                 :     
    1465                 :     // Get pixel row
    1466           17176 :     if ( iSrcY >= 0 && iSrcY < nSrcYSize
    1467                 :          && iSrcOffset >= 0 && iSrcOffset < nSrcXSize * nSrcYSize
    1468                 :          && GWKGetPixelRow( poWK, iBand, iSrcOffset, 1,
    1469                 :                             adfDensity, adfReal, adfImag ) )
    1470                 :     {
    1471           17136 :         double dfMult1 = dfRatioX * dfRatioY;
    1472           17136 :         double dfMult2 = (1.0-dfRatioX) * dfRatioY;
    1473                 : 
    1474                 :         // Shifting corrected
    1475           17136 :         if ( bShifted )
    1476                 :         {
    1477             222 :             adfReal[0] = adfReal[1];
    1478             222 :             adfImag[0] = adfImag[1];
    1479             222 :             adfDensity[0] = adfDensity[1];
    1480                 :         }
    1481                 :         
    1482                 :         // Upper Left Pixel
    1483           34272 :         if ( iSrcX >= 0 && iSrcX < nSrcXSize
    1484           17136 :              && adfDensity[0] > 0.000000001 )
    1485                 :         {
    1486           17104 :             dfAccumulatorDivisor += dfMult1;
    1487                 : 
    1488           17104 :             dfAccumulatorReal += adfReal[0] * dfMult1;
    1489           17104 :             dfAccumulatorImag += adfImag[0] * dfMult1;
    1490           17104 :             dfAccumulatorDensity += adfDensity[0] * dfMult1;
    1491                 :         }
    1492                 :             
    1493                 :         // Upper Right Pixel
    1494           33540 :         if ( iSrcX+1 >= 0 && iSrcX+1 < nSrcXSize
    1495           16404 :              && adfDensity[1] > 0.000000001 )
    1496                 :         {
    1497           16404 :             dfAccumulatorDivisor += dfMult2;
    1498                 : 
    1499           16404 :             dfAccumulatorReal += adfReal[1] * dfMult2;
    1500           16404 :             dfAccumulatorImag += adfImag[1] * dfMult2;
    1501           16404 :             dfAccumulatorDensity += adfDensity[1] * dfMult2;
    1502                 :         }
    1503                 :     }
    1504                 :         
    1505                 :     // Get pixel row
    1506           17176 :     if ( iSrcY+1 >= 0 && iSrcY+1 < nSrcYSize
    1507                 :          && iSrcOffset+nSrcXSize >= 0
    1508                 :          && iSrcOffset+nSrcXSize < nSrcXSize * nSrcYSize
    1509                 :          && GWKGetPixelRow( poWK, iBand, iSrcOffset+nSrcXSize, 1,
    1510                 :                            adfDensity, adfReal, adfImag ) )
    1511                 :     {
    1512           16744 :         double dfMult1 = dfRatioX * (1.0-dfRatioY);
    1513           16744 :         double dfMult2 = (1.0-dfRatioX) * (1.0-dfRatioY);
    1514                 :         
    1515                 :         // Shifting corrected
    1516           16744 :         if ( bShifted )
    1517                 :         {
    1518             114 :             adfReal[0] = adfReal[1];
    1519             114 :             adfImag[0] = adfImag[1];
    1520             114 :             adfDensity[0] = adfDensity[1];
    1521                 :         }
    1522                 :         
    1523                 :         // Lower Left Pixel
    1524           33488 :         if ( iSrcX >= 0 && iSrcX < nSrcXSize
    1525           16744 :              && adfDensity[0] > 0.000000001 )
    1526                 :         {
    1527           16704 :             dfAccumulatorDivisor += dfMult1;
    1528                 : 
    1529           16704 :             dfAccumulatorReal += adfReal[0] * dfMult1;
    1530           16704 :             dfAccumulatorImag += adfImag[0] * dfMult1;
    1531           16704 :             dfAccumulatorDensity += adfDensity[0] * dfMult1;
    1532                 :         }
    1533                 : 
    1534                 :         // Lower Right Pixel
    1535           32864 :         if ( iSrcX+1 >= 0 && iSrcX+1 < nSrcXSize
    1536           16120 :              && adfDensity[1] > 0.000000001 )
    1537                 :         {
    1538           16120 :             dfAccumulatorDivisor += dfMult2;
    1539                 : 
    1540           16120 :             dfAccumulatorReal += adfReal[1] * dfMult2;
    1541           16120 :             dfAccumulatorImag += adfImag[1] * dfMult2;
    1542           16120 :             dfAccumulatorDensity += adfDensity[1] * dfMult2;
    1543                 :         }
    1544                 :     }
    1545                 : 
    1546                 : /* -------------------------------------------------------------------- */
    1547                 : /*      Return result.                                                  */
    1548                 : /* -------------------------------------------------------------------- */
    1549           17176 :     if ( dfAccumulatorDivisor == 1.0 )
    1550                 :     {
    1551           16804 :         *pdfReal = dfAccumulatorReal;
    1552           16804 :         *pdfImag = dfAccumulatorImag;
    1553           16804 :         *pdfDensity = dfAccumulatorDensity;
    1554           16804 :         return TRUE;
    1555                 :     }
    1556             372 :     else if ( dfAccumulatorDivisor < 0.00001 )
    1557                 :     {
    1558               0 :         *pdfReal = 0.0;
    1559               0 :         *pdfImag = 0.0;
    1560               0 :         *pdfDensity = 0.0;
    1561               0 :         return FALSE;
    1562                 :     }
    1563                 :     else
    1564                 :     {
    1565             372 :         *pdfReal = dfAccumulatorReal / dfAccumulatorDivisor;
    1566             372 :         *pdfImag = dfAccumulatorImag / dfAccumulatorDivisor;
    1567             372 :         *pdfDensity = dfAccumulatorDensity / dfAccumulatorDivisor;
    1568             372 :         return TRUE;
    1569                 :     }
    1570                 : }
    1571                 : 
    1572          579390 : static int GWKBilinearResampleNoMasksByte( GDALWarpKernel *poWK, int iBand, 
    1573                 :                                            double dfSrcX, double dfSrcY,
    1574                 :                                            GByte *pbValue )
    1575                 : 
    1576                 : {
    1577          579390 :     double  dfAccumulator = 0.0;
    1578          579390 :     double  dfAccumulatorDivisor = 0.0;
    1579                 : 
    1580          579390 :     int     iSrcX = (int) floor(dfSrcX - 0.5);
    1581          579390 :     int     iSrcY = (int) floor(dfSrcY - 0.5);
    1582          579390 :     int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
    1583          579390 :     double  dfRatioX = 1.5 - (dfSrcX - iSrcX);
    1584          579390 :     double  dfRatioY = 1.5 - (dfSrcY - iSrcY);
    1585                 : 
    1586                 :     // Upper Left Pixel
    1587          579390 :     if( iSrcX >= 0 && iSrcX < poWK->nSrcXSize
    1588                 :         && iSrcY >= 0 && iSrcY < poWK->nSrcYSize )
    1589                 :     {
    1590          565750 :         double dfMult = dfRatioX * dfRatioY;
    1591                 : 
    1592          565750 :         dfAccumulatorDivisor += dfMult;
    1593                 : 
    1594                 :         dfAccumulator +=
    1595          565750 :             (double)poWK->papabySrcImage[iBand][iSrcOffset] * dfMult;
    1596                 :     }
    1597                 :         
    1598                 :     // Upper Right Pixel
    1599          579390 :     if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
    1600                 :         && iSrcY >= 0 && iSrcY < poWK->nSrcYSize )
    1601                 :     {
    1602          571800 :         double dfMult = (1.0-dfRatioX) * dfRatioY;
    1603                 : 
    1604          571800 :         dfAccumulatorDivisor += dfMult;
    1605                 : 
    1606                 :         dfAccumulator +=
    1607          571800 :             (double)poWK->papabySrcImage[iBand][iSrcOffset+1] * dfMult;
    1608                 :     }
    1609                 :         
    1610                 :     // Lower Right Pixel
    1611          579390 :     if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
    1612                 :         && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
    1613                 :     {
    1614          577956 :         double dfMult = (1.0-dfRatioX) * (1.0-dfRatioY);
    1615                 : 
    1616          577956 :         dfAccumulatorDivisor += dfMult;
    1617                 : 
    1618                 :         dfAccumulator +=
    1619          577956 :             (double)poWK->papabySrcImage[iBand][iSrcOffset+1+poWK->nSrcXSize]
    1620          577956 :             * dfMult;
    1621                 :     }
    1622                 :         
    1623                 :     // Lower Left Pixel
    1624          579390 :     if( iSrcX >= 0 && iSrcX < poWK->nSrcXSize
    1625                 :         && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
    1626                 :     {
    1627          571848 :         double dfMult = dfRatioX * (1.0-dfRatioY);
    1628                 : 
    1629          571848 :         dfAccumulatorDivisor += dfMult;
    1630                 : 
    1631                 :         dfAccumulator +=
    1632          571848 :             (double)poWK->papabySrcImage[iBand][iSrcOffset+poWK->nSrcXSize]
    1633          571848 :             * dfMult;
    1634                 :     }
    1635                 : 
    1636                 : /* -------------------------------------------------------------------- */
    1637                 : /*      Return result.                                                  */
    1638                 : /* -------------------------------------------------------------------- */
    1639                 :     double      dfValue;
    1640                 : 
    1641          579390 :     if( dfAccumulatorDivisor < 0.00001 )
    1642                 :     {
    1643               0 :         *pbValue = 0;
    1644               0 :         return FALSE;
    1645                 :     }
    1646          579390 :     else if( dfAccumulatorDivisor == 1.0 )
    1647                 :     {
    1648          548766 :         dfValue = dfAccumulator;
    1649                 :     }
    1650                 :     else
    1651                 :     {
    1652           30624 :         dfValue = dfAccumulator / dfAccumulatorDivisor;
    1653                 :     }
    1654                 : 
    1655          579390 :     if ( dfValue < 0.0 )
    1656               0 :         *pbValue = 0;
    1657          579390 :     else if ( dfValue > 255.0 )
    1658            1432 :         *pbValue = 255;
    1659                 :     else
    1660          577958 :         *pbValue = (GByte)(0.5 + dfValue);
    1661                 :     
    1662          579390 :     return TRUE;
    1663                 : }
    1664                 : 
    1665         3429782 : static int GWKBilinearResampleNoMasksShort( GDALWarpKernel *poWK, int iBand, 
    1666                 :                                             double dfSrcX, double dfSrcY,
    1667                 :                                             GInt16 *piValue )
    1668                 : 
    1669                 : {
    1670         3429782 :     double  dfAccumulator = 0.0;
    1671         3429782 :     double  dfAccumulatorDivisor = 0.0;
    1672                 : 
    1673         3429782 :     int     iSrcX = (int) floor(dfSrcX - 0.5);
    1674         3429782 :     int     iSrcY = (int) floor(dfSrcY - 0.5);
    1675         3429782 :     int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
    1676         3429782 :     double  dfRatioX = 1.5 - (dfSrcX - iSrcX);
    1677         3429782 :     double  dfRatioY = 1.5 - (dfSrcY - iSrcY);
    1678                 : 
    1679                 :     // Upper Left Pixel
    1680         3429782 :     if( iSrcX >= 0 && iSrcX < poWK->nSrcXSize
    1681                 :         && iSrcY >= 0 && iSrcY < poWK->nSrcYSize )
    1682                 :     {
    1683         3414710 :         double dfMult = dfRatioX * dfRatioY;
    1684                 : 
    1685         3414710 :         dfAccumulatorDivisor += dfMult;
    1686                 : 
    1687                 :         dfAccumulator +=
    1688         3414710 :             (double)((GInt16 *)poWK->papabySrcImage[iBand])[iSrcOffset]
    1689         3414710 :             * dfMult;
    1690                 :     }
    1691                 :         
    1692                 :     // Upper Right Pixel
    1693         3429782 :     if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
    1694                 :         && iSrcY >= 0 && iSrcY < poWK->nSrcYSize )
    1695                 :     {
    1696         3418364 :         double dfMult = (1.0-dfRatioX) * dfRatioY;
    1697                 : 
    1698         3418364 :         dfAccumulatorDivisor += dfMult;
    1699                 : 
    1700                 :         dfAccumulator +=
    1701         3418364 :             (double)((GInt16 *)poWK->papabySrcImage[iBand])[iSrcOffset+1] * dfMult;
    1702                 :     }
    1703                 :         
    1704                 :     // Lower Right Pixel
    1705         3429782 :     if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
    1706                 :         && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
    1707                 :     {
    1708         3427070 :         double dfMult = (1.0-dfRatioX) * (1.0-dfRatioY);
    1709                 : 
    1710         3427070 :         dfAccumulatorDivisor += dfMult;
    1711                 : 
    1712                 :         dfAccumulator +=
    1713         3427070 :             (double)((GInt16 *)poWK->papabySrcImage[iBand])[iSrcOffset+1+poWK->nSrcXSize]
    1714         3427070 :             * dfMult;
    1715                 :     }
    1716                 :         
    1717                 :     // Lower Left Pixel
    1718         3429782 :     if( iSrcX >= 0 && iSrcX < poWK->nSrcXSize
    1719                 :         && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
    1720                 :     {
    1721         3423364 :         double dfMult = dfRatioX * (1.0-dfRatioY);
    1722                 : 
    1723         3423364 :         dfAccumulatorDivisor += dfMult;
    1724                 : 
    1725                 :         dfAccumulator +=
    1726         3423364 :             (double)((GInt16 *)poWK->papabySrcImage[iBand])[iSrcOffset+poWK->nSrcXSize]
    1727         3423364 :             * dfMult;
    1728                 :     }
    1729                 : 
    1730                 : /* -------------------------------------------------------------------- */
    1731                 : /*      Return result.                                                  */
    1732                 : /* -------------------------------------------------------------------- */
    1733         3429782 :     if( dfAccumulatorDivisor == 1.0 )
    1734                 :     {
    1735         3397522 :         *piValue = (GInt16)(0.5 + dfAccumulator);
    1736         3397522 :         return TRUE;
    1737                 :     }
    1738           32260 :     else if( dfAccumulatorDivisor < 0.00001 )
    1739                 :     {
    1740               0 :         *piValue = 0;
    1741               0 :         return FALSE;
    1742                 :     }
    1743                 :     else
    1744                 :     {
    1745           32260 :         *piValue = (GInt16)(0.5 + dfAccumulator / dfAccumulatorDivisor);
    1746           32260 :         return TRUE;
    1747                 :     }
    1748                 : }
    1749                 : 
    1750                 : /************************************************************************/
    1751                 : /*                        GWKCubicResample()                            */
    1752                 : /*     Set of bicubic interpolators using cubic convolution.            */
    1753                 : /************************************************************************/
    1754                 : 
    1755                 : #define CubicConvolution(distance1,distance2,distance3,f0,f1,f2,f3) \
    1756                 :    (  (   -f0 +     f1 - f2 + f3) * distance3                       \
    1757                 :     + (2.0*(f0 - f1) + f2 - f3) * distance2                         \
    1758                 :     + (   -f0          + f2     ) * distance1                       \
    1759                 :     +               f1                         )
    1760                 : 
    1761            1116 : static int GWKCubicResample( GDALWarpKernel *poWK, int iBand,
    1762                 :                              double dfSrcX, double dfSrcY,
    1763                 :                              double *pdfDensity,
    1764                 :                              double *pdfReal, double *pdfImag )
    1765                 : 
    1766                 : {
    1767            1116 :     int     iSrcX = (int) floor( dfSrcX - 0.5 );
    1768            1116 :     int     iSrcY = (int) floor( dfSrcY - 0.5 );
    1769            1116 :     int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
    1770            1116 :     double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
    1771            1116 :     double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
    1772            1116 :     double  dfDeltaX2 = dfDeltaX * dfDeltaX;
    1773            1116 :     double  dfDeltaY2 = dfDeltaY * dfDeltaY;
    1774            1116 :     double  dfDeltaX3 = dfDeltaX2 * dfDeltaX;
    1775            1116 :     double  dfDeltaY3 = dfDeltaY2 * dfDeltaY;
    1776                 :     double  adfValueDens[4], adfValueReal[4], adfValueImag[4];
    1777                 :     double  adfDensity[4], adfReal[4], adfImag[4];
    1778                 :     int     i;
    1779                 : 
    1780                 :     // Get the bilinear interpolation at the image borders
    1781            1116 :     if ( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
    1782                 :          || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
    1783                 :         return GWKBilinearResample( poWK, iBand, dfSrcX, dfSrcY,
    1784             828 :                                     pdfDensity, pdfReal, pdfImag );
    1785                 : 
    1786            1440 :     for ( i = -1; i < 3; i++ )
    1787                 :     {
    1788            5760 :         if ( !GWKGetPixelRow(poWK, iBand, iSrcOffset + i * poWK->nSrcXSize - 1,
    1789                 :                              2, adfDensity, adfReal, adfImag)
    1790            1152 :              || adfDensity[0] < 0.000000001
    1791            1152 :              || adfDensity[1] < 0.000000001
    1792            1152 :              || adfDensity[2] < 0.000000001
    1793            1152 :              || adfDensity[3] < 0.000000001 )
    1794                 :         {
    1795                 :             return GWKBilinearResample( poWK, iBand, dfSrcX, dfSrcY,
    1796               0 :                                        pdfDensity, pdfReal, pdfImag );
    1797                 :         }
    1798                 : 
    1799            9216 :         adfValueDens[i + 1] = CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
    1800            9216 :             adfDensity[0], adfDensity[1], adfDensity[2], adfDensity[3]);
    1801            9216 :         adfValueReal[i + 1] = CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
    1802            9216 :             adfReal[0], adfReal[1], adfReal[2], adfReal[3]);
    1803            9216 :         adfValueImag[i + 1] = CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
    1804            9216 :             adfImag[0], adfImag[1], adfImag[2], adfImag[3]);
    1805                 :     }
    1806                 : 
    1807                 :     
    1808                 : /* -------------------------------------------------------------------- */
    1809                 : /*      For now, if we have any pixels missing in the kernel area,      */
    1810                 : /*      we fallback on using bilinear interpolation.  Ideally we        */
    1811                 : /*      should do "weight adjustment" of our results similarly to       */
    1812                 : /*      what is done for the cubic spline and lanc. interpolators.      */
    1813                 : /* -------------------------------------------------------------------- */
    1814            2304 :     *pdfDensity = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
    1815                 :                                    adfValueDens[0], adfValueDens[1],
    1816            2304 :                                    adfValueDens[2], adfValueDens[3]);
    1817            2304 :     *pdfReal = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
    1818                 :                                    adfValueReal[0], adfValueReal[1],
    1819            2304 :                                    adfValueReal[2], adfValueReal[3]);
    1820            2304 :     *pdfImag = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
    1821                 :                                    adfValueImag[0], adfValueImag[1],
    1822            2304 :                                    adfValueImag[2], adfValueImag[3]);
    1823                 :     
    1824             288 :     return TRUE;
    1825                 : }
    1826                 : 
    1827          556414 : static int GWKCubicResampleNoMasksByte( GDALWarpKernel *poWK, int iBand,
    1828                 :                                         double dfSrcX, double dfSrcY,
    1829                 :                                         GByte *pbValue )
    1830                 : 
    1831                 : {
    1832          556414 :     int     iSrcX = (int) floor( dfSrcX - 0.5 );
    1833          556414 :     int     iSrcY = (int) floor( dfSrcY - 0.5 );
    1834          556414 :     int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
    1835          556414 :     double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
    1836          556414 :     double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
    1837          556414 :     double  dfDeltaX2 = dfDeltaX * dfDeltaX;
    1838          556414 :     double  dfDeltaY2 = dfDeltaY * dfDeltaY;
    1839          556414 :     double  dfDeltaX3 = dfDeltaX2 * dfDeltaX;
    1840          556414 :     double  dfDeltaY3 = dfDeltaY2 * dfDeltaY;
    1841                 :     double  adfValue[4];
    1842                 :     int     i;
    1843                 : 
    1844                 :     // Get the bilinear interpolation at the image borders
    1845          556414 :     if ( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
    1846                 :          || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
    1847                 :         return GWKBilinearResampleNoMasksByte( poWK, iBand, dfSrcX, dfSrcY,
    1848           21140 :                                                pbValue);
    1849                 : 
    1850         2676370 :     for ( i = -1; i < 3; i++ )
    1851                 :     {
    1852         2141096 :         int     iOffset = iSrcOffset + i * poWK->nSrcXSize;
    1853                 : 
    1854        23552056 :         adfValue[i + 1] = CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
    1855                 :                             (double)poWK->papabySrcImage[iBand][iOffset - 1],
    1856                 :                             (double)poWK->papabySrcImage[iBand][iOffset],
    1857                 :                             (double)poWK->papabySrcImage[iBand][iOffset + 1],
    1858        23552056 :                             (double)poWK->papabySrcImage[iBand][iOffset + 2]);
    1859                 :     }
    1860                 : 
    1861          535274 :     double dfValue = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
    1862                 :                         adfValue[0], adfValue[1], adfValue[2], adfValue[3]);
    1863                 : 
    1864          535274 :     if ( dfValue < 0.0 )
    1865              16 :         *pbValue = 0;
    1866          535258 :     else if ( dfValue > 255.0 )
    1867           23012 :         *pbValue = 255;
    1868                 :     else
    1869          512246 :         *pbValue = (GByte)(0.5 + dfValue);
    1870                 :     
    1871          535274 :     return TRUE;
    1872                 : }
    1873                 : 
    1874          524414 : static int GWKCubicResampleNoMasksShort( GDALWarpKernel *poWK, int iBand,
    1875                 :                                          double dfSrcX, double dfSrcY,
    1876                 :                                          GInt16 *piValue )
    1877                 : 
    1878                 : {
    1879          524414 :     int     iSrcX = (int) floor( dfSrcX - 0.5 );
    1880          524414 :     int     iSrcY = (int) floor( dfSrcY - 0.5 );
    1881          524414 :     int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
    1882          524414 :     double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
    1883          524414 :     double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
    1884          524414 :     double  dfDeltaX2 = dfDeltaX * dfDeltaX;
    1885          524414 :     double  dfDeltaY2 = dfDeltaY * dfDeltaY;
    1886          524414 :     double  dfDeltaX3 = dfDeltaX2 * dfDeltaX;
    1887          524414 :     double  dfDeltaY3 = dfDeltaY2 * dfDeltaY;
    1888                 :     double  adfValue[4];
    1889                 :     int     i;
    1890                 : 
    1891                 :     // Get the bilinear interpolation at the image borders
    1892          524414 :     if ( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
    1893                 :          || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
    1894                 :         return GWKBilinearResampleNoMasksShort( poWK, iBand, dfSrcX, dfSrcY,
    1895           18364 :                                                 piValue);
    1896                 : 
    1897         2530250 :     for ( i = -1; i < 3; i++ )
    1898                 :     {
    1899         2024200 :         int     iOffset = iSrcOffset + i * poWK->nSrcXSize;
    1900                 : 
    1901        22266200 :         adfValue[i + 1] =CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
    1902                 :                 (double)((GInt16 *)poWK->papabySrcImage[iBand])[iOffset - 1],
    1903                 :                 (double)((GInt16 *)poWK->papabySrcImage[iBand])[iOffset],
    1904                 :                 (double)((GInt16 *)poWK->papabySrcImage[iBand])[iOffset + 1],
    1905        22266200 :                 (double)((GInt16 *)poWK->papabySrcImage[iBand])[iOffset + 2]);
    1906                 :     }
    1907                 : 
    1908         4048400 :     *piValue = (GInt16)CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
    1909         4048400 :                         adfValue[0], adfValue[1], adfValue[2], adfValue[3]);
    1910                 :     
    1911          506050 :     return TRUE;
    1912                 : }
    1913                 : 
    1914                 : 
    1915                 : /************************************************************************/
    1916                 : /*                          GWKLanczosSinc()                            */
    1917                 : /************************************************************************/
    1918                 : 
    1919                 : /*
    1920                 :  * Lanczos windowed sinc interpolation kernel with radius r.
    1921                 :  *        /
    1922                 :  *        | sinc(x) * sinc(x/r), if |x| < r
    1923                 :  * L(x) = | 1, if x = 0                     ,
    1924                 :  *        | 0, otherwise
    1925                 :  *        \
    1926                 :  *
    1927                 :  * where sinc(x) = sin(PI * x) / (PI * x).
    1928                 :  */
    1929                 : 
    1930                 : #define GWK_PI 3.14159265358979323846
    1931         7690124 : static double GWKLanczosSinc( double dfX, double dfR )
    1932                 : {
    1933         7690124 :     if ( fabs(dfX) > dfR )
    1934         1065668 :         return 0.0;
    1935         6624456 :     if ( dfX == 0.0 )
    1936            2728 :         return 1.0;
    1937                 :     
    1938         6621728 :     double dfPIX = GWK_PI * dfX;
    1939         6621728 :     return ( sin(dfPIX) / dfPIX ) * ( sin(dfPIX / dfR) * dfR / dfPIX );
    1940                 : }
    1941                 : #undef GWK_PI
    1942                 : 
    1943                 : /************************************************************************/
    1944                 : /*                           GWKBSpline()                               */
    1945                 : /************************************************************************/
    1946                 : 
    1947         8653900 : static double GWKBSpline( double x )
    1948                 : {
    1949         8653900 :     double xp2 = x + 2.0;
    1950         8653900 :     double xp1 = x + 1.0;
    1951         8653900 :     double xm1 = x - 1.0;
    1952                 :     
    1953                 :     // This will most likely be used, so we'll compute it ahead of time to
    1954                 :     // avoid stalling the processor
    1955         8653900 :     double xp2c = xp2 * xp2 * xp2;
    1956                 :     
    1957                 :     // Note that the test is computed only if it is needed
    1958                 :     return (((xp2 > 0.0)?((xp1 > 0.0)?((x > 0.0)?((xm1 > 0.0)?
    1959                 :                                                   -4.0 * xm1*xm1*xm1:0.0) +
    1960                 :                                        6.0 * x*x*x:0.0) +
    1961                 :                           -4.0 * xp1*xp1*xp1:0.0) +
    1962         8653900 :              xp2c:0.0) ) * 0.166666666666666666666;
    1963                 : }
    1964                 : 
    1965                 : 
    1966                 : typedef struct
    1967                 : {
    1968                 :     // Space for saved X weights
    1969                 :     double  *padfWeightsX;
    1970                 :     char    *panCalcX;
    1971                 : 
    1972                 :     // Space for saving a row of pixels
    1973                 :     double  *padfRowDensity;
    1974                 :     double  *padfRowReal;
    1975                 :     double  *padfRowImag;
    1976                 : } GWKResampleWrkStruct;
    1977                 : 
    1978             174 : static GWKResampleWrkStruct* GWKResampleCreateWrkStruct(GDALWarpKernel *poWK)
    1979                 : {
    1980             174 :     int     nXDist = ( poWK->nXRadius + 1 ) * 2;
    1981                 : 
    1982                 :     GWKResampleWrkStruct* psWrkStruct =
    1983             174 :             (GWKResampleWrkStruct*)CPLMalloc(sizeof(GWKResampleWrkStruct));
    1984                 : 
    1985                 :     // Alloc space for saved X weights
    1986             174 :     psWrkStruct->padfWeightsX = (double *)CPLCalloc( nXDist, sizeof(double) );
    1987             174 :     psWrkStruct->panCalcX = (char *)CPLMalloc( nXDist * sizeof(char) );
    1988                 : 
    1989                 :     // Alloc space for saving a row of pixels
    1990             174 :     psWrkStruct->padfRowDensity = (double *)CPLCalloc( nXDist, sizeof(double) );
    1991             174 :     psWrkStruct->padfRowReal = (double *)CPLCalloc( nXDist, sizeof(double) );
    1992             174 :     psWrkStruct->padfRowImag = (double *)CPLCalloc( nXDist, sizeof(double) );
    1993                 : 
    1994             174 :     return psWrkStruct;
    1995                 : }
    1996                 : 
    1997             174 : static void GWKResampleDeleteWrkStruct(GWKResampleWrkStruct* psWrkStruct)
    1998                 : {
    1999             174 :     CPLFree( psWrkStruct->padfWeightsX );
    2000             174 :     CPLFree( psWrkStruct->panCalcX );
    2001             174 :     CPLFree( psWrkStruct->padfRowDensity );
    2002             174 :     CPLFree( psWrkStruct->padfRowReal );
    2003             174 :     CPLFree( psWrkStruct->padfRowImag );
    2004             174 :     CPLFree( psWrkStruct );
    2005             174 : }
    2006                 : 
    2007                 : /************************************************************************/
    2008                 : /*                           GWKResample()                              */
    2009                 : /************************************************************************/
    2010                 : 
    2011          558768 : static int GWKResample( GDALWarpKernel *poWK, int iBand, 
    2012                 :                         double dfSrcX, double dfSrcY,
    2013                 :                         double *pdfDensity, 
    2014                 :                         double *pdfReal, double *pdfImag,
    2015                 :                         const GWKResampleWrkStruct* psWrkStruct )
    2016                 : 
    2017                 : {
    2018                 :     // Save as local variables to avoid following pointers in loops
    2019          558768 :     int     nSrcXSize = poWK->nSrcXSize;
    2020          558768 :     int     nSrcYSize = poWK->nSrcYSize;
    2021                 : 
    2022          558768 :     double  dfAccumulatorReal = 0.0, dfAccumulatorImag = 0.0;
    2023          558768 :     double  dfAccumulatorDensity = 0.0;
    2024          558768 :     double  dfAccumulatorWeight = 0.0;
    2025          558768 :     int     iSrcX = (int) floor( dfSrcX - 0.5 );
    2026          558768 :     int     iSrcY = (int) floor( dfSrcY - 0.5 );
    2027          558768 :     int     iSrcOffset = iSrcX + iSrcY * nSrcXSize;
    2028          558768 :     double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
    2029          558768 :     double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
    2030          558768 :     int     eResample = poWK->eResample;
    2031                 : 
    2032                 :     double  dfXScale, dfYScale;
    2033                 :     double  dfXFilter, dfYFilter;
    2034                 :     int     nXRadius, nFiltInitX;
    2035                 :     int     nYRadius, nFiltInitY;
    2036                 : 
    2037          558768 :     dfXScale = poWK->dfXScale;
    2038          558768 :     dfYScale = poWK->dfYScale;
    2039          558768 :     nXRadius = poWK->nXRadius;
    2040          558768 :     nYRadius = poWK->nYRadius;
    2041          558768 :     nFiltInitX = poWK->nFiltInitX;
    2042          558768 :     nFiltInitY = poWK->nFiltInitY;
    2043          558768 :     dfXFilter = poWK->dfXFilter;
    2044          558768 :     dfYFilter = poWK->dfYFilter;
    2045                 : 
    2046                 :     int     i, j;
    2047          558768 :     int     nXDist = ( nXRadius + 1 ) * 2;
    2048                 : 
    2049                 :     // Space for saved X weights
    2050          558768 :     double  *padfWeightsX = psWrkStruct->padfWeightsX;
    2051          558768 :     char    *panCalcX = psWrkStruct->panCalcX;
    2052                 : 
    2053                 :     // Space for saving a row of pixels
    2054          558768 :     double  *padfRowDensity = psWrkStruct->padfRowDensity;
    2055          558768 :     double  *padfRowReal = psWrkStruct->padfRowReal;
    2056          558768 :     double  *padfRowImag = psWrkStruct->padfRowImag;
    2057                 : 
    2058                 :     // Mark as needing calculation (don't calculate the weights yet,
    2059                 :     // because a mask may render it unnecessary)
    2060          558768 :     memset( panCalcX, FALSE, nXDist * sizeof(char) );
    2061                 : 
    2062                 :     // Loop over pixel rows in the kernel
    2063         4466796 :     for ( j = nFiltInitY; j <= nYRadius; ++j )
    2064                 :     {
    2065         3908028 :         int     iRowOffset, nXMin = nFiltInitX, nXMax = nXRadius;
    2066                 :         double  dfWeight1;
    2067                 :         
    2068                 :         // Skip sampling over edge of image
    2069         3908028 :         if ( iSrcY + j < 0 || iSrcY + j >= nSrcYSize )
    2070           59960 :             continue;
    2071                 : 
    2072                 :         // Invariant; needs calculation only once per row
    2073         3848068 :         iRowOffset = iSrcOffset + j * nSrcXSize + nFiltInitX;
    2074                 : 
    2075                 :         // Make sure we don't read before or after the source array.
    2076         3848068 :         if ( iRowOffset < 0 )
    2077                 :         {
    2078            2632 :             nXMin = nXMin - iRowOffset;
    2079            2632 :             iRowOffset = 0;
    2080                 :         }
    2081         3848068 :         if ( iRowOffset + nXDist >= nSrcXSize*nSrcYSize )
    2082                 :         {
    2083            1836 :             nXMax = nSrcXSize*nSrcYSize - iRowOffset + nXMin - 1;
    2084            1836 :             nXMax -= (nXMax-nXMin+1) % 2;
    2085                 :         }
    2086                 : 
    2087                 :         // Get pixel values
    2088         3848068 :         if ( !GWKGetPixelRow( poWK, iBand, iRowOffset, (nXMax-nXMin+2)/2,
    2089                 :                               padfRowDensity, padfRowReal, padfRowImag ) )
    2090               0 :             continue;
    2091                 : 
    2092                 :         // Select the resampling algorithm
    2093         3848068 :         if ( eResample == GRA_CubicSpline )
    2094                 :             // Calculate the Y weight
    2095                 :             dfWeight1 = ( dfYScale < 1.0 ) ?
    2096                 :                 GWKBSpline(((double)j) * dfYScale) * dfYScale :
    2097            3600 :                 GWKBSpline(((double)j) - dfDeltaY);
    2098         3844468 :         else if ( eResample == GRA_Lanczos )
    2099                 :             dfWeight1 = ( dfYScale < 1.0 ) ?
    2100                 :                 GWKLanczosSinc(j * dfYScale, dfYFilter) * dfYScale :
    2101         3844468 :                 GWKLanczosSinc(j - dfDeltaY, dfYFilter);
    2102                 :         else
    2103               0 :             return FALSE;
    2104                 :         
    2105                 :         // Iterate over pixels in row
    2106        30766192 :         for (i = nXMin; i <= nXMax; ++i )
    2107                 :         {
    2108                 :             double dfWeight2;
    2109                 :             
    2110                 :             // Skip sampling at edge of image OR if pixel has zero density
    2111        53449520 :             if ( iSrcX + i < 0 || iSrcX + i >= nSrcXSize
    2112        26531396 :                  || padfRowDensity[i-nXMin] < 0.000000001 )
    2113          386728 :                 continue;
    2114                 : 
    2115                 :             // Make or use a cached set of weights for this row
    2116        26531396 :             if ( panCalcX[i-nFiltInitX] )
    2117                 :                 // Use saved weight value instead of recomputing it
    2118        22682032 :                 dfWeight2 = dfWeight1 * padfWeightsX[i-nFiltInitX];
    2119                 :             else
    2120                 :             {
    2121                 :                 // Choose among possible algorithms
    2122         3849364 :                 if ( eResample == GRA_CubicSpline )
    2123                 :                     // Calculate & save the X weight
    2124            3708 :                     padfWeightsX[i-nFiltInitX] = dfWeight2 = (dfXScale < 1.0 ) ?
    2125                 :                         GWKBSpline((double)i * dfXScale) * dfXScale :
    2126            3708 :                         GWKBSpline(dfDeltaX - (double)i);
    2127         3845656 :                 else if ( eResample == GRA_Lanczos )
    2128                 :                     // Calculate & save the X weight
    2129         3845656 :                     padfWeightsX[i-nFiltInitX] = dfWeight2 = (dfXScale < 1.0 ) ?
    2130                 :                         GWKLanczosSinc(i * dfXScale, dfXFilter) * dfXScale :
    2131         3845656 :                         GWKLanczosSinc(i - dfDeltaX, dfXFilter);
    2132                 :                 else
    2133               0 :                     return FALSE;
    2134                 :                 
    2135         3849364 :                 dfWeight2 *= dfWeight1;
    2136         3849364 :                 panCalcX[i-nFiltInitX] = TRUE;
    2137                 :             }
    2138                 :             
    2139                 :             // Accumulate!
    2140        26531396 :             dfAccumulatorReal += padfRowReal[i-nXMin] * dfWeight2;
    2141        26531396 :             dfAccumulatorImag += padfRowImag[i-nXMin] * dfWeight2;
    2142        26531396 :             dfAccumulatorDensity += padfRowDensity[i-nXMin] * dfWeight2;
    2143        26531396 :             dfAccumulatorWeight += dfWeight2;
    2144                 :         }
    2145                 :     }
    2146                 : 
    2147          558768 :     if ( dfAccumulatorWeight < 0.000001 || dfAccumulatorDensity < 0.000001 )
    2148                 :     {
    2149               0 :         *pdfDensity = 0.0;
    2150               0 :         return FALSE;
    2151                 :     }
    2152                 : 
    2153                 :     // Calculate the output taking into account weighting
    2154         1115740 :     if ( dfAccumulatorWeight < 0.99999 || dfAccumulatorWeight > 1.00001 )
    2155                 :     {
    2156          556972 :         *pdfReal = dfAccumulatorReal / dfAccumulatorWeight;
    2157          556972 :         *pdfImag = dfAccumulatorImag / dfAccumulatorWeight;
    2158          556972 :         *pdfDensity = dfAccumulatorDensity / dfAccumulatorWeight;
    2159                 :     }
    2160                 :     else
    2161                 :     {
    2162            1796 :         *pdfReal = dfAccumulatorReal;
    2163            1796 :         *pdfImag = dfAccumulatorImag;
    2164            1796 :         *pdfDensity = dfAccumulatorDensity;
    2165                 :     }
    2166                 :     
    2167          558768 :     return TRUE;
    2168                 : }
    2169                 : 
    2170          556414 : static int GWKCubicSplineResampleNoMasksByte( GDALWarpKernel *poWK, int iBand,
    2171                 :                                               double dfSrcX, double dfSrcY,
    2172                 :                                               GByte *pbValue, double *padfBSpline )
    2173                 : 
    2174                 : {
    2175                 :     // Commonly used; save locally
    2176          556414 :     int     nSrcXSize = poWK->nSrcXSize;
    2177          556414 :     int     nSrcYSize = poWK->nSrcYSize;
    2178                 :     
    2179          556414 :     double  dfAccumulator = 0.0;
    2180          556414 :     int     iSrcX = (int) floor( dfSrcX - 0.5 );
    2181          556414 :     int     iSrcY = (int) floor( dfSrcY - 0.5 );
    2182          556414 :     int     iSrcOffset = iSrcX + iSrcY * nSrcXSize;
    2183          556414 :     double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
    2184          556414 :     double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
    2185                 : 
    2186          556414 :     double  dfXScale = poWK->dfXScale;
    2187          556414 :     double  dfYScale = poWK->dfYScale;
    2188          556414 :     int     nXRadius = poWK->nXRadius;
    2189          556414 :     int     nYRadius = poWK->nYRadius;
    2190                 : 
    2191          556414 :     GByte*  pabySrcBand = poWK->papabySrcImage[iBand];
    2192                 :     
    2193                 :     // Politely refusing to process invalid coordinates or obscenely small image
    2194          556414 :     if ( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize
    2195                 :          || nXRadius > nSrcXSize || nYRadius > nSrcYSize )
    2196               2 :         return GWKBilinearResampleNoMasksByte( poWK, iBand, dfSrcX, dfSrcY, pbValue);
    2197                 : 
    2198                 :     // Loop over all rows in the kernel
    2199                 :     int     j, jC;
    2200         2782060 :     for ( jC = 0, j = 1 - nYRadius; j <= nYRadius; ++j, ++jC )
    2201                 :     {
    2202                 :         int     iSampJ;
    2203                 :         // Calculate the Y weight
    2204                 :         double  dfWeight1 = ( dfYScale < 1.0 ) ?
    2205                 :             GWKBSpline((double)j * dfYScale) * dfYScale :
    2206         2225648 :             GWKBSpline((double)j - dfDeltaY);
    2207                 : 
    2208                 :         // Flip sampling over edge of image
    2209         2225648 :         if ( iSrcY + j < 0 )
    2210           13352 :             iSampJ = iSrcOffset - (iSrcY + j) * nSrcXSize;
    2211         2212296 :         else if ( iSrcY + j >= nSrcYSize )
    2212            1112 :             iSampJ = iSrcOffset + (2*nSrcYSize - 2*iSrcY - j - 1) * nSrcXSize;
    2213                 :         else
    2214         2211184 :             iSampJ = iSrcOffset + j * nSrcXSize;
    2215                 :         
    2216                 :         // Loop over all pixels in the row
    2217                 :         int     i, iC;
    2218        11128240 :         for ( iC = 0, i = 1 - nXRadius; i <= nXRadius; ++i, ++iC )
    2219                 :         {
    2220                 :             int     iSampI;
    2221                 :             double  dfWeight2;
    2222                 :             
    2223                 :             // Flip sampling over edge of image
    2224         8902592 :             if ( iSrcX + i < 0 )
    2225           53408 :                 iSampI = -iSrcX - i;
    2226         8849184 :             else if ( iSrcX + i >= nSrcXSize )
    2227            4448 :                 iSampI = 2*nSrcXSize - 2*iSrcX - i - 1;
    2228                 :             else
    2229         8844736 :                 iSampI = i;
    2230                 :             
    2231                 :             // Make a cached set of GWKBSpline values
    2232         8902592 :             if( jC == 0 )
    2233                 :             {
    2234                 :                 // Calculate & save the X weight
    2235         2225648 :                 dfWeight2 = padfBSpline[iC] = ((dfXScale < 1.0 ) ?
    2236                 :                     GWKBSpline((double)i * dfXScale) * dfXScale :
    2237         2225648 :                     GWKBSpline(dfDeltaX - (double)i));
    2238         2225648 :                 dfWeight2 *= dfWeight1;
    2239                 :             }
    2240                 :             else
    2241         6676944 :                 dfWeight2 = dfWeight1 * padfBSpline[iC];
    2242                 : 
    2243                 :             // Retrieve the pixel & accumulate
    2244         8902592 :             dfAccumulator += (double)pabySrcBand[iSampI+iSampJ] * dfWeight2;
    2245                 :         }
    2246                 :     }
    2247                 : 
    2248          556412 :     if ( dfAccumulator < 0.0 )
    2249               0 :         *pbValue = 0;
    2250          556412 :     else if ( dfAccumulator > 255.0 )
    2251              38 :         *pbValue = 255;
    2252                 :     else
    2253          556374 :         *pbValue = (GByte)(0.5 + dfAccumulator);
    2254                 :      
    2255          556412 :     return TRUE;
    2256                 : }
    2257                 : 
    2258          524414 : static int GWKCubicSplineResampleNoMasksShort( GDALWarpKernel *poWK, int iBand,
    2259                 :                                                double dfSrcX, double dfSrcY,
    2260                 :                                                GInt16 *piValue, double *padfBSpline )
    2261                 : 
    2262                 : {
    2263                 :     //Save src size to local var
    2264          524414 :     int     nSrcXSize = poWK->nSrcXSize;
    2265          524414 :     int     nSrcYSize = poWK->nSrcYSize;
    2266                 :     
    2267          524414 :     double  dfAccumulator = 0.0;
    2268          524414 :     int     iSrcX = (int) floor( dfSrcX - 0.5 );
    2269          524414 :     int     iSrcY = (int) floor( dfSrcY - 0.5 );
    2270          524414 :     int     iSrcOffset = iSrcX + iSrcY * nSrcXSize;
    2271          524414 :     double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
    2272          524414 :     double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
    2273                 : 
    2274          524414 :     double  dfXScale = poWK->dfXScale;
    2275          524414 :     double  dfYScale = poWK->dfYScale;
    2276          524414 :     int     nXRadius = poWK->nXRadius;
    2277          524414 :     int     nYRadius = poWK->nYRadius;
    2278                 : 
    2279                 :     // Save band array pointer to local var; cast here instead of later
    2280          524414 :     GInt16* pabySrcBand = ((GInt16 *)poWK->papabySrcImage[iBand]);
    2281                 : 
    2282                 :     // Politely refusing to process invalid coordinates or obscenely small image
    2283          524414 :     if ( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize
    2284                 :          || nXRadius > nSrcXSize || nYRadius > nSrcYSize )
    2285               2 :         return GWKBilinearResampleNoMasksShort( poWK, iBand, dfSrcX, dfSrcY, piValue);
    2286                 : 
    2287                 :     // Loop over all pixels in the kernel
    2288                 :     int     j, jC;
    2289         2622060 :     for ( jC = 0, j = 1 - nYRadius; j <= nYRadius; ++j, ++jC )
    2290                 :     {
    2291                 :         int     iSampJ;
    2292                 :         
    2293                 :         // Calculate the Y weight
    2294                 :         double  dfWeight1 = ( dfYScale < 1.0 ) ?
    2295                 :             GWKBSpline((double)j * dfYScale) * dfYScale :
    2296         2097648 :             GWKBSpline((double)j - dfDeltaY);
    2297                 : 
    2298                 :         // Flip sampling over edge of image
    2299         2097648 :         if ( iSrcY + j < 0 )
    2300           12312 :             iSampJ = iSrcOffset - (iSrcY + j) * nSrcXSize;
    2301         2085336 :         else if ( iSrcY + j >= nSrcYSize )
    2302              72 :             iSampJ = iSrcOffset + (2*nSrcYSize - 2*iSrcY - j - 1) * nSrcXSize;
    2303                 :         else
    2304         2085264 :             iSampJ = iSrcOffset + j * nSrcXSize;
    2305                 :         
    2306                 :         // Loop over all pixels in row
    2307                 :         int     i, iC;
    2308        10488240 :         for ( iC = 0, i = 1 - nXRadius; i <= nXRadius; ++i, ++iC )
    2309                 :         {
    2310                 :         int     iSampI;
    2311                 :             double  dfWeight2;
    2312                 :             
    2313                 :             // Flip sampling over edge of image
    2314         8390592 :             if ( iSrcX + i < 0 )
    2315           49248 :                 iSampI = -iSrcX - i;
    2316         8341344 :             else if(iSrcX + i >= nSrcXSize)
    2317             288 :                 iSampI = 2*nSrcXSize - 2*iSrcX - i - 1;
    2318                 :             else
    2319         8341056 :                 iSampI = i;
    2320                 :             
    2321                 :             // Make a cached set of GWKBSpline values
    2322         8390592 :             if ( jC == 0 )
    2323                 :             {
    2324                 :                 // Calculate & save the X weight
    2325         2097648 :                 dfWeight2 = padfBSpline[iC] = ((dfXScale < 1.0 ) ?
    2326                 :                     GWKBSpline((double)i * dfXScale) * dfXScale :
    2327         2097648 :                     GWKBSpline(dfDeltaX - (double)i));
    2328         2097648 :                 dfWeight2 *= dfWeight1;
    2329                 :             } else
    2330         6292944 :                 dfWeight2 = dfWeight1 * padfBSpline[iC];
    2331                 : 
    2332         8390592 :             dfAccumulator += (double)pabySrcBand[iSampI + iSampJ] * dfWeight2;
    2333                 :         }
    2334                 :     }
    2335                 : 
    2336          524412 :     *piValue = (GInt16)(0.5 + dfAccumulator);
    2337                 :     
    2338          524412 :     return TRUE;
    2339                 : }
    2340                 : 
    2341                 : /************************************************************************/
    2342                 : /*                           GWKOpenCLCase()                            */
    2343                 : /*                                                                      */
    2344                 : /*      This is identical to GWKGeneralCase(), but functions via        */
    2345                 : /*      OpenCL. This means we have vector optimization (SSE) and/or     */
    2346                 : /*      GPU optimization depending on our prefs. The code itsef is      */
    2347                 : /*      general and not optimized, but by defining constants we can     */
    2348                 : /*      make some pretty darn good code on the fly.                     */
    2349                 : /************************************************************************/
    2350                 : 
    2351                 : #if defined(HAVE_OPENCL)
    2352                 : static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
    2353                 : {
    2354                 :     int iDstY, iBand;
    2355                 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    2356                 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    2357                 :     int nDstXOff  = poWK->nDstXOff , nDstYOff  = poWK->nDstYOff;
    2358                 :     int nSrcXOff  = poWK->nSrcXOff , nSrcYOff  = poWK->nSrcYOff;
    2359                 :     CPLErr eErr = CE_None;
    2360                 :     struct oclWarper *warper;
    2361                 :     cl_channel_type imageFormat;
    2362                 :     int useImag = FALSE;
    2363                 :     OCLResampAlg resampAlg;
    2364                 :     cl_int err;
    2365                 :     
    2366                 :     switch ( poWK->eWorkingDataType )
    2367                 :     {
    2368                 :       case GDT_Byte:
    2369                 :         imageFormat = CL_UNORM_INT8;
    2370                 :         break;
    2371                 :       case GDT_UInt16:
    2372                 :         imageFormat = CL_UNORM_INT16;
    2373                 :         break;
    2374                 :       case GDT_CInt16:
    2375                 :         useImag = TRUE;
    2376                 :       case GDT_Int16:
    2377                 :         imageFormat = CL_SNORM_INT16;
    2378                 :         break;
    2379                 :       case GDT_CFloat32:
    2380                 :         useImag = TRUE;
    2381                 :       case GDT_Float32:
    2382                 :         imageFormat = CL_FLOAT;
    2383                 :         break;
    2384                 :       default:
    2385                 :         // We don't support higher precision formats
    2386                 :         CPLDebug( "OpenCL",
    2387                 :                   "Unsupported resampling OpenCL data type %d.", 
    2388                 :                   (int) poWK->eWorkingDataType );
    2389                 :         return CE_Warning;
    2390                 :     }
    2391                 :     
    2392                 :     switch (poWK->eResample)
    2393                 :     {
    2394                 :       case GRA_Bilinear:
    2395                 :         resampAlg = OCL_Bilinear;
    2396                 :         break;
    2397                 :       case GRA_Cubic:
    2398                 :         resampAlg = OCL_Cubic;
    2399                 :         break;
    2400                 :       case GRA_CubicSpline:
    2401                 :         resampAlg = OCL_CubicSpline;
    2402                 :         break;
    2403                 :       case GRA_Lanczos:
    2404                 :         resampAlg = OCL_Lanczos;
    2405                 :         break;
    2406                 :       default:
    2407                 :         // We don't support higher precision formats
    2408                 :         CPLDebug( "OpenCL", 
    2409                 :                   "Unsupported resampling OpenCL resampling alg %d.", 
    2410                 :                   (int) poWK->eResample );
    2411                 :         return CE_Warning;
    2412                 :     }
    2413                 :     
    2414                 :     // Using a factor of 2 or 4 seems to have much less rounding error than 3 on the GPU.
    2415                 :     // Then the rounding error can cause strange artifacting under the right conditions.
    2416                 :     warper = GDALWarpKernelOpenCL_createEnv(nSrcXSize, nSrcYSize,
    2417                 :                                             nDstXSize, nDstYSize,
    2418                 :                                             imageFormat, poWK->nBands, 4,
    2419                 :                                             useImag, poWK->papanBandSrcValid != NULL,
    2420                 :                                             poWK->pafDstDensity,
    2421                 :                                             poWK->padfDstNoDataReal,
    2422                 :                                             resampAlg, &err );
    2423                 : 
    2424                 :     if(err != CL_SUCCESS || warper == NULL)
    2425                 :     {
    2426                 :         eErr = CE_Warning;
    2427                 :         if (warper != NULL)
    2428                 :             goto free_warper;
    2429                 :         return eErr;
    2430                 :     }
    2431                 :     
    2432                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKOpenCLCase()\n"
    2433                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    2434                 :               nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
    2435                 :               nDstXOff, nDstYOff, nDstXSize, nDstYSize );
    2436                 :     
    2437                 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    2438                 :     {
    2439                 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    2440                 :         eErr = CE_Failure;
    2441                 :         goto free_warper;
    2442                 :     }
    2443                 :     
    2444                 :     /* ==================================================================== */
    2445                 :     /*      Loop over bands.                                                */
    2446                 :     /* ==================================================================== */
    2447                 :     for( iBand = 0; iBand < poWK->nBands; iBand++ ) {
    2448                 :         if( poWK->papanBandSrcValid != NULL && poWK->papanBandSrcValid[iBand] != NULL) {
    2449                 :             GDALWarpKernelOpenCL_setSrcValid(warper, (int *)poWK->papanBandSrcValid[iBand], iBand);
    2450                 :             if(err != CL_SUCCESS)
    2451                 :             {
    2452                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
    2453                 :                           "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
    2454                 :                 eErr = CE_Failure;
    2455                 :                 goto free_warper;
    2456                 :             }
    2457                 :         }
    2458                 :         
    2459                 :         err = GDALWarpKernelOpenCL_setSrcImg(warper, poWK->papabySrcImage[iBand], iBand);
    2460                 :         if(err != CL_SUCCESS)
    2461                 :         {
    2462                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    2463                 :                       "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
    2464                 :             eErr = CE_Failure;
    2465                 :             goto free_warper;
    2466                 :         }
    2467                 :         
    2468                 :         err = GDALWarpKernelOpenCL_setDstImg(warper, poWK->papabyDstImage[iBand], iBand);
    2469                 :         if(err != CL_SUCCESS)
    2470                 :         {
    2471                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    2472                 :                       "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
    2473                 :             eErr = CE_Failure;
    2474                 :             goto free_warper;
    2475                 :         }
    2476                 :     }
    2477                 :     
    2478                 :     /* -------------------------------------------------------------------- */
    2479                 :     /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    2480                 :     /*      scanlines worth of positions.                                   */
    2481                 :     /* -------------------------------------------------------------------- */
    2482                 :     double *padfX, *padfY, *padfZ;
    2483                 :     int    *pabSuccess;
    2484                 :     
    2485                 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    2486                 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    2487                 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    2488                 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    2489                 :     
    2490                 :     /* ==================================================================== */
    2491                 :     /*      Loop over output lines.                                         */
    2492                 :     /* ==================================================================== */
    2493                 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; ++iDstY )
    2494                 :     {
    2495                 :         int iDstX;
    2496                 :         
    2497                 :         /* ---------------------------------------------------------------- */
    2498                 :         /*      Setup points to transform to source image space.            */
    2499                 :         /* ---------------------------------------------------------------- */
    2500                 :         for( iDstX = 0; iDstX < nDstXSize; ++iDstX )
    2501                 :         {
    2502                 :             padfX[iDstX] = iDstX + 0.5 + nDstXOff;
    2503                 :             padfY[iDstX] = iDstY + 0.5 + nDstYOff;
    2504                 :             padfZ[iDstX] = 0.0;
    2505                 :         }
    2506                 :         
    2507                 :         /* ---------------------------------------------------------------- */
    2508                 :         /*      Transform the points from destination pixel/line coordinates*/
    2509                 :         /*      to source pixel/line coordinates.                           */
    2510                 :         /* ---------------------------------------------------------------- */
    2511                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    2512                 :                               padfX, padfY, padfZ, pabSuccess );
    2513                 :         
    2514                 :         err = GDALWarpKernelOpenCL_setCoordRow(warper, padfX, padfY,
    2515                 :                                                nSrcXOff, nSrcYOff,
    2516                 :                                                pabSuccess, iDstY);
    2517                 :         if(err != CL_SUCCESS)
    2518                 :         {
    2519                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    2520                 :                       "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
    2521                 :             return CE_Failure;
    2522                 :         }
    2523                 :         
    2524                 :         //Update the valid & density masks because we don't do so in the kernel
    2525                 :         for( iDstX = 0; iDstX < nDstXSize && eErr == CE_None; iDstX++ )
    2526                 :         {
    2527                 :             double dfX = padfX[iDstX];
    2528                 :             double dfY = padfY[iDstX];
    2529                 :             int iDstOffset = iDstX + iDstY * nDstXSize;
    2530                 :             
    2531                 :             //See GWKGeneralCase() for appropriate commenting
    2532                 :             if( !pabSuccess[iDstX] || dfX < nSrcXOff || dfY < nSrcYOff )
    2533                 :                 continue;
    2534                 :             
    2535                 :             int iSrcX = ((int) dfX) - nSrcXOff;
    2536                 :             int iSrcY = ((int) dfY) - nSrcYOff;
    2537                 :             
    2538                 :             if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
    2539                 :                 continue;
    2540                 :             
    2541                 :             int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
    2542                 :             double  dfDensity = 1.0;
    2543                 :             
    2544                 :             if( poWK->pafUnifiedSrcDensity != NULL 
    2545                 :                 && iSrcX >= 0 && iSrcY >= 0 
    2546                 :                 && iSrcX < nSrcXSize && iSrcY < nSrcYSize )
    2547                 :                 dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
    2548                 :             
    2549                 :             GWKOverlayDensity( poWK, iDstOffset, dfDensity );
    2550                 :             
    2551                 :             //Because this is on the bit-wise level, it can't be done well in OpenCL
    2552                 :             if( poWK->panDstValid != NULL )
    2553                 :                 poWK->panDstValid[iDstOffset>>5] |= 0x01 << (iDstOffset & 0x1f);
    2554                 :         }
    2555                 :     }
    2556                 :     
    2557                 :     CPLFree( padfX );
    2558                 :     CPLFree( padfY );
    2559                 :     CPLFree( padfZ );
    2560                 :     CPLFree( pabSuccess );
    2561                 :     
    2562                 :     err = GDALWarpKernelOpenCL_runResamp(warper,
    2563                 :                                          poWK->pafUnifiedSrcDensity,
    2564                 :                                          poWK->panUnifiedSrcValid,
    2565                 :                                          poWK->pafDstDensity,
    2566                 :                                          poWK->panUnifiedSrcValid,
    2567                 :                                          poWK->dfXScale, poWK->dfYScale,
    2568                 :                                          poWK->dfXFilter, poWK->dfYFilter,
    2569                 :                                          poWK->nXRadius, poWK->nYRadius,
    2570                 :                                          poWK->nFiltInitX, poWK->nFiltInitY);
    2571                 :     
    2572                 :     if(err != CL_SUCCESS)
    2573                 :     {
    2574                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    2575                 :                   "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
    2576                 :         eErr = CE_Failure;
    2577                 :         goto free_warper;
    2578                 :     }
    2579                 :     
    2580                 :     /* ==================================================================== */
    2581                 :     /*      Loop over output lines.                                         */
    2582                 :     /* ==================================================================== */
    2583                 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    2584                 :     {
    2585                 :         for( iBand = 0; iBand < poWK->nBands; iBand++ )
    2586                 :         {
    2587                 :             int iDstX;
    2588                 :             void *rowReal, *rowImag;
    2589                 :             GByte *pabyDst = poWK->papabyDstImage[iBand];
    2590                 :             
    2591                 :             err = GDALWarpKernelOpenCL_getRow(warper, &rowReal, &rowImag, iDstY, iBand);
    2592                 :             if(err != CL_SUCCESS)
    2593                 :             {
    2594                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
    2595                 :                           "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
    2596                 :                 eErr = CE_Failure;
    2597                 :                 goto free_warper;
    2598                 :             }
    2599                 :             
    2600                 :             //Copy the data from the warper to GDAL's memory
    2601                 :             switch ( poWK->eWorkingDataType )
    2602                 :             {
    2603                 :               case GDT_Byte:
    2604                 :                 memcpy((void **)&(((GByte *)pabyDst)[iDstY*nDstXSize]),
    2605                 :                        rowReal, sizeof(GByte)*nDstXSize);
    2606                 :                 break;
    2607                 :               case GDT_Int16:
    2608                 :                 memcpy((void **)&(((GInt16 *)pabyDst)[iDstY*nDstXSize]),
    2609                 :                        rowReal, sizeof(GInt16)*nDstXSize);
    2610                 :                 break;
    2611                 :               case GDT_UInt16:
    2612                 :                 memcpy((void **)&(((GUInt16 *)pabyDst)[iDstY*nDstXSize]),
    2613                 :                        rowReal, sizeof(GUInt16)*nDstXSize);
    2614                 :                 break;
    2615                 :               case GDT_Float32:
    2616                 :                 memcpy((void **)&(((float *)pabyDst)[iDstY*nDstXSize]),
    2617                 :                        rowReal, sizeof(float)*nDstXSize);
    2618                 :                 break;
    2619                 :               case GDT_CInt16:
    2620                 :               {
    2621                 :                   GInt16 *pabyDstI16 = &(((GInt16 *)pabyDst)[iDstY*nDstXSize]);
    2622                 :                   for (iDstX = 0; iDstX < nDstXSize; iDstX++) {
    2623                 :                       pabyDstI16[iDstX*2  ] = ((GInt16 *)rowReal)[iDstX];
    2624                 :                       pabyDstI16[iDstX*2+1] = ((GInt16 *)rowImag)[iDstX];
    2625                 :                   }
    2626                 :               }
    2627                 :               break;
    2628                 :               case GDT_CFloat32:
    2629                 :               {
    2630                 :                   float *pabyDstF32 = &(((float *)pabyDst)[iDstY*nDstXSize]);
    2631                 :                   for (iDstX = 0; iDstX < nDstXSize; iDstX++) {
    2632                 :                       pabyDstF32[iDstX*2  ] = ((float *)rowReal)[iDstX];
    2633                 :                       pabyDstF32[iDstX*2+1] = ((float *)rowImag)[iDstX];
    2634                 :                   }
    2635                 :               }
    2636                 :               break;
    2637                 :               default:
    2638                 :                 // We don't support higher precision formats
    2639                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
    2640                 :                           "Unsupported resampling OpenCL data type %d.", (int) poWK->eWorkingDataType );
    2641                 :                 eErr = CE_Failure;
    2642                 :                 goto free_warper;
    2643                 :             }
    2644                 :         }
    2645                 :     }
    2646                 : free_warper:
    2647                 :     if((err = GDALWarpKernelOpenCL_deleteEnv(warper)) != CL_SUCCESS)
    2648                 :     {
    2649                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    2650                 :                   "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
    2651                 :         return CE_Failure;
    2652                 :     }
    2653                 :     
    2654                 :     return eErr;
    2655                 : }
    2656                 : #endif /* defined(HAVE_OPENCL) */
    2657                 : 
    2658                 : 
    2659                 : #define COMPUTE_iSrcOffset(_pabSuccess, _iDstX, _padfX, _padfY, _poWK, _nSrcXSize, _nSrcYSize) \
    2660                 :             if( !_pabSuccess[_iDstX] ) \
    2661                 :                 continue; \
    2662                 : \
    2663                 : /* -------------------------------------------------------------------- */ \
    2664                 : /*      Figure out what pixel we want in our source raster, and skip    */ \
    2665                 : /*      further processing if it is well off the source image.          */ \
    2666                 : /* -------------------------------------------------------------------- */ \
    2667                 :             /* We test against the value before casting to avoid the */ \
    2668                 :             /* problem of asymmetric truncation effects around zero.  That is */ \
    2669                 :             /* -0.5 will be 0 when cast to an int. */ \
    2670                 :             if( _padfX[_iDstX] < _poWK->nSrcXOff \
    2671                 :                 || _padfY[_iDstX] < _poWK->nSrcYOff ) \
    2672                 :                 continue; \
    2673                 : \
    2674                 :             int iSrcX, iSrcY, iSrcOffset;\
    2675                 : \
    2676                 :             iSrcX = ((int) (_padfX[_iDstX] + 1e-10)) - _poWK->nSrcXOff;\
    2677                 :             iSrcY = ((int) (_padfY[_iDstX] + 1e-10)) - _poWK->nSrcYOff;\
    2678                 : \
    2679                 :             /* If operating outside natural projection area, padfX/Y can be */ \
    2680                 :             /* a very huge positive number, that becomes -2147483648 in the */ \
    2681                 :             /* int trucation. So it is necessary to test now for non negativeness. */ \
    2682                 :             if( iSrcX < 0 || iSrcX >= _nSrcXSize || iSrcY < 0 || iSrcY >= _nSrcYSize )\
    2683                 :                 continue;\
    2684                 : \
    2685                 :             iSrcOffset = iSrcX + iSrcY * _nSrcXSize;
    2686                 : 
    2687                 : /************************************************************************/
    2688                 : /*                           GWKGeneralCase()                           */
    2689                 : /*                                                                      */
    2690                 : /*      This is the most general case.  It attempts to handle all       */
    2691                 : /*      possible features with relatively little concern for            */
    2692                 : /*      efficiency.                                                     */
    2693                 : /************************************************************************/
    2694                 : 
    2695             386 : static CPLErr GWKGeneralCase( GDALWarpKernel *poWK )
    2696                 : 
    2697                 : {
    2698                 :     int iDstY;
    2699             386 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    2700             386 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    2701             386 :     CPLErr eErr = CE_None;
    2702                 : 
    2703                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKGeneralCase()\n"
    2704                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    2705                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    2706                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    2707                 :               poWK->nDstXOff, poWK->nDstYOff, 
    2708             386 :               poWK->nDstXSize, poWK->nDstYSize );
    2709                 : 
    2710             386 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    2711                 :     {
    2712               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    2713               0 :         return CE_Failure;
    2714                 :     }
    2715                 : 
    2716                 : /* -------------------------------------------------------------------- */
    2717                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    2718                 : /*      scanlines worth of positions.                                   */
    2719                 : /* -------------------------------------------------------------------- */
    2720                 :     double *padfX, *padfY, *padfZ;
    2721                 :     int    *pabSuccess;
    2722                 : 
    2723             386 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    2724             386 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    2725             386 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    2726             386 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    2727                 : 
    2728             386 :     GWKResampleWrkStruct* psWrkStruct = NULL;
    2729             386 :     if (poWK->eResample == GRA_CubicSpline
    2730                 :         || poWK->eResample == GRA_Lanczos )
    2731                 :     {
    2732             174 :         psWrkStruct = GWKResampleCreateWrkStruct(poWK);
    2733                 :     }
    2734                 : 
    2735                 : /* ==================================================================== */
    2736                 : /*      Loop over output lines.                                         */
    2737                 : /* ==================================================================== */
    2738            3834 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    2739                 :     {
    2740                 :         int iDstX;
    2741                 : 
    2742                 : /* -------------------------------------------------------------------- */
    2743                 : /*      Setup points to transform to source image space.                */
    2744                 : /* -------------------------------------------------------------------- */
    2745         1066344 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    2746                 :         {
    2747         1062896 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    2748         1062896 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    2749         1062896 :             padfZ[iDstX] = 0.0;
    2750                 :         }
    2751                 : 
    2752                 : /* -------------------------------------------------------------------- */
    2753                 : /*      Transform the points from destination pixel/line coordinates    */
    2754                 : /*      to source pixel/line coordinates.                               */
    2755                 : /* -------------------------------------------------------------------- */
    2756                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    2757            3448 :                               padfX, padfY, padfZ, pabSuccess );
    2758                 : 
    2759                 : /* ==================================================================== */
    2760                 : /*      Loop over pixels in output scanline.                            */
    2761                 : /* ==================================================================== */
    2762         1066344 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    2763                 :         {
    2764                 :             int iDstOffset;
    2765                 : 
    2766         1062896 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    2767                 : 
    2768                 : /* -------------------------------------------------------------------- */
    2769                 : /*      Do not try to apply transparent/invalid source pixels to the    */
    2770                 : /*      destination.  This currently ignores the multi-pixel input      */
    2771                 : /*      of bilinear and cubic resamples.                                */
    2772                 : /* -------------------------------------------------------------------- */
    2773          569814 :             double  dfDensity = 1.0;
    2774                 : 
    2775          569814 :             if( poWK->pafUnifiedSrcDensity != NULL 
    2776                 :                 && iSrcX >= 0 && iSrcY >= 0 
    2777                 :                 && iSrcX < nSrcXSize && iSrcY < nSrcYSize )
    2778                 :             {
    2779            2656 :                 dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
    2780            2656 :                 if( dfDensity < 0.00001 )
    2781            2598 :                     continue;
    2782                 :             }
    2783                 : 
    2784          567216 :             if( poWK->panUnifiedSrcValid != NULL
    2785                 :                 && iSrcX >= 0 && iSrcY >= 0 
    2786                 :                 && iSrcX < nSrcXSize && iSrcY < nSrcYSize 
    2787               0 :                 && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
    2788                 :                      & (0x01 << (iSrcOffset & 0x1f))) )
    2789               0 :                 continue;
    2790                 : 
    2791                 : /* ==================================================================== */
    2792                 : /*      Loop processing each band.                                      */
    2793                 : /* ==================================================================== */
    2794                 :             int iBand;
    2795          567216 :             int bHasFoundDensity = FALSE;
    2796                 :             
    2797          567216 :             iDstOffset = iDstX + iDstY * nDstXSize;
    2798         1146006 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    2799                 :             {
    2800          578790 :                 double dfBandDensity = 0.0;
    2801          578790 :                 double dfValueReal = 0.0;
    2802          578790 :                 double dfValueImag = 0.0;
    2803                 : 
    2804                 : /* -------------------------------------------------------------------- */
    2805                 : /*      Collect the source value.                                       */
    2806                 : /* -------------------------------------------------------------------- */
    2807          581348 :                 if ( poWK->eResample == GRA_NearestNeighbour ||
    2808                 :                      nSrcXSize == 1 || nSrcYSize == 1)
    2809                 :                 {
    2810                 :                     GWKGetPixelValue( poWK, iBand, iSrcOffset,
    2811            2558 :                                       &dfBandDensity, &dfValueReal, &dfValueImag );
    2812                 :                 }
    2813          576232 :                 else if ( poWK->eResample == GRA_Bilinear )
    2814                 :                 {
    2815                 :                     GWKBilinearResample( poWK, iBand, 
    2816           16348 :                                          padfX[iDstX]-poWK->nSrcXOff,
    2817           16348 :                                          padfY[iDstX]-poWK->nSrcYOff,
    2818                 :                                          &dfBandDensity, 
    2819           32696 :                                          &dfValueReal, &dfValueImag );
    2820                 :                 }
    2821          559884 :                 else if ( poWK->eResample == GRA_Cubic )
    2822                 :                 {
    2823                 :                     GWKCubicResample( poWK, iBand, 
    2824            1116 :                                       padfX[iDstX]-poWK->nSrcXOff,
    2825            1116 :                                       padfY[iDstX]-poWK->nSrcYOff,
    2826                 :                                       &dfBandDensity, 
    2827            2232 :                                       &dfValueReal, &dfValueImag );
    2828                 :                 }
    2829          558768 :                 else if ( poWK->eResample == GRA_CubicSpline
    2830                 :                           || poWK->eResample == GRA_Lanczos )
    2831                 :                 {
    2832                 :                     GWKResample( poWK, iBand, 
    2833          558768 :                                  padfX[iDstX]-poWK->nSrcXOff,
    2834          558768 :                                  padfY[iDstX]-poWK->nSrcYOff,
    2835                 :                                  &dfBandDensity, 
    2836         1117536 :                                  &dfValueReal, &dfValueImag, psWrkStruct );
    2837                 :                 }
    2838                 : 
    2839                 : 
    2840                 :                 // If we didn't find any valid inputs skip to next band.
    2841          578790 :                 if ( dfBandDensity < 0.0000000001 )
    2842               0 :                     continue;
    2843                 : 
    2844          578790 :                 bHasFoundDensity = TRUE;
    2845                 : 
    2846                 : /* -------------------------------------------------------------------- */
    2847                 : /*      We have a computed value from the source.  Now apply it to      */
    2848                 : /*      the destination pixel.                                          */
    2849                 : /* -------------------------------------------------------------------- */
    2850                 :                 GWKSetPixelValue( poWK, iBand, iDstOffset,
    2851                 :                                   dfBandDensity,
    2852          578790 :                                   dfValueReal, dfValueImag );
    2853                 : 
    2854                 :             }
    2855                 : 
    2856          567216 :             if (!bHasFoundDensity)
    2857               0 :               continue;
    2858                 : 
    2859                 : /* -------------------------------------------------------------------- */
    2860                 : /*      Update destination density/validity masks.                      */
    2861                 : /* -------------------------------------------------------------------- */
    2862          567216 :             GWKOverlayDensity( poWK, iDstOffset, dfDensity );
    2863                 : 
    2864          567216 :             if( poWK->panDstValid != NULL )
    2865                 :             {
    2866                 :                 poWK->panDstValid[iDstOffset>>5] |= 
    2867               0 :                     0x01 << (iDstOffset & 0x1f);
    2868                 :             }
    2869                 : 
    2870                 :         } /* Next iDstX */
    2871                 : 
    2872                 : /* -------------------------------------------------------------------- */
    2873                 : /*      Report progress to the user, and optionally cancel out.         */
    2874                 : /* -------------------------------------------------------------------- */
    2875            3448 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    2876                 :                                 ((iDstY+1) / (double) nDstYSize), 
    2877                 :                                 "", poWK->pProgress ) )
    2878                 :         {
    2879               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    2880               0 :             eErr = CE_Failure;
    2881                 :         }
    2882                 :     }
    2883                 : 
    2884                 : /* -------------------------------------------------------------------- */
    2885                 : /*      Cleanup and return.                                             */
    2886                 : /* -------------------------------------------------------------------- */
    2887             386 :     CPLFree( padfX );
    2888             386 :     CPLFree( padfY );
    2889             386 :     CPLFree( padfZ );
    2890             386 :     CPLFree( pabSuccess );
    2891             386 :     if (psWrkStruct)
    2892             174 :         GWKResampleDeleteWrkStruct(psWrkStruct);
    2893                 : 
    2894             386 :     return eErr;
    2895                 : }
    2896                 : 
    2897                 : /************************************************************************/
    2898                 : /*                       GWKNearestNoMasksByte()                        */
    2899                 : /*                                                                      */
    2900                 : /*      Case for 8bit input data with nearest neighbour resampling      */
    2901                 : /*      without concerning about masking. Should be as fast as          */
    2902                 : /*      possible for this particular transformation type.               */
    2903                 : /************************************************************************/
    2904                 : 
    2905             506 : static CPLErr GWKNearestNoMasksByte( GDALWarpKernel *poWK )
    2906                 : 
    2907                 : {
    2908                 :     int iDstY;
    2909             506 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    2910             506 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    2911             506 :     CPLErr eErr = CE_None;
    2912                 : 
    2913                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestNoMasksByte()\n"
    2914                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    2915                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    2916                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    2917                 :               poWK->nDstXOff, poWK->nDstYOff, 
    2918             506 :               poWK->nDstXSize, poWK->nDstYSize );
    2919                 : 
    2920             506 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    2921                 :     {
    2922               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    2923               0 :         return CE_Failure;
    2924                 :     }
    2925                 : 
    2926                 : /* -------------------------------------------------------------------- */
    2927                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    2928                 : /*      scanlines worth of positions.                                   */
    2929                 : /* -------------------------------------------------------------------- */
    2930                 :     double *padfX, *padfY, *padfZ;
    2931                 :     int    *pabSuccess;
    2932                 : 
    2933             506 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    2934             506 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    2935             506 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    2936             506 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    2937                 : 
    2938                 : /* ==================================================================== */
    2939                 : /*      Loop over output lines.                                         */
    2940                 : /* ==================================================================== */
    2941           61284 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    2942                 :     {
    2943                 :         int iDstX;
    2944                 : 
    2945                 : /* -------------------------------------------------------------------- */
    2946                 : /*      Setup points to transform to source image space.                */
    2947                 : /* -------------------------------------------------------------------- */
    2948        17292462 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    2949                 :         {
    2950        17231684 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    2951        17231684 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    2952        17231684 :             padfZ[iDstX] = 0.0;
    2953                 :         }
    2954                 : 
    2955                 : /* -------------------------------------------------------------------- */
    2956                 : /*      Transform the points from destination pixel/line coordinates    */
    2957                 : /*      to source pixel/line coordinates.                               */
    2958                 : /* -------------------------------------------------------------------- */
    2959                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    2960           60778 :                               padfX, padfY, padfZ, pabSuccess );
    2961                 : 
    2962                 : /* ==================================================================== */
    2963                 : /*      Loop over pixels in output scanline.                            */
    2964                 : /* ==================================================================== */
    2965        17292462 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    2966                 :         {
    2967        17231684 :             if( !pabSuccess[iDstX] )
    2968          307338 :                 continue;
    2969                 : 
    2970        16924346 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    2971                 : 
    2972                 : /* ==================================================================== */
    2973                 : /*      Loop processing each band.                                      */
    2974                 : /* ==================================================================== */
    2975                 :             int iBand;
    2976                 :             int iDstOffset;
    2977                 : 
    2978        16662326 :             iDstOffset = iDstX + iDstY * nDstXSize;
    2979                 : 
    2980        40501740 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    2981                 :             {
    2982        23839414 :                 poWK->papabyDstImage[iBand][iDstOffset] = 
    2983        23839414 :                     poWK->papabySrcImage[iBand][iSrcOffset];
    2984                 :             }
    2985                 :         }
    2986                 : 
    2987                 : /* -------------------------------------------------------------------- */
    2988                 : /*      Report progress to the user, and optionally cancel out.         */
    2989                 : /* -------------------------------------------------------------------- */
    2990           60778 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    2991                 :                                 ((iDstY+1) / (double) nDstYSize), 
    2992                 :                                 "", poWK->pProgress ) )
    2993                 :         {
    2994               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    2995               0 :             eErr = CE_Failure;
    2996                 :         }
    2997                 :     }
    2998                 : 
    2999                 : /* -------------------------------------------------------------------- */
    3000                 : /*      Cleanup and return.                                             */
    3001                 : /* -------------------------------------------------------------------- */
    3002             506 :     CPLFree( padfX );
    3003             506 :     CPLFree( padfY );
    3004             506 :     CPLFree( padfZ );
    3005             506 :     CPLFree( pabSuccess );
    3006                 : 
    3007             506 :     return eErr;
    3008                 : }
    3009                 : 
    3010                 : /************************************************************************/
    3011                 : /*                       GWKBilinearNoMasksByte()                       */
    3012                 : /*                                                                      */
    3013                 : /*      Case for 8bit input data with bilinear resampling without       */
    3014                 : /*      concerning about masking. Should be as fast as possible         */
    3015                 : /*      for this particular transformation type.                        */
    3016                 : /************************************************************************/
    3017                 : 
    3018              28 : static CPLErr GWKBilinearNoMasksByte( GDALWarpKernel *poWK )
    3019                 : 
    3020                 : {
    3021                 :     int iDstY;
    3022              28 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    3023              28 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    3024              28 :     CPLErr eErr = CE_None;
    3025                 : 
    3026                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKBilinearNoMasksByte()\n"
    3027                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    3028                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    3029                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    3030                 :               poWK->nDstXOff, poWK->nDstYOff, 
    3031              28 :               poWK->nDstXSize, poWK->nDstYSize );
    3032                 : 
    3033              28 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    3034                 :     {
    3035               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3036               0 :         return CE_Failure;
    3037                 :     }
    3038                 : 
    3039                 : /* -------------------------------------------------------------------- */
    3040                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    3041                 : /*      scanlines worth of positions.                                   */
    3042                 : /* -------------------------------------------------------------------- */
    3043                 :     double *padfX, *padfY, *padfZ;
    3044                 :     int    *pabSuccess;
    3045                 : 
    3046              28 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3047              28 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3048              28 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3049              28 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    3050                 : 
    3051                 : /* ==================================================================== */
    3052                 : /*      Loop over output lines.                                         */
    3053                 : /* ==================================================================== */
    3054            1516 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    3055                 :     {
    3056                 :         int iDstX;
    3057                 : 
    3058                 : /* -------------------------------------------------------------------- */
    3059                 : /*      Setup points to transform to source image space.                */
    3060                 : /* -------------------------------------------------------------------- */
    3061          662008 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3062                 :         {
    3063          660520 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    3064          660520 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    3065          660520 :             padfZ[iDstX] = 0.0;
    3066                 :         }
    3067                 : 
    3068                 : /* -------------------------------------------------------------------- */
    3069                 : /*      Transform the points from destination pixel/line coordinates    */
    3070                 : /*      to source pixel/line coordinates.                               */
    3071                 : /* -------------------------------------------------------------------- */
    3072                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    3073            1488 :                               padfX, padfY, padfZ, pabSuccess );
    3074                 : 
    3075                 : /* ==================================================================== */
    3076                 : /*      Loop over pixels in output scanline.                            */
    3077                 : /* ==================================================================== */
    3078          662008 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3079                 :         {
    3080          660520 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    3081                 : 
    3082                 : /* ==================================================================== */
    3083                 : /*      Loop processing each band.                                      */
    3084                 : /* ==================================================================== */
    3085                 :             int iBand;
    3086                 :             int iDstOffset;
    3087                 : 
    3088          558248 :             iDstOffset = iDstX + iDstY * nDstXSize;
    3089                 : 
    3090         1116496 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    3091                 :             {
    3092                 :                 GWKBilinearResampleNoMasksByte( poWK, iBand,
    3093          558248 :                                                 padfX[iDstX]-poWK->nSrcXOff,
    3094          558248 :                                                 padfY[iDstX]-poWK->nSrcYOff,
    3095         1674744 :                                                 &poWK->papabyDstImage[iBand][iDstOffset] );
    3096                 :             }
    3097                 :         }
    3098                 : 
    3099                 : /* -------------------------------------------------------------------- */
    3100                 : /*      Report progress to the user, and optionally cancel out.         */
    3101                 : /* -------------------------------------------------------------------- */
    3102            1488 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    3103                 :                                 ((iDstY+1) / (double) nDstYSize), 
    3104                 :                                 "", poWK->pProgress ) )
    3105                 :         {
    3106               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3107               0 :             eErr = CE_Failure;
    3108                 :         }
    3109                 :     }
    3110                 : 
    3111                 : /* -------------------------------------------------------------------- */
    3112                 : /*      Cleanup and return.                                             */
    3113                 : /* -------------------------------------------------------------------- */
    3114              28 :     CPLFree( padfX );
    3115              28 :     CPLFree( padfY );
    3116              28 :     CPLFree( padfZ );
    3117              28 :     CPLFree( pabSuccess );
    3118                 : 
    3119              28 :     return eErr;
    3120                 : }
    3121                 : 
    3122                 : /************************************************************************/
    3123                 : /*                       GWKCubicNoMasksByte()                          */
    3124                 : /*                                                                      */
    3125                 : /*      Case for 8bit input data with cubic resampling without          */
    3126                 : /*      concerning about masking. Should be as fast as possible         */
    3127                 : /*      for this particular transformation type.                        */
    3128                 : /************************************************************************/
    3129                 : 
    3130              20 : static CPLErr GWKCubicNoMasksByte( GDALWarpKernel *poWK )
    3131                 : 
    3132                 : {
    3133                 :     int iDstY;
    3134              20 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    3135              20 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    3136              20 :     CPLErr eErr = CE_None;
    3137                 : 
    3138                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKCubicNoMasksByte()\n"
    3139                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    3140                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    3141                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    3142                 :               poWK->nDstXOff, poWK->nDstYOff, 
    3143              20 :               poWK->nDstXSize, poWK->nDstYSize );
    3144                 : 
    3145              20 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    3146                 :     {
    3147               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3148               0 :         return CE_Failure;
    3149                 :     }
    3150                 : 
    3151                 : /* -------------------------------------------------------------------- */
    3152                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    3153                 : /*      scanlines worth of positions.                                   */
    3154                 : /* -------------------------------------------------------------------- */
    3155                 :     double *padfX, *padfY, *padfZ;
    3156                 :     int    *pabSuccess;
    3157                 : 
    3158              20 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3159              20 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3160              20 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3161              20 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    3162                 : 
    3163                 : /* ==================================================================== */
    3164                 : /*      Loop over output lines.                                         */
    3165                 : /* ==================================================================== */
    3166            1406 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    3167                 :     {
    3168                 :         int iDstX;
    3169                 : 
    3170                 : /* -------------------------------------------------------------------- */
    3171                 : /*      Setup points to transform to source image space.                */
    3172                 : /* -------------------------------------------------------------------- */
    3173          660072 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3174                 :         {
    3175          658686 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    3176          658686 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    3177          658686 :             padfZ[iDstX] = 0.0;
    3178                 :         }
    3179                 : 
    3180                 : /* -------------------------------------------------------------------- */
    3181                 : /*      Transform the points from destination pixel/line coordinates    */
    3182                 : /*      to source pixel/line coordinates.                               */
    3183                 : /* -------------------------------------------------------------------- */
    3184                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    3185            1386 :                               padfX, padfY, padfZ, pabSuccess );
    3186                 : 
    3187                 : /* ==================================================================== */
    3188                 : /*      Loop over pixels in output scanline.                            */
    3189                 : /* ==================================================================== */
    3190          660072 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3191                 :         {
    3192          658686 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    3193                 : 
    3194                 : /* ==================================================================== */
    3195                 : /*      Loop processing each band.                                      */
    3196                 : /* ==================================================================== */
    3197                 :             int iBand;
    3198                 :             int iDstOffset;
    3199                 : 
    3200          556414 :             iDstOffset = iDstX + iDstY * nDstXSize;
    3201                 : 
    3202         1112828 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    3203                 :             {
    3204                 :                 GWKCubicResampleNoMasksByte( poWK, iBand,
    3205          556414 :                                              padfX[iDstX]-poWK->nSrcXOff,
    3206          556414 :                                              padfY[iDstX]-poWK->nSrcYOff,
    3207         1669242 :                                              &poWK->papabyDstImage[iBand][iDstOffset] );
    3208                 :             }
    3209                 :         }
    3210                 : 
    3211                 : /* -------------------------------------------------------------------- */
    3212                 : /*      Report progress to the user, and optionally cancel out.         */
    3213                 : /* -------------------------------------------------------------------- */
    3214            1386 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    3215                 :                                 ((iDstY+1) / (double) nDstYSize), 
    3216                 :                                 "", poWK->pProgress ) )
    3217                 :         {
    3218               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3219               0 :             eErr = CE_Failure;
    3220                 :         }
    3221                 :     }
    3222                 : 
    3223                 : /* -------------------------------------------------------------------- */
    3224                 : /*      Cleanup and return.                                             */
    3225                 : /* -------------------------------------------------------------------- */
    3226              20 :     CPLFree( padfX );
    3227              20 :     CPLFree( padfY );
    3228              20 :     CPLFree( padfZ );
    3229              20 :     CPLFree( pabSuccess );
    3230                 : 
    3231              20 :     return eErr;
    3232                 : }
    3233                 : 
    3234                 : /************************************************************************/
    3235                 : /*                   GWKCubicSplineNoMasksByte()                        */
    3236                 : /*                                                                      */
    3237                 : /*      Case for 8bit input data with cubic spline resampling without   */
    3238                 : /*      concerning about masking. Should be as fast as possible         */
    3239                 : /*      for this particular transformation type.                        */
    3240                 : /************************************************************************/
    3241                 : 
    3242              20 : static CPLErr GWKCubicSplineNoMasksByte( GDALWarpKernel *poWK )
    3243                 : 
    3244                 : {
    3245                 :     int iDstY;
    3246              20 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    3247              20 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    3248              20 :     CPLErr eErr = CE_None;
    3249                 : 
    3250                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKCubicSplineNoMasksByte()\n"
    3251                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    3252                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    3253                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    3254                 :               poWK->nDstXOff, poWK->nDstYOff, 
    3255              20 :               poWK->nDstXSize, poWK->nDstYSize );
    3256                 : 
    3257              20 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    3258                 :     {
    3259               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3260               0 :         return CE_Failure;
    3261                 :     }
    3262                 : 
    3263                 : /* -------------------------------------------------------------------- */
    3264                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    3265                 : /*      scanlines worth of positions.                                   */
    3266                 : /* -------------------------------------------------------------------- */
    3267                 :     double *padfX, *padfY, *padfZ;
    3268                 :     int    *pabSuccess;
    3269                 : 
    3270              20 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3271              20 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3272              20 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3273              20 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    3274                 : 
    3275              20 :     int     nXRadius = poWK->nXRadius;
    3276              20 :     double  *padfBSpline = (double *)CPLCalloc( nXRadius * 2, sizeof(double) );
    3277                 : 
    3278                 : /* ==================================================================== */
    3279                 : /*      Loop over output lines.                                         */
    3280                 : /* ==================================================================== */
    3281            1406 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    3282                 :     {
    3283                 :         int iDstX;
    3284                 : 
    3285                 : /* -------------------------------------------------------------------- */
    3286                 : /*      Setup points to transform to source image space.                */
    3287                 : /* -------------------------------------------------------------------- */
    3288          660072 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3289                 :         {
    3290          658686 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    3291          658686 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    3292          658686 :             padfZ[iDstX] = 0.0;
    3293                 :         }
    3294                 : 
    3295                 : /* -------------------------------------------------------------------- */
    3296                 : /*      Transform the points from destination pixel/line coordinates    */
    3297                 : /*      to source pixel/line coordinates.                               */
    3298                 : /* -------------------------------------------------------------------- */
    3299                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    3300            1386 :                               padfX, padfY, padfZ, pabSuccess );
    3301                 : 
    3302                 : /* ==================================================================== */
    3303                 : /*      Loop over pixels in output scanline.                            */
    3304                 : /* ==================================================================== */
    3305          660072 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3306                 :         {
    3307          658686 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    3308                 : 
    3309                 : /* ==================================================================== */
    3310                 : /*      Loop processing each band.                                      */
    3311                 : /* ==================================================================== */
    3312                 :             int iBand;
    3313                 :             int iDstOffset;
    3314                 : 
    3315          556414 :             iDstOffset = iDstX + iDstY * nDstXSize;
    3316                 : 
    3317         1112828 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    3318                 :             {
    3319                 :                 GWKCubicSplineResampleNoMasksByte( poWK, iBand,
    3320          556414 :                                                    padfX[iDstX]-poWK->nSrcXOff,
    3321          556414 :                                                    padfY[iDstX]-poWK->nSrcYOff,
    3322          556414 :                                                    &poWK->papabyDstImage[iBand][iDstOffset],
    3323         1669242 :                                                    padfBSpline);
    3324                 :             }
    3325                 :         }
    3326                 : 
    3327                 : /* -------------------------------------------------------------------- */
    3328                 : /*      Report progress to the user, and optionally cancel out.         */
    3329                 : /* -------------------------------------------------------------------- */
    3330            1386 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    3331                 :                                 ((iDstY+1) / (double) nDstYSize), 
    3332                 :                                 "", poWK->pProgress ) )
    3333                 :         {
    3334               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3335               0 :             eErr = CE_Failure;
    3336                 :         }
    3337                 :     }
    3338                 : 
    3339                 : /* -------------------------------------------------------------------- */
    3340                 : /*      Cleanup and return.                                             */
    3341                 : /* -------------------------------------------------------------------- */
    3342              20 :     CPLFree( padfX );
    3343              20 :     CPLFree( padfY );
    3344              20 :     CPLFree( padfZ );
    3345              20 :     CPLFree( pabSuccess );
    3346              20 :     CPLFree( padfBSpline );
    3347                 : 
    3348              20 :     return eErr;
    3349                 : }
    3350                 : 
    3351                 : /************************************************************************/
    3352                 : /*                          GWKNearestByte()                            */
    3353                 : /*                                                                      */
    3354                 : /*      Case for 8bit input data with nearest neighbour resampling      */
    3355                 : /*      using valid flags. Should be as fast as possible for this       */
    3356                 : /*      particular transformation type.                                 */
    3357                 : /************************************************************************/
    3358                 : 
    3359              50 : static CPLErr GWKNearestByte( GDALWarpKernel *poWK )
    3360                 : 
    3361                 : {
    3362                 :     int iDstY;
    3363              50 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    3364              50 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    3365              50 :     CPLErr eErr = CE_None;
    3366                 : 
    3367                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestByte()\n"
    3368                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    3369                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    3370                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    3371                 :               poWK->nDstXOff, poWK->nDstYOff, 
    3372              50 :               poWK->nDstXSize, poWK->nDstYSize );
    3373                 : 
    3374              50 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    3375                 :     {
    3376               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3377               0 :         return CE_Failure;
    3378                 :     }
    3379                 : 
    3380                 : /* -------------------------------------------------------------------- */
    3381                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    3382                 : /*      scanlines worth of positions.                                   */
    3383                 : /* -------------------------------------------------------------------- */
    3384                 :     double *padfX, *padfY, *padfZ;
    3385                 :     int    *pabSuccess;
    3386                 : 
    3387              50 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3388              50 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3389              50 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3390              50 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    3391                 : 
    3392                 : /* ==================================================================== */
    3393                 : /*      Loop over output lines.                                         */
    3394                 : /* ==================================================================== */
    3395            6362 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    3396                 :     {
    3397                 :         int iDstX;
    3398                 : 
    3399                 : /* -------------------------------------------------------------------- */
    3400                 : /*      Setup points to transform to source image space.                */
    3401                 : /* -------------------------------------------------------------------- */
    3402         2805644 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3403                 :         {
    3404         2799332 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    3405         2799332 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    3406         2799332 :             padfZ[iDstX] = 0.0;
    3407                 :         }
    3408                 : 
    3409                 : /* -------------------------------------------------------------------- */
    3410                 : /*      Transform the points from destination pixel/line coordinates    */
    3411                 : /*      to source pixel/line coordinates.                               */
    3412                 : /* -------------------------------------------------------------------- */
    3413                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    3414            6312 :                               padfX, padfY, padfZ, pabSuccess );
    3415                 : 
    3416                 : /* ==================================================================== */
    3417                 : /*      Loop over pixels in output scanline.                            */
    3418                 : /* ==================================================================== */
    3419         2805644 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3420                 :         {
    3421                 :             int iDstOffset;
    3422                 : 
    3423         2799332 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    3424                 : 
    3425                 : /* -------------------------------------------------------------------- */
    3426                 : /*      Do not try to apply invalid source pixels to the dest.          */
    3427                 : /* -------------------------------------------------------------------- */
    3428         1458294 :             if( poWK->panUnifiedSrcValid != NULL
    3429          314956 :                 && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
    3430                 :                      & (0x01 << (iSrcOffset & 0x1f))) )
    3431           64598 :                 continue;
    3432                 : 
    3433                 : /* -------------------------------------------------------------------- */
    3434                 : /*      Do not try to apply transparent source pixels to the destination.*/
    3435                 : /* -------------------------------------------------------------------- */
    3436         1078740 :             double  dfDensity = 1.0;
    3437                 : 
    3438         1078740 :             if( poWK->pafUnifiedSrcDensity != NULL )
    3439                 :             {
    3440          180000 :                 dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
    3441          180000 :                 if( dfDensity < 0.00001 )
    3442          149794 :                     continue;
    3443                 :             }
    3444                 : 
    3445                 : /* ==================================================================== */
    3446                 : /*      Loop processing each band.                                      */
    3447                 : /* ==================================================================== */
    3448                 :             int iBand;
    3449                 : 
    3450          928946 :             iDstOffset = iDstX + iDstY * nDstXSize;
    3451                 : 
    3452         2377404 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    3453                 :             {
    3454         1448458 :                 GByte   bValue = 0;
    3455         1448458 :                 double dfBandDensity = 0.0;
    3456                 : 
    3457                 : /* -------------------------------------------------------------------- */
    3458                 : /*      Collect the source value.                                       */
    3459                 : /* -------------------------------------------------------------------- */
    3460         1448458 :                 if ( GWKGetPixelByte( poWK, iBand, iSrcOffset, &dfBandDensity,
    3461                 :                                       &bValue ) )
    3462                 :                 {
    3463         1448458 :                     if( dfBandDensity < 1.0 )
    3464                 :                     {
    3465            2944 :                         if( dfBandDensity == 0.0 )
    3466                 :                             /* do nothing */;
    3467                 :                         else
    3468                 :                         {
    3469                 :                             /* let the general code take care of mixing */
    3470                 :                             GWKSetPixelValue( poWK, iBand, iDstOffset, 
    3471                 :                                               dfBandDensity, (double) bValue, 
    3472            2944 :                                               0.0 );
    3473                 :                         }
    3474                 :                     }
    3475                 :                     else
    3476                 :                     {
    3477         1445514 :                         poWK->papabyDstImage[iBand][iDstOffset] = bValue;
    3478                 :                     }
    3479                 :                 }
    3480                 :             }
    3481                 : 
    3482                 : /* -------------------------------------------------------------------- */
    3483                 : /*      Mark this pixel valid/opaque in the output.                     */
    3484                 : /* -------------------------------------------------------------------- */
    3485          928946 :             GWKOverlayDensity( poWK, iDstOffset, dfDensity );
    3486                 : 
    3487          928946 :             if( poWK->panDstValid != NULL )
    3488                 :             {
    3489                 :                 poWK->panDstValid[iDstOffset>>5] |= 
    3490            1404 :                     0x01 << (iDstOffset & 0x1f);
    3491                 :             }
    3492                 :         } /* Next iDstX */
    3493                 : 
    3494                 : /* -------------------------------------------------------------------- */
    3495                 : /*      Report progress to the user, and optionally cancel out.         */
    3496                 : /* -------------------------------------------------------------------- */
    3497            6312 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    3498                 :                                 ((iDstY+1) / (double) nDstYSize), 
    3499                 :                                 "", poWK->pProgress ) )
    3500                 :         {
    3501               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3502               0 :             eErr = CE_Failure;
    3503                 :         }
    3504                 :     } /* Next iDstY */
    3505                 : 
    3506                 : /* -------------------------------------------------------------------- */
    3507                 : /*      Cleanup and return.                                             */
    3508                 : /* -------------------------------------------------------------------- */
    3509              50 :     CPLFree( padfX );
    3510              50 :     CPLFree( padfY );
    3511              50 :     CPLFree( padfZ );
    3512              50 :     CPLFree( pabSuccess );
    3513                 : 
    3514              50 :     return eErr;
    3515                 : }
    3516                 : 
    3517                 : /************************************************************************/
    3518                 : /*                    GWKNearestNoMasksShort()                          */
    3519                 : /*                                                                      */
    3520                 : /*      Case for 16bit signed and unsigned integer input data with      */
    3521                 : /*      nearest neighbour resampling without concerning about masking.  */
    3522                 : /*      Should be as fast as possible for this particular               */
    3523                 : /*      transformation type.                                            */
    3524                 : /************************************************************************/
    3525                 : 
    3526              28 : static CPLErr GWKNearestNoMasksShort( GDALWarpKernel *poWK )
    3527                 : 
    3528                 : {
    3529                 :     int iDstY;
    3530              28 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    3531              28 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    3532              28 :     CPLErr eErr = CE_None;
    3533                 : 
    3534                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestNoMasksShort()\n"
    3535                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    3536                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    3537                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    3538                 :               poWK->nDstXOff, poWK->nDstYOff, 
    3539              28 :               poWK->nDstXSize, poWK->nDstYSize );
    3540                 : 
    3541              28 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    3542                 :     {
    3543               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3544               0 :         return CE_Failure;
    3545                 :     }
    3546                 : 
    3547                 : /* -------------------------------------------------------------------- */
    3548                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    3549                 : /*      scanlines worth of positions.                                   */
    3550                 : /* -------------------------------------------------------------------- */
    3551                 :     double *padfX, *padfY, *padfZ;
    3552                 :     int    *pabSuccess;
    3553                 : 
    3554              28 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3555              28 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3556              28 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3557              28 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    3558                 : 
    3559                 : /* ==================================================================== */
    3560                 : /*      Loop over output lines.                                         */
    3561                 : /* ==================================================================== */
    3562            1400 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    3563                 :     {
    3564                 :         int iDstX;
    3565                 : 
    3566                 : /* -------------------------------------------------------------------- */
    3567                 : /*      Setup points to transform to source image space.                */
    3568                 : /* -------------------------------------------------------------------- */
    3569          657784 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3570                 :         {
    3571          656412 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    3572          656412 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    3573          656412 :             padfZ[iDstX] = 0.0;
    3574                 :         }
    3575                 : 
    3576                 : /* -------------------------------------------------------------------- */
    3577                 : /*      Transform the points from destination pixel/line coordinates    */
    3578                 : /*      to source pixel/line coordinates.                               */
    3579                 : /* -------------------------------------------------------------------- */
    3580                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    3581            1372 :                               padfX, padfY, padfZ, pabSuccess );
    3582                 : 
    3583                 : /* ==================================================================== */
    3584                 : /*      Loop over pixels in output scanline.                            */
    3585                 : /* ==================================================================== */
    3586          657784 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3587                 :         {
    3588                 :             int iDstOffset;
    3589                 : 
    3590          656412 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    3591                 : 
    3592                 : /* ==================================================================== */
    3593                 : /*      Loop processing each band.                                      */
    3594                 : /* ==================================================================== */
    3595                 :             int iBand;
    3596                 :             
    3597          529896 :             iDstOffset = iDstX + iDstY * nDstXSize;
    3598                 : 
    3599         1059792 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    3600                 :             {
    3601          529896 :                 ((GInt16 *)poWK->papabyDstImage[iBand])[iDstOffset] = 
    3602          529896 :                     ((GInt16 *)poWK->papabySrcImage[iBand])[iSrcOffset];
    3603                 :             }
    3604                 :         }
    3605                 : 
    3606                 : /* -------------------------------------------------------------------- */
    3607                 : /*      Report progress to the user, and optionally cancel out.         */
    3608                 : /* -------------------------------------------------------------------- */
    3609            1372 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    3610                 :                                 ((iDstY+1) / (double) nDstYSize), 
    3611                 :                                 "", poWK->pProgress ) )
    3612                 :         {
    3613               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3614               0 :             eErr = CE_Failure;
    3615                 :         }
    3616                 :     }
    3617                 : 
    3618                 : /* -------------------------------------------------------------------- */
    3619                 : /*      Cleanup and return.                                             */
    3620                 : /* -------------------------------------------------------------------- */
    3621              28 :     CPLFree( padfX );
    3622              28 :     CPLFree( padfY );
    3623              28 :     CPLFree( padfZ );
    3624              28 :     CPLFree( pabSuccess );
    3625                 : 
    3626              28 :     return eErr;
    3627                 : }
    3628                 : 
    3629                 : /************************************************************************/
    3630                 : /*                       GWKBilinearNoMasksShort()                      */
    3631                 : /*                                                                      */
    3632                 : /*      Case for 16bit input data with cubic resampling without         */
    3633                 : /*      concerning about masking. Should be as fast as possible         */
    3634                 : /*      for this particular transformation type.                        */
    3635                 : /************************************************************************/
    3636                 : 
    3637              40 : static CPLErr GWKBilinearNoMasksShort( GDALWarpKernel *poWK )
    3638                 : 
    3639                 : {
    3640                 :     int iDstY;
    3641              40 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    3642              40 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    3643              40 :     CPLErr eErr = CE_None;
    3644                 : 
    3645                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKBilinearNoMasksShort()\n"
    3646                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    3647                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    3648                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    3649                 :               poWK->nDstXOff, poWK->nDstYOff, 
    3650              40 :               poWK->nDstXSize, poWK->nDstYSize );
    3651                 : 
    3652              40 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    3653                 :     {
    3654               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3655               0 :         return CE_Failure;
    3656                 :     }
    3657                 : 
    3658                 : /* -------------------------------------------------------------------- */
    3659                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    3660                 : /*      scanlines worth of positions.                                   */
    3661                 : /* -------------------------------------------------------------------- */
    3662                 :     double *padfX, *padfY, *padfZ;
    3663                 :     int    *pabSuccess;
    3664                 : 
    3665              40 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3666              40 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3667              40 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3668              40 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    3669                 : 
    3670                 : /* ==================================================================== */
    3671                 : /*      Loop over output lines.                                         */
    3672                 : /* ==================================================================== */
    3673            3712 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    3674                 :     {
    3675                 :         int iDstX;
    3676                 : 
    3677                 : /* -------------------------------------------------------------------- */
    3678                 : /*      Setup points to transform to source image space.                */
    3679                 : /* -------------------------------------------------------------------- */
    3680         3415088 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3681                 :         {
    3682         3411416 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    3683         3411416 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    3684         3411416 :             padfZ[iDstX] = 0.0;
    3685                 :         }
    3686                 : 
    3687                 : /* -------------------------------------------------------------------- */
    3688                 : /*      Transform the points from destination pixel/line coordinates    */
    3689                 : /*      to source pixel/line coordinates.                               */
    3690                 : /* -------------------------------------------------------------------- */
    3691                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    3692            3672 :                               padfX, padfY, padfZ, pabSuccess );
    3693                 : 
    3694                 : /* ==================================================================== */
    3695                 : /*      Loop over pixels in output scanline.                            */
    3696                 : /* ==================================================================== */
    3697         3415088 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3698                 :         {
    3699         3411416 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    3700                 : 
    3701                 : /* ==================================================================== */
    3702                 : /*      Loop processing each band.                                      */
    3703                 : /* ==================================================================== */
    3704                 :             int iBand;
    3705                 :             int iDstOffset;
    3706                 : 
    3707         3411416 :             iDstOffset = iDstX + iDstY * nDstXSize;
    3708                 : 
    3709         6822832 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    3710                 :             {
    3711         3411416 :                 GInt16  iValue = 0;
    3712                 :                 GWKBilinearResampleNoMasksShort( poWK, iBand,
    3713         3411416 :                                                  padfX[iDstX]-poWK->nSrcXOff,
    3714         3411416 :                                                  padfY[iDstX]-poWK->nSrcYOff,
    3715         6822832 :                                                  &iValue );
    3716         3411416 :                 ((GInt16 *)poWK->papabyDstImage[iBand])[iDstOffset] = iValue;
    3717                 :             }
    3718                 :         }
    3719                 : 
    3720                 : /* -------------------------------------------------------------------- */
    3721                 : /*      Report progress to the user, and optionally cancel out.         */
    3722                 : /* -------------------------------------------------------------------- */
    3723            3672 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    3724                 :                                 ((iDstY+1) / (double) nDstYSize), 
    3725                 :                                 "", poWK->pProgress ) )
    3726                 :         {
    3727               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3728               0 :             eErr = CE_Failure;
    3729                 :         }
    3730                 :     }
    3731                 : 
    3732                 : /* -------------------------------------------------------------------- */
    3733                 : /*      Cleanup and return.                                             */
    3734                 : /* -------------------------------------------------------------------- */
    3735              40 :     CPLFree( padfX );
    3736              40 :     CPLFree( padfY );
    3737              40 :     CPLFree( padfZ );
    3738              40 :     CPLFree( pabSuccess );
    3739                 : 
    3740              40 :     return eErr;
    3741                 : }
    3742                 : 
    3743                 : /************************************************************************/
    3744                 : /*                       GWKCubicNoMasksShort()                         */
    3745                 : /*                                                                      */
    3746                 : /*      Case for 16bit input data with cubic resampling without         */
    3747                 : /*      concerning about masking. Should be as fast as possible         */
    3748                 : /*      for this particular transformation type.                        */
    3749                 : /************************************************************************/
    3750                 : 
    3751              16 : static CPLErr GWKCubicNoMasksShort( GDALWarpKernel *poWK )
    3752                 : 
    3753                 : {
    3754                 :     int iDstY;
    3755              16 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    3756              16 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    3757              16 :     CPLErr eErr = CE_None;
    3758                 : 
    3759                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKCubicNoMasksShort()\n"
    3760                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    3761                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    3762                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    3763                 :               poWK->nDstXOff, poWK->nDstYOff, 
    3764              16 :               poWK->nDstXSize, poWK->nDstYSize );
    3765                 : 
    3766              16 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    3767                 :     {
    3768               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3769               0 :         return CE_Failure;
    3770                 :     }
    3771                 : 
    3772                 : /* -------------------------------------------------------------------- */
    3773                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    3774                 : /*      scanlines worth of positions.                                   */
    3775                 : /* -------------------------------------------------------------------- */
    3776                 :     double *padfX, *padfY, *padfZ;
    3777                 :     int    *pabSuccess;
    3778                 : 
    3779              16 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3780              16 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3781              16 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3782              16 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    3783                 : 
    3784                 : /* ==================================================================== */
    3785                 : /*      Loop over output lines.                                         */
    3786                 : /* ==================================================================== */
    3787            1066 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    3788                 :     {
    3789                 :         int iDstX;
    3790                 : 
    3791                 : /* -------------------------------------------------------------------- */
    3792                 : /*      Setup points to transform to source image space.                */
    3793                 : /* -------------------------------------------------------------------- */
    3794          525464 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3795                 :         {
    3796          524414 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    3797          524414 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    3798          524414 :             padfZ[iDstX] = 0.0;
    3799                 :         }
    3800                 : 
    3801                 : /* -------------------------------------------------------------------- */
    3802                 : /*      Transform the points from destination pixel/line coordinates    */
    3803                 : /*      to source pixel/line coordinates.                               */
    3804                 : /* -------------------------------------------------------------------- */
    3805                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    3806            1050 :                               padfX, padfY, padfZ, pabSuccess );
    3807                 : 
    3808                 : /* ==================================================================== */
    3809                 : /*      Loop over pixels in output scanline.                            */
    3810                 : /* ==================================================================== */
    3811          525464 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3812                 :         {
    3813          524414 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    3814                 : 
    3815                 : /* ==================================================================== */
    3816                 : /*      Loop processing each band.                                      */
    3817                 : /* ==================================================================== */
    3818                 :             int iBand;
    3819                 :             int iDstOffset;
    3820                 : 
    3821          524414 :             iDstOffset = iDstX + iDstY * nDstXSize;
    3822                 : 
    3823         1048828 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    3824                 :             {
    3825          524414 :                 GInt16  iValue = 0;
    3826                 :                 GWKCubicResampleNoMasksShort( poWK, iBand,
    3827          524414 :                                               padfX[iDstX]-poWK->nSrcXOff,
    3828          524414 :                                               padfY[iDstX]-poWK->nSrcYOff,
    3829         1048828 :                                               &iValue );
    3830          524414 :                 ((GInt16 *)poWK->papabyDstImage[iBand])[iDstOffset] = iValue;
    3831                 :             }
    3832                 :         }
    3833                 : 
    3834                 : /* -------------------------------------------------------------------- */
    3835                 : /*      Report progress to the user, and optionally cancel out.         */
    3836                 : /* -------------------------------------------------------------------- */
    3837            1050 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    3838                 :                                 ((iDstY+1) / (double) nDstYSize), 
    3839                 :                                 "", poWK->pProgress ) )
    3840                 :         {
    3841               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3842               0 :             eErr = CE_Failure;
    3843                 :         }
    3844                 :     }
    3845                 : 
    3846                 : /* -------------------------------------------------------------------- */
    3847                 : /*      Cleanup and return.                                             */
    3848                 : /* -------------------------------------------------------------------- */
    3849              16 :     CPLFree( padfX );
    3850              16 :     CPLFree( padfY );
    3851              16 :     CPLFree( padfZ );
    3852              16 :     CPLFree( pabSuccess );
    3853                 : 
    3854              16 :     return eErr;
    3855                 : }
    3856                 : 
    3857                 : /************************************************************************/
    3858                 : /*                    GWKCubicSplineNoMasksShort()                      */
    3859                 : /*                                                                      */
    3860                 : /*      Case for 16bit input data with cubic resampling without         */
    3861                 : /*      concerning about masking. Should be as fast as possible         */
    3862                 : /*      for this particular transformation type.                        */
    3863                 : /************************************************************************/
    3864                 : 
    3865              16 : static CPLErr GWKCubicSplineNoMasksShort( GDALWarpKernel *poWK )
    3866                 : 
    3867                 : {
    3868                 :     int iDstY;
    3869              16 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    3870              16 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    3871              16 :     CPLErr eErr = CE_None;
    3872                 : 
    3873                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKCubicSplineNoMasksShort()\n"
    3874                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    3875                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    3876                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    3877                 :               poWK->nDstXOff, poWK->nDstYOff, 
    3878              16 :               poWK->nDstXSize, poWK->nDstYSize );
    3879                 : 
    3880              16 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    3881                 :     {
    3882               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3883               0 :         return CE_Failure;
    3884                 :     }
    3885                 : 
    3886                 : /* -------------------------------------------------------------------- */
    3887                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    3888                 : /*      scanlines worth of positions.                                   */
    3889                 : /* -------------------------------------------------------------------- */
    3890                 :     double *padfX, *padfY, *padfZ;
    3891                 :     int    *pabSuccess;
    3892                 : 
    3893              16 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3894              16 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3895              16 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    3896              16 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    3897                 : 
    3898              16 :     int     nXRadius = poWK->nXRadius;
    3899                 :     // Make space to save weights
    3900              16 :     double  *padfBSpline = (double *)CPLCalloc( nXRadius * 2, sizeof(double) );
    3901                 : 
    3902                 : /* ==================================================================== */
    3903                 : /*      Loop over output lines.                                         */
    3904                 : /* ==================================================================== */
    3905            1066 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    3906                 :     {
    3907                 :         int iDstX;
    3908                 : 
    3909                 : /* -------------------------------------------------------------------- */
    3910                 : /*      Setup points to transform to source image space.                */
    3911                 : /* -------------------------------------------------------------------- */
    3912          525464 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3913                 :         {
    3914          524414 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    3915          524414 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    3916          524414 :             padfZ[iDstX] = 0.0;
    3917                 :         }
    3918                 : 
    3919                 : /* -------------------------------------------------------------------- */
    3920                 : /*      Transform the points from destination pixel/line coordinates    */
    3921                 : /*      to source pixel/line coordinates.                               */
    3922                 : /* -------------------------------------------------------------------- */
    3923                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    3924            1050 :                               padfX, padfY, padfZ, pabSuccess );
    3925                 : 
    3926                 : /* ==================================================================== */
    3927                 : /*      Loop over pixels in output scanline.                            */
    3928                 : /* ==================================================================== */
    3929          525464 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    3930                 :         {
    3931          524414 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    3932                 : 
    3933                 : /* ==================================================================== */
    3934                 : /*      Loop processing each band.                                      */
    3935                 : /* ==================================================================== */
    3936                 :             int iBand;
    3937                 :             int iDstOffset;
    3938                 : 
    3939          524414 :             iDstOffset = iDstX + iDstY * nDstXSize;
    3940                 : 
    3941         1048828 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    3942                 :             {
    3943          524414 :                 GInt16  iValue = 0;
    3944                 :                 GWKCubicSplineResampleNoMasksShort( poWK, iBand,
    3945          524414 :                                                     padfX[iDstX]-poWK->nSrcXOff,
    3946          524414 :                                                     padfY[iDstX]-poWK->nSrcYOff,
    3947                 :                                                     &iValue,
    3948         1048828 :                                                     padfBSpline);
    3949          524414 :                 ((GInt16 *)poWK->papabyDstImage[iBand])[iDstOffset] = iValue;
    3950                 :             }
    3951                 :         }
    3952                 : 
    3953                 : /* -------------------------------------------------------------------- */
    3954                 : /*      Report progress to the user, and optionally cancel out.         */
    3955                 : /* -------------------------------------------------------------------- */
    3956            1050 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    3957                 :                                 ((iDstY+1) / (double) nDstYSize), 
    3958                 :                                 "", poWK->pProgress ) )
    3959                 :         {
    3960               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    3961               0 :             eErr = CE_Failure;
    3962                 :         }
    3963                 :     }
    3964                 : 
    3965                 : /* -------------------------------------------------------------------- */
    3966                 : /*      Cleanup and return.                                             */
    3967                 : /* -------------------------------------------------------------------- */
    3968              16 :     CPLFree( padfX );
    3969              16 :     CPLFree( padfY );
    3970              16 :     CPLFree( padfZ );
    3971              16 :     CPLFree( pabSuccess );
    3972              16 :     CPLFree( padfBSpline );
    3973                 : 
    3974              16 :     return eErr;
    3975                 : }
    3976                 : 
    3977                 : /************************************************************************/
    3978                 : /*                          GWKNearestShort()                           */
    3979                 : /*                                                                      */
    3980                 : /*      Case for 32bit float input data with nearest neighbour          */
    3981                 : /*      resampling using valid flags. Should be as fast as possible     */
    3982                 : /*      for this particular transformation type.                        */
    3983                 : /************************************************************************/
    3984                 : 
    3985              14 : static CPLErr GWKNearestShort( GDALWarpKernel *poWK )
    3986                 : 
    3987                 : {
    3988                 :     int iDstY;
    3989              14 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    3990              14 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    3991              14 :     CPLErr eErr = CE_None;
    3992                 : 
    3993                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestShort()\n"
    3994                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    3995                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    3996                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    3997                 :               poWK->nDstXOff, poWK->nDstYOff, 
    3998              14 :               poWK->nDstXSize, poWK->nDstYSize );
    3999                 : 
    4000              14 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    4001                 :     {
    4002               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    4003               0 :         return CE_Failure;
    4004                 :     }
    4005                 : 
    4006                 : /* -------------------------------------------------------------------- */
    4007                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    4008                 : /*      scanlines worth of positions.                                   */
    4009                 : /* -------------------------------------------------------------------- */
    4010                 :     double *padfX, *padfY, *padfZ;
    4011                 :     int    *pabSuccess;
    4012                 : 
    4013              14 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    4014              14 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    4015              14 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    4016              14 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    4017                 : 
    4018                 : /* ==================================================================== */
    4019                 : /*      Loop over output lines.                                         */
    4020                 : /* ==================================================================== */
    4021            4594 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    4022                 :     {
    4023                 :         int iDstX;
    4024                 : 
    4025                 : /* -------------------------------------------------------------------- */
    4026                 : /*      Setup points to transform to source image space.                */
    4027                 : /* -------------------------------------------------------------------- */
    4028         3241252 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    4029                 :         {
    4030         3236672 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    4031         3236672 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    4032         3236672 :             padfZ[iDstX] = 0.0;
    4033                 :         }
    4034                 : 
    4035                 : /* -------------------------------------------------------------------- */
    4036                 : /*      Transform the points from destination pixel/line coordinates    */
    4037                 : /*      to source pixel/line coordinates.                               */
    4038                 : /* -------------------------------------------------------------------- */
    4039                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    4040            4580 :                               padfX, padfY, padfZ, pabSuccess );
    4041                 : 
    4042                 : /* ==================================================================== */
    4043                 : /*      Loop over pixels in output scanline.                            */
    4044                 : /* ==================================================================== */
    4045         3241252 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    4046                 :         {
    4047                 :             int iDstOffset;
    4048                 : 
    4049         3236672 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    4050                 : 
    4051                 : /* -------------------------------------------------------------------- */
    4052                 : /*      Don't generate output pixels for which the source valid         */
    4053                 : /*      mask exists and is invalid.                                     */
    4054                 : /* -------------------------------------------------------------------- */
    4055         2976132 :             if( poWK->panUnifiedSrcValid != NULL
    4056               0 :                 && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
    4057                 :                      & (0x01 << (iSrcOffset & 0x1f))) )
    4058               0 :                 continue;
    4059                 : 
    4060                 : /* -------------------------------------------------------------------- */
    4061                 : /*      Do not try to apply transparent source pixels to the destination.*/
    4062                 : /* -------------------------------------------------------------------- */
    4063         2976132 :             double  dfDensity = 1.0;
    4064                 : 
    4065         2976132 :             if( poWK->pafUnifiedSrcDensity != NULL )
    4066                 :             {
    4067            1604 :                 dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
    4068            1604 :                 if( dfDensity < 0.00001 )
    4069             802 :                     continue;
    4070                 :             }
    4071                 : 
    4072                 : /* ==================================================================== */
    4073                 : /*      Loop processing each band.                                      */
    4074                 : /* ==================================================================== */
    4075                 :             int iBand;
    4076         2975330 :             iDstOffset = iDstX + iDstY * nDstXSize;
    4077                 : 
    4078         5952264 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    4079                 :             {
    4080         2976934 :                 GInt16  iValue = 0;
    4081         2976934 :                 double dfBandDensity = 0.0;
    4082                 : 
    4083                 : /* -------------------------------------------------------------------- */
    4084                 : /*      Collect the source value.                                       */
    4085                 : /* -------------------------------------------------------------------- */
    4086         2976934 :                 if ( GWKGetPixelShort( poWK, iBand, iSrcOffset, &dfBandDensity,
    4087                 :                                        &iValue ) )
    4088                 :                 {
    4089         2975504 :                     if( dfBandDensity < 1.0 )
    4090                 :                     {
    4091               0 :                         if( dfBandDensity == 0.0 )
    4092                 :                             /* do nothing */;
    4093                 :                         else
    4094                 :                         {
    4095                 :                             /* let the general code take care of mixing */
    4096                 :                             GWKSetPixelValue( poWK, iBand, iDstOffset, 
    4097                 :                                               dfBandDensity, (double) iValue, 
    4098               0 :                                               0.0 );
    4099                 :                         }
    4100                 :                     }
    4101                 :                     else
    4102                 :                     {
    4103         2975504 :                         ((GInt16 *)poWK->papabyDstImage[iBand])[iDstOffset] = iValue;
    4104                 :                     }
    4105                 :                 }
    4106                 :             }
    4107                 : 
    4108                 : /* -------------------------------------------------------------------- */
    4109                 : /*      Mark this pixel valid/opaque in the output.                     */
    4110                 : /* -------------------------------------------------------------------- */
    4111         2975330 :             GWKOverlayDensity( poWK, iDstOffset, dfDensity );
    4112                 : 
    4113         2975330 :             if( poWK->panDstValid != NULL )
    4114                 :             {
    4115                 :                 poWK->panDstValid[iDstOffset>>5] |= 
    4116               0 :                     0x01 << (iDstOffset & 0x1f);
    4117                 :             }
    4118                 :         } /* Next iDstX */
    4119                 : 
    4120                 : /* -------------------------------------------------------------------- */
    4121                 : /*      Report progress to the user, and optionally cancel out.         */
    4122                 : /* -------------------------------------------------------------------- */
    4123            4580 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    4124                 :                                 ((iDstY+1) / (double) nDstYSize), 
    4125                 :                                 "", poWK->pProgress ) )
    4126                 :         {
    4127               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    4128               0 :             eErr = CE_Failure;
    4129                 :         }
    4130                 :     } /* Next iDstY */
    4131                 : 
    4132                 : /* -------------------------------------------------------------------- */
    4133                 : /*      Cleanup and return.                                             */
    4134                 : /* -------------------------------------------------------------------- */
    4135              14 :     CPLFree( padfX );
    4136              14 :     CPLFree( padfY );
    4137              14 :     CPLFree( padfZ );
    4138              14 :     CPLFree( pabSuccess );
    4139                 : 
    4140              14 :     return eErr;
    4141                 : }
    4142                 : 
    4143                 : /************************************************************************/
    4144                 : /*                    GWKNearestNoMasksFloat()                          */
    4145                 : /*                                                                      */
    4146                 : /*      Case for 32bit float input data with nearest neighbour          */
    4147                 : /*      resampling without concerning about masking. Should be as fast  */
    4148                 : /*      as possible for this particular transformation type.            */
    4149                 : /************************************************************************/
    4150                 : 
    4151              16 : static CPLErr GWKNearestNoMasksFloat( GDALWarpKernel *poWK )
    4152                 : 
    4153                 : {
    4154                 :     int iDstY;
    4155              16 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    4156              16 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    4157              16 :     CPLErr eErr = CE_None;
    4158                 : 
    4159                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestNoMasksFloat()\n"
    4160                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    4161                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    4162                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    4163                 :               poWK->nDstXOff, poWK->nDstYOff, 
    4164              16 :               poWK->nDstXSize, poWK->nDstYSize );
    4165                 : 
    4166              16 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    4167                 :     {
    4168               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    4169               0 :         return CE_Failure;
    4170                 :     }
    4171                 : 
    4172                 : /* -------------------------------------------------------------------- */
    4173                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    4174                 : /*      scanlines worth of positions.                                   */
    4175                 : /* -------------------------------------------------------------------- */
    4176                 :     double *padfX, *padfY, *padfZ;
    4177                 :     int    *pabSuccess;
    4178                 : 
    4179              16 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    4180              16 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    4181              16 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    4182              16 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    4183                 : 
    4184                 : /* ==================================================================== */
    4185                 : /*      Loop over output lines.                                         */
    4186                 : /* ==================================================================== */
    4187            1066 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    4188                 :     {
    4189                 :         int iDstX;
    4190                 : 
    4191                 : /* -------------------------------------------------------------------- */
    4192                 : /*      Setup points to transform to source image space.                */
    4193                 : /* -------------------------------------------------------------------- */
    4194          525464 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    4195                 :         {
    4196          524414 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    4197          524414 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    4198          524414 :             padfZ[iDstX] = 0.0;
    4199                 :         }
    4200                 : 
    4201                 : /* -------------------------------------------------------------------- */
    4202                 : /*      Transform the points from destination pixel/line coordinates    */
    4203                 : /*      to source pixel/line coordinates.                               */
    4204                 : /* -------------------------------------------------------------------- */
    4205                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    4206            1050 :                               padfX, padfY, padfZ, pabSuccess );
    4207                 : 
    4208                 : /* ==================================================================== */
    4209                 : /*      Loop over pixels in output scanline.                            */
    4210                 : /* ==================================================================== */
    4211          525464 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    4212                 :         {
    4213                 :             int iDstOffset;
    4214                 : 
    4215          524414 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    4216                 : 
    4217                 : /* ==================================================================== */
    4218                 : /*      Loop processing each band.                                      */
    4219                 : /* ==================================================================== */
    4220                 :             int iBand;
    4221                 :             
    4222          524414 :             iDstOffset = iDstX + iDstY * nDstXSize;
    4223                 : 
    4224         1048828 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    4225                 :             {
    4226          524414 :                 ((float *)poWK->papabyDstImage[iBand])[iDstOffset] = 
    4227          524414 :                     ((float *)poWK->papabySrcImage[iBand])[iSrcOffset];
    4228                 :             }
    4229                 :         }
    4230                 : 
    4231                 : /* -------------------------------------------------------------------- */
    4232                 : /*      Report progress to the user, and optionally cancel out.         */
    4233                 : /* -------------------------------------------------------------------- */
    4234            1050 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    4235                 :                                 ((iDstY+1) / (double) nDstYSize), 
    4236                 :                                 "", poWK->pProgress ) )
    4237                 :         {
    4238               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    4239               0 :             eErr = CE_Failure;
    4240                 :         }
    4241                 :     }
    4242                 : 
    4243                 : /* -------------------------------------------------------------------- */
    4244                 : /*      Cleanup and return.                                             */
    4245                 : /* -------------------------------------------------------------------- */
    4246              16 :     CPLFree( padfX );
    4247              16 :     CPLFree( padfY );
    4248              16 :     CPLFree( padfZ );
    4249              16 :     CPLFree( pabSuccess );
    4250                 : 
    4251              16 :     return eErr;
    4252                 : }
    4253                 : 
    4254                 : /************************************************************************/
    4255                 : /*                          GWKNearestFloat()                           */
    4256                 : /*                                                                      */
    4257                 : /*      Case for 32bit float input data with nearest neighbour          */
    4258                 : /*      resampling using valid flags. Should be as fast as possible     */
    4259                 : /*      for this particular transformation type.                        */
    4260                 : /************************************************************************/
    4261                 : 
    4262              12 : static CPLErr GWKNearestFloat( GDALWarpKernel *poWK )
    4263                 : 
    4264                 : {
    4265                 :     int iDstY;
    4266              12 :     int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
    4267              12 :     int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
    4268              12 :     CPLErr eErr = CE_None;
    4269                 : 
    4270                 :     CPLDebug( "GDAL", "GDALWarpKernel()::GWKNearestFloat()\n"
    4271                 :               "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
    4272                 :               poWK->nSrcXOff, poWK->nSrcYOff, 
    4273                 :               poWK->nSrcXSize, poWK->nSrcYSize,
    4274                 :               poWK->nDstXOff, poWK->nDstYOff, 
    4275              12 :               poWK->nDstXSize, poWK->nDstYSize );
    4276                 : 
    4277              12 :     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
    4278                 :     {
    4279               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    4280               0 :         return CE_Failure;
    4281                 :     }
    4282                 : 
    4283                 : /* -------------------------------------------------------------------- */
    4284                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
    4285                 : /*      scanlines worth of positions.                                   */
    4286                 : /* -------------------------------------------------------------------- */
    4287                 :     double *padfX, *padfY, *padfZ;
    4288                 :     int    *pabSuccess;
    4289                 : 
    4290              12 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    4291              12 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    4292              12 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
    4293              12 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
    4294                 : 
    4295                 : /* ==================================================================== */
    4296                 : /*      Loop over output lines.                                         */
    4297                 : /* ==================================================================== */
    4298            1548 :     for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
    4299                 :     {
    4300                 :         int iDstX;
    4301                 : 
    4302                 : /* -------------------------------------------------------------------- */
    4303                 : /*      Setup points to transform to source image space.                */
    4304                 : /* -------------------------------------------------------------------- */
    4305          787968 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    4306                 :         {
    4307          786432 :             padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
    4308          786432 :             padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
    4309          786432 :             padfZ[iDstX] = 0.0;
    4310                 :         }
    4311                 : 
    4312                 : /* -------------------------------------------------------------------- */
    4313                 : /*      Transform the points from destination pixel/line coordinates    */
    4314                 : /*      to source pixel/line coordinates.                               */
    4315                 : /* -------------------------------------------------------------------- */
    4316                 :         poWK->pfnTransformer( poWK->pTransformerArg, TRUE, nDstXSize, 
    4317            1536 :                               padfX, padfY, padfZ, pabSuccess );
    4318                 : 
    4319                 : /* ==================================================================== */
    4320                 : /*      Loop over pixels in output scanline.                            */
    4321                 : /* ==================================================================== */
    4322          787968 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
    4323                 :         {
    4324                 :             int iDstOffset;
    4325                 : 
    4326          786432 :             COMPUTE_iSrcOffset(pabSuccess, iDstX, padfX, padfY, poWK, nSrcXSize, nSrcYSize);
    4327                 : 
    4328                 : /* -------------------------------------------------------------------- */
    4329                 : /*      Do not try to apply invalid source pixels to the dest.          */
    4330                 : /* -------------------------------------------------------------------- */
    4331            2404 :             if( poWK->panUnifiedSrcValid != NULL
    4332               0 :                 && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
    4333                 :                      & (0x01 << (iSrcOffset & 0x1f))) )
    4334               0 :                 continue;
    4335                 : 
    4336                 : /* -------------------------------------------------------------------- */
    4337                 : /*      Do not try to apply transparent source pixels to the destination.*/
    4338                 : /* -------------------------------------------------------------------- */
    4339            2404 :             double  dfDensity = 1.0;
    4340                 : 
    4341            2404 :             if( poWK->pafUnifiedSrcDensity != NULL )
    4342                 :             {
    4343            1604 :                 dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
    4344            1604 :                 if( dfDensity < 0.00001 )
    4345             802 :                     continue;
    4346                 :             }
    4347                 : 
    4348                 : /* ==================================================================== */
    4349                 : /*      Loop processing each band.                                      */
    4350                 : /* ==================================================================== */
    4351                 :             int iBand;
    4352                 : 
    4353            1602 :             iDstOffset = iDstX + iDstY * nDstXSize;
    4354                 : 
    4355            4808 :             for( iBand = 0; iBand < poWK->nBands; iBand++ )
    4356                 :             {
    4357            3206 :                 float   fValue = 0;
    4358            3206 :                 double dfBandDensity = 0.0;
    4359                 : 
    4360                 : /* -------------------------------------------------------------------- */
    4361                 : /*      Collect the source value.                                       */
    4362                 : /* -------------------------------------------------------------------- */
    4363            3206 :                 if ( GWKGetPixelFloat( poWK, iBand, iSrcOffset, &dfBandDensity,
    4364                 :                                        &fValue ) )
    4365                 :                 {
    4366            3126 :                     if( dfBandDensity < 1.0 )
    4367                 :                     {
    4368               0 :                         if( dfBandDensity == 0.0 )
    4369                 :                             /* do nothing */;
    4370                 :                         else
    4371                 :                         {
    4372                 :                             /* let the general code take care of mixing */
    4373                 :                             GWKSetPixelValue( poWK, iBand, iDstOffset, 
    4374                 :                                               dfBandDensity, (double) fValue, 
    4375               0 :                                               0.0 );
    4376                 :                         }
    4377                 :                     }
    4378                 :                     else
    4379                 :                     {
    4380            3126 :                         ((float *)poWK->papabyDstImage[iBand])[iDstOffset] 
    4381            3126 :                             = fValue;
    4382                 :                     }
    4383                 :                 }
    4384                 :             }
    4385                 : 
    4386                 : /* -------------------------------------------------------------------- */
    4387                 : /*      Mark this pixel valid/opaque in the output.                     */
    4388                 : /* -------------------------------------------------------------------- */
    4389            1602 :             GWKOverlayDensity( poWK, iDstOffset, dfDensity );
    4390                 : 
    4391            1602 :             if( poWK->panDstValid != NULL )
    4392                 :             {
    4393                 :                 poWK->panDstValid[iDstOffset>>5] |= 
    4394             800 :                     0x01 << (iDstOffset & 0x1f);
    4395                 :             }
    4396                 :         }
    4397                 : 
    4398                 : /* -------------------------------------------------------------------- */
    4399                 : /*      Report progress to the user, and optionally cancel out.         */
    4400                 : /* -------------------------------------------------------------------- */
    4401            1536 :         if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
    4402                 :                                 ((iDstY+1) / (double) nDstYSize), 
    4403                 :                                 "", poWK->pProgress ) )
    4404                 :         {
    4405               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    4406               0 :             eErr = CE_Failure;
    4407                 :         }
    4408                 :     }
    4409                 : 
    4410                 : /* -------------------------------------------------------------------- */
    4411                 : /*      Cleanup and return.                                             */
    4412                 : /* -------------------------------------------------------------------- */
    4413              12 :     CPLFree( padfX );
    4414              12 :     CPLFree( padfY );
    4415              12 :     CPLFree( padfZ );
    4416              12 :     CPLFree( pabSuccess );
    4417                 : 
    4418              12 :     return eErr;
    4419                 : }
    4420                 : 

Generated by: LCOV version 1.7