LCOV - code coverage report
Current view: directory - alg - gdalwarper.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 437 315 72.1 %
Date: 2012-12-26 Functions: 11 10 90.9 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalwarper.cpp 25229 2012-11-16 19:06:58Z rouault $
       3                 :  *
       4                 :  * Project:  High Performance Image Reprojector
       5                 :  * Purpose:  Implementation of high level convenience APIs for warper.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "gdalwarper.h"
      31                 : #include "cpl_string.h"
      32                 : #include "cpl_minixml.h"
      33                 : #include "ogr_api.h"
      34                 : #include "gdal_priv.h"
      35                 : 
      36                 : CPL_CVSID("$Id: gdalwarper.cpp 25229 2012-11-16 19:06:58Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                         GDALReprojectImage()                         */
      40                 : /************************************************************************/
      41                 : 
      42                 : /**
      43                 :  * Reproject image.
      44                 :  *
      45                 :  * This is a convenience function utilizing the GDALWarpOperation class to
      46                 :  * reproject an image from a source to a destination.  In particular, this
      47                 :  * function takes care of establishing the transformation function to
      48                 :  * implement the reprojection, and will default a variety of other 
      49                 :  * warp options. 
      50                 :  *
      51                 :  * No metadata, projection info, or color tables are transferred
      52                 :  * to the output file. 
      53                 :  *
      54                 :  * @param hSrcDS the source image file. 
      55                 :  * @param pszSrcWKT the source projection.  If NULL the source projection
      56                 :  * is read from from hSrcDS.
      57                 :  * @param hDstDS the destination image file. 
      58                 :  * @param pszDstWKT the destination projection.  If NULL the destination
      59                 :  * projection will be read from hDstDS.
      60                 :  * @param eResampleAlg the type of resampling to use.  
      61                 :  * @param dfWarpMemoryLimit the amount of memory (in bytes) that the warp
      62                 :  * API is allowed to use for caching.  This is in addition to the memory
      63                 :  * already allocated to the GDAL caching (as per GDALSetCacheMax()).  May be
      64                 :  * 0.0 to use default memory settings.
      65                 :  * @param dfMaxError maximum error measured in input pixels that is allowed
      66                 :  * in approximating the transformation (0.0 for exact calculations).
      67                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
      68                 :  * reporting progress or NULL. 
      69                 :  * @param pProgressArg argument to be passed to pfnProgress.  May be NULL.
      70                 :  * @param psOptions warp options, normally NULL.
      71                 :  *
      72                 :  * @return CE_None on success or CE_Failure if something goes wrong.
      73                 :  */
      74                 : 
      75                 : CPLErr CPL_STDCALL 
      76              27 : GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT, 
      77                 :                     GDALDatasetH hDstDS, const char *pszDstWKT,
      78                 :                     GDALResampleAlg eResampleAlg, 
      79                 :                     double dfWarpMemoryLimit, 
      80                 :                     double dfMaxError,
      81                 :                     GDALProgressFunc pfnProgress, void *pProgressArg, 
      82                 :                     GDALWarpOptions *psOptions )
      83                 : 
      84                 : {
      85                 :     GDALWarpOptions *psWOptions;
      86                 : 
      87                 : /* -------------------------------------------------------------------- */
      88                 : /*      Setup a reprojection based transformer.                         */
      89                 : /* -------------------------------------------------------------------- */
      90                 :     void *hTransformArg;
      91                 : 
      92                 :     hTransformArg = 
      93                 :         GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT, 
      94              27 :                                          TRUE, 1000.0, 0 );
      95                 : 
      96              27 :     if( hTransformArg == NULL )
      97               0 :         return CE_Failure;
      98                 : 
      99                 : /* -------------------------------------------------------------------- */
     100                 : /*      Create a copy of the user provided options, or a defaulted      */
     101                 : /*      options structure.                                              */
     102                 : /* -------------------------------------------------------------------- */
     103              27 :     if( psOptions == NULL )
     104              27 :         psWOptions = GDALCreateWarpOptions();
     105                 :     else
     106               0 :         psWOptions = GDALCloneWarpOptions( psOptions );
     107                 : 
     108              27 :     psWOptions->eResampleAlg = eResampleAlg;
     109                 : 
     110                 : /* -------------------------------------------------------------------- */
     111                 : /*      Set transform.                                                  */
     112                 : /* -------------------------------------------------------------------- */
     113              27 :     if( dfMaxError > 0.0 )
     114                 :     {
     115                 :         psWOptions->pTransformerArg = 
     116                 :             GDALCreateApproxTransformer( GDALGenImgProjTransform, 
     117               3 :                                          hTransformArg, dfMaxError );
     118                 : 
     119               3 :         psWOptions->pfnTransformer = GDALApproxTransform;
     120                 :     }
     121                 :     else
     122                 :     {
     123              24 :         psWOptions->pfnTransformer = GDALGenImgProjTransform;
     124              24 :         psWOptions->pTransformerArg = hTransformArg;
     125                 :     }
     126                 : 
     127                 : /* -------------------------------------------------------------------- */
     128                 : /*      Set file and band mapping.                                      */
     129                 : /* -------------------------------------------------------------------- */
     130                 :     int  iBand;
     131                 : 
     132              27 :     psWOptions->hSrcDS = hSrcDS;
     133              27 :     psWOptions->hDstDS = hDstDS;
     134                 : 
     135              27 :     if( psWOptions->nBandCount == 0 )
     136                 :     {
     137                 :         psWOptions->nBandCount = MIN(GDALGetRasterCount(hSrcDS),
     138              27 :                                      GDALGetRasterCount(hDstDS));
     139                 :         
     140                 :         psWOptions->panSrcBands = (int *) 
     141              27 :             CPLMalloc(sizeof(int) * psWOptions->nBandCount);
     142                 :         psWOptions->panDstBands = (int *) 
     143              27 :             CPLMalloc(sizeof(int) * psWOptions->nBandCount);
     144                 : 
     145              60 :         for( iBand = 0; iBand < psWOptions->nBandCount; iBand++ )
     146                 :         {
     147              33 :             psWOptions->panSrcBands[iBand] = iBand+1;
     148              33 :             psWOptions->panDstBands[iBand] = iBand+1;
     149                 :         }
     150                 :     }
     151                 : 
     152                 : /* -------------------------------------------------------------------- */
     153                 : /*      Set source nodata values if the source dataset seems to have    */
     154                 : /*      any.                                                            */
     155                 : /* -------------------------------------------------------------------- */
     156              60 :     for( iBand = 0; iBand < psWOptions->nBandCount; iBand++ )
     157                 :     {
     158              33 :         GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, iBand+1 );
     159              33 :         int             bGotNoData = FALSE;
     160                 :         double          dfNoDataValue;
     161                 : 
     162              33 :         if (GDALGetRasterColorInterpretation(hBand) == GCI_AlphaBand)
     163                 :         {
     164               2 :             psWOptions->nSrcAlphaBand = iBand + 1;
     165                 :         }
     166                 : 
     167              33 :         dfNoDataValue = GDALGetRasterNoDataValue( hBand, &bGotNoData );
     168              33 :         if( bGotNoData )
     169                 :         {
     170               5 :             if( psWOptions->padfSrcNoDataReal == NULL )
     171                 :             {
     172                 :                 int  ii;
     173                 : 
     174                 :                 psWOptions->padfSrcNoDataReal = (double *) 
     175               5 :                     CPLMalloc(sizeof(double) * psWOptions->nBandCount);
     176                 :                 psWOptions->padfSrcNoDataImag = (double *) 
     177               5 :                     CPLMalloc(sizeof(double) * psWOptions->nBandCount);
     178                 : 
     179              10 :                 for( ii = 0; ii < psWOptions->nBandCount; ii++ )
     180                 :                 {
     181               5 :                     psWOptions->padfSrcNoDataReal[ii] = -1.1e20;
     182               5 :                     psWOptions->padfSrcNoDataImag[ii] = 0.0;
     183                 :                 }
     184                 :             }
     185                 : 
     186               5 :             psWOptions->padfSrcNoDataReal[iBand] = dfNoDataValue;
     187                 :         }
     188                 : 
     189              33 :         hBand = GDALGetRasterBand( hDstDS, iBand+1 );
     190              33 :         if (hBand && GDALGetRasterColorInterpretation(hBand) == GCI_AlphaBand)
     191                 :         {
     192               2 :             psWOptions->nDstAlphaBand = iBand + 1;
     193                 :         }
     194                 :     }
     195                 : 
     196                 : /* -------------------------------------------------------------------- */
     197                 : /*      Set the progress function.                                      */
     198                 : /* -------------------------------------------------------------------- */
     199              27 :     if( pfnProgress != NULL )
     200                 :     {
     201               3 :         psWOptions->pfnProgress = pfnProgress;
     202               3 :         psWOptions->pProgressArg = pProgressArg;
     203                 :     }
     204                 : 
     205                 : /* -------------------------------------------------------------------- */
     206                 : /*      Create a warp options based on the options.                     */
     207                 : /* -------------------------------------------------------------------- */
     208              27 :     GDALWarpOperation  oWarper;
     209                 :     CPLErr eErr;
     210                 : 
     211              27 :     eErr = oWarper.Initialize( psWOptions );
     212                 : 
     213              27 :     if( eErr == CE_None )
     214                 :         eErr = oWarper.ChunkAndWarpImage( 0, 0, 
     215                 :                                           GDALGetRasterXSize(hDstDS),
     216              27 :                                           GDALGetRasterYSize(hDstDS) );
     217                 : 
     218                 : /* -------------------------------------------------------------------- */
     219                 : /*      Cleanup.                                                        */
     220                 : /* -------------------------------------------------------------------- */
     221              27 :     GDALDestroyGenImgProjTransformer( hTransformArg );
     222                 : 
     223              27 :     if( dfMaxError > 0.0 )
     224               3 :         GDALDestroyApproxTransformer( psWOptions->pTransformerArg );
     225                 :         
     226              27 :     GDALDestroyWarpOptions( psWOptions );
     227                 : 
     228              27 :     return eErr;
     229                 : }
     230                 : 
     231                 : /************************************************************************/
     232                 : /*                    GDALCreateAndReprojectImage()                     */
     233                 : /*                                                                      */
     234                 : /*      This is a "quicky" reprojection API.                            */
     235                 : /************************************************************************/
     236                 : 
     237               0 : CPLErr CPL_STDCALL GDALCreateAndReprojectImage( 
     238                 :     GDALDatasetH hSrcDS, const char *pszSrcWKT, 
     239                 :     const char *pszDstFilename, const char *pszDstWKT,
     240                 :     GDALDriverH hDstDriver, char **papszCreateOptions,
     241                 :     GDALResampleAlg eResampleAlg, double dfWarpMemoryLimit, double dfMaxError,
     242                 :     GDALProgressFunc pfnProgress, void *pProgressArg, 
     243                 :     GDALWarpOptions *psOptions )
     244                 :     
     245                 : {
     246               0 :     VALIDATE_POINTER1( hSrcDS, "GDALCreateAndReprojectImage", CE_Failure );
     247                 : 
     248                 : /* -------------------------------------------------------------------- */
     249                 : /*      Default a few parameters.                                       */
     250                 : /* -------------------------------------------------------------------- */
     251               0 :     if( hDstDriver == NULL )
     252                 :     {
     253               0 :         hDstDriver = GDALGetDriverByName( "GTiff" );
     254               0 :         if (hDstDriver == NULL)
     255                 :         {
     256                 :             CPLError(CE_Failure, CPLE_AppDefined,
     257               0 :                      "GDALCreateAndReprojectImage needs GTiff driver");
     258               0 :             return CE_Failure;
     259                 :         }
     260                 :     }
     261                 : 
     262               0 :     if( pszSrcWKT == NULL )
     263               0 :         pszSrcWKT = GDALGetProjectionRef( hSrcDS );
     264                 : 
     265               0 :     if( pszDstWKT == NULL )
     266               0 :         pszDstWKT = pszSrcWKT;
     267                 : 
     268                 : /* -------------------------------------------------------------------- */
     269                 : /*      Create a transformation object from the source to               */
     270                 : /*      destination coordinate system.                                  */
     271                 : /* -------------------------------------------------------------------- */
     272                 :     void *hTransformArg;
     273                 : 
     274                 :     hTransformArg = 
     275                 :         GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, NULL, pszDstWKT, 
     276               0 :                                          TRUE, 1000.0, 0 );
     277                 : 
     278               0 :     if( hTransformArg == NULL )
     279               0 :         return CE_Failure;
     280                 : 
     281                 : /* -------------------------------------------------------------------- */
     282                 : /*      Get approximate output definition.                              */
     283                 : /* -------------------------------------------------------------------- */
     284                 :     double adfDstGeoTransform[6];
     285                 :     int    nPixels, nLines;
     286                 : 
     287               0 :     if( GDALSuggestedWarpOutput( hSrcDS, 
     288                 :                                  GDALGenImgProjTransform, hTransformArg, 
     289                 :                                  adfDstGeoTransform, &nPixels, &nLines )
     290                 :         != CE_None )
     291               0 :         return CE_Failure;
     292                 : 
     293               0 :     GDALDestroyGenImgProjTransformer( hTransformArg );
     294                 : 
     295                 : /* -------------------------------------------------------------------- */
     296                 : /*      Create the output file.                                         */
     297                 : /* -------------------------------------------------------------------- */
     298                 :     GDALDatasetH hDstDS;
     299                 : 
     300                 :     hDstDS = GDALCreate( hDstDriver, pszDstFilename, nPixels, nLines, 
     301                 :                          GDALGetRasterCount(hSrcDS),
     302                 :                          GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1)),
     303               0 :                          papszCreateOptions );
     304                 : 
     305               0 :     if( hDstDS == NULL )
     306               0 :         return CE_Failure;
     307                 : 
     308                 : /* -------------------------------------------------------------------- */
     309                 : /*      Write out the projection definition.                            */
     310                 : /* -------------------------------------------------------------------- */
     311               0 :     GDALSetProjection( hDstDS, pszDstWKT );
     312               0 :     GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
     313                 : 
     314                 : /* -------------------------------------------------------------------- */
     315                 : /*      Perform the reprojection.                                       */
     316                 : /* -------------------------------------------------------------------- */
     317                 :     CPLErr eErr ;
     318                 : 
     319                 :     eErr = 
     320                 :         GDALReprojectImage( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT, 
     321                 :                             eResampleAlg, dfWarpMemoryLimit, dfMaxError,
     322               0 :                             pfnProgress, pProgressArg, psOptions );
     323                 : 
     324               0 :     GDALClose( hDstDS );
     325                 : 
     326               0 :     return eErr;
     327                 : }
     328                 : 
     329                 : /************************************************************************/
     330                 : /*                        GDALWarpNoDataMasker()                        */
     331                 : /*                                                                      */
     332                 : /*      GDALMaskFunc for establishing a validity mask for a source      */
     333                 : /*      band based on a provided NODATA value.                          */
     334                 : /************************************************************************/
     335                 : 
     336                 : CPLErr 
     337              36 : GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType, 
     338                 :                       int /* nXOff */, int /* nYOff */, int nXSize, int nYSize,
     339                 :                       GByte **ppImageData, 
     340                 :                       int bMaskIsFloat, void *pValidityMask )
     341                 : 
     342                 : {
     343              36 :     double *padfNoData = (double *) pMaskFuncArg;
     344              36 :     GUInt32 *panValidityMask = (GUInt32 *) pValidityMask;
     345                 : 
     346              36 :     if( nBandCount != 1 || bMaskIsFloat )
     347                 :     {
     348                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     349               0 :                   "Invalid nBandCount or bMaskIsFloat argument in SourceNoDataMask" );
     350               0 :         return CE_Failure;
     351                 :     }
     352                 : 
     353              36 :     switch( eType )
     354                 :     {
     355                 :       case GDT_Byte:
     356                 :       {
     357              15 :           int nNoData = (int) padfNoData[0];
     358              15 :           GByte *pabyData = (GByte *) *ppImageData;
     359                 :           int iOffset;
     360                 : 
     361                 :           // nothing to do if value is out of range.
     362              30 :           if( padfNoData[0] < 0.0 || padfNoData[0] > 255.000001 
     363              15 :               || padfNoData[1] != 0.0 )
     364               0 :               return CE_None;
     365                 : 
     366          279200 :           for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
     367                 :           {
     368          279185 :               if( pabyData[iOffset] == nNoData )
     369                 :               {
     370          264930 :                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
     371                 :               }
     372                 :           }
     373                 :       }
     374              15 :       break;
     375                 :       
     376                 :       case GDT_Int16:
     377                 :       {
     378               5 :           int nNoData = (int) padfNoData[0];
     379               5 :           GInt16 *panData = (GInt16 *) *ppImageData;
     380                 :           int iOffset;
     381                 : 
     382                 :           // nothing to do if value is out of range.
     383              10 :           if( padfNoData[0] < -32768 || padfNoData[0] > 32767
     384               5 :               || padfNoData[1] != 0.0 )
     385               0 :               return CE_None;
     386                 : 
     387           45829 :           for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
     388                 :           {
     389           45824 :               if( panData[iOffset] == nNoData )
     390                 :               {
     391             715 :                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
     392                 :               }
     393                 :           }
     394                 :       }
     395               5 :       break;
     396                 :       
     397                 :       case GDT_UInt16:
     398                 :       {
     399               0 :           int nNoData = (int) padfNoData[0];
     400               0 :           GUInt16 *panData = (GUInt16 *) *ppImageData;
     401                 :           int iOffset;
     402                 : 
     403                 :           // nothing to do if value is out of range.
     404               0 :           if( padfNoData[0] < 0 || padfNoData[0] > 65535
     405               0 :               || padfNoData[1] != 0.0 )
     406               0 :               return CE_None;
     407                 : 
     408               0 :           for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
     409                 :           {
     410               0 :               if( panData[iOffset] == nNoData )
     411                 :               {
     412               0 :                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
     413                 :               }
     414                 :           }
     415                 :       }
     416               0 :       break;
     417                 :       
     418                 :       case GDT_Float32:
     419                 :       {
     420               8 :           float fNoData = (float) padfNoData[0];
     421               8 :           float *pafData = (float *) *ppImageData;
     422                 :           int iOffset;
     423               8 :           int bIsNoDataNan = CPLIsNan(fNoData);
     424                 : 
     425                 :           // nothing to do if value is out of range.
     426               8 :           if( padfNoData[1] != 0.0 )
     427               0 :               return CE_None;
     428                 : 
     429          262552 :           for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
     430                 :           {
     431          262544 :               float fVal = pafData[iOffset];
     432          262544 :               if( (bIsNoDataNan && CPLIsNan(fVal)) || (!bIsNoDataNan && ARE_REAL_EQUAL(fVal, fNoData)) )
     433                 :               {
     434          262184 :                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
     435                 :               }
     436                 :           }
     437                 :       }
     438               8 :       break;
     439                 :       
     440                 :       case GDT_Float64:
     441                 :       {
     442               0 :           double dfNoData = padfNoData[0];
     443               0 :           double *padfData = (double *) *ppImageData;
     444                 :           int iOffset;
     445               0 :           int bIsNoDataNan = CPLIsNan(dfNoData);
     446                 : 
     447                 :           // nothing to do if value is out of range.
     448               0 :           if( padfNoData[1] != 0.0 )
     449               0 :               return CE_None;
     450                 : 
     451               0 :           for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
     452                 :           {
     453               0 :               double dfVal = padfData[iOffset];
     454               0 :               if( (bIsNoDataNan && CPLIsNan(dfVal)) || (!bIsNoDataNan && ARE_REAL_EQUAL(dfVal, dfNoData)) )
     455                 :               {
     456               0 :                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
     457                 :               }
     458                 :           }
     459                 :       }
     460               0 :       break;
     461                 :       
     462                 :       default:
     463                 :       {
     464                 :           double  *padfWrk;
     465                 :           int     iLine, iPixel;
     466               8 :           int     nWordSize = GDALGetDataTypeSize(eType)/8;
     467                 :           
     468               8 :           int bIsNoDataRealNan = CPLIsNan(padfNoData[0]);
     469               8 :           int bIsNoDataImagNan = CPLIsNan(padfNoData[1]);
     470                 : 
     471               8 :           padfWrk = (double *) CPLMalloc(nXSize * sizeof(double) * 2);
     472              88 :           for( iLine = 0; iLine < nYSize; iLine++ )
     473                 :           {
     474                 :               GDALCopyWords( ((GByte *) *ppImageData)+nWordSize*iLine*nXSize, 
     475                 :                              eType, nWordSize,
     476              80 :                              padfWrk, GDT_CFloat64, 16, nXSize );
     477                 :               
     478             880 :               for( iPixel = 0; iPixel < nXSize; iPixel++ )
     479                 :               {
     480            4000 :                   if( ((bIsNoDataRealNan && CPLIsNan(padfWrk[iPixel*2])) ||
     481            3200 :                        (!bIsNoDataRealNan && ARE_REAL_EQUAL(padfWrk[iPixel*2], padfNoData[0])))
     482                 :                       && ((bIsNoDataImagNan && CPLIsNan(padfWrk[iPixel*2+1])) ||
     483               0 :                           (!bIsNoDataImagNan && ARE_REAL_EQUAL(padfWrk[iPixel*2+1], padfNoData[1]))) )
     484                 :                   {
     485               0 :                       int iOffset = iPixel + iLine * nXSize;
     486                 :                       
     487                 :                       panValidityMask[iOffset>>5] &=
     488               0 :                           ~(0x01 << (iOffset & 0x1f));
     489                 :                   }
     490                 :               }
     491                 :               
     492                 :           }
     493                 : 
     494               8 :           CPLFree( padfWrk );
     495                 :       }
     496                 :       break;
     497                 :     }
     498                 : 
     499              36 :     return CE_None;
     500                 : }
     501                 : 
     502                 : /************************************************************************/
     503                 : /*                       GDALWarpSrcAlphaMasker()                       */
     504                 : /*                                                                      */
     505                 : /*      GDALMaskFunc for reading source simple 8bit alpha mask          */
     506                 : /*      information and building a floating point density mask from     */
     507                 : /*      it.                                                             */
     508                 : /************************************************************************/
     509                 : 
     510                 : CPLErr 
     511               9 : GDALWarpSrcAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType, 
     512                 :                         int nXOff, int nYOff, int nXSize, int nYSize,
     513                 :                         GByte ** /*ppImageData */,
     514                 :                         int bMaskIsFloat, void *pValidityMask )
     515                 : 
     516                 : {
     517               9 :     GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
     518               9 :     float *pafMask = (float *) pValidityMask;
     519                 : 
     520                 : /* -------------------------------------------------------------------- */
     521                 : /*      Do some minimal checking.                                       */
     522                 : /* -------------------------------------------------------------------- */
     523               9 :     if( !bMaskIsFloat )
     524                 :     {
     525               0 :         CPLAssert( FALSE );
     526               0 :         return CE_Failure;
     527                 :     }
     528                 : 
     529               9 :     if( psWO == NULL || psWO->nSrcAlphaBand < 1 )
     530                 :     {
     531               0 :         CPLAssert( FALSE );
     532               0 :         return CE_Failure;
     533                 :     }
     534                 : 
     535                 : /* -------------------------------------------------------------------- */
     536                 : /*      Read the alpha band.                                            */
     537                 : /* -------------------------------------------------------------------- */
     538                 :     CPLErr eErr;
     539                 :     GDALRasterBandH hAlphaBand = GDALGetRasterBand( psWO->hSrcDS, 
     540               9 :                                                     psWO->nSrcAlphaBand );
     541               9 :     if (hAlphaBand == NULL)
     542               0 :         return CE_Failure;
     543                 : 
     544                 :     eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize, 
     545               9 :                          pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
     546                 : 
     547               9 :     if( eErr != CE_None )
     548               0 :         return eErr;
     549                 : 
     550                 : /* -------------------------------------------------------------------- */
     551                 : /*      Rescale from 0-255 to 0.0-1.0.                                  */
     552                 : /* -------------------------------------------------------------------- */
     553            3309 :     for( int iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
     554                 :     {                                    //  (1/255)
     555            3300 :         pafMask[iPixel] = (float)( pafMask[iPixel] * 0.00392157 );
     556            3300 :         pafMask[iPixel] = MIN( 1.0F, pafMask[iPixel] );
     557                 :     }
     558                 : 
     559               9 :     return CE_None;
     560                 : }
     561                 : 
     562                 : /************************************************************************/
     563                 : /*                       GDALWarpSrcMaskMasker()                        */
     564                 : /*                                                                      */
     565                 : /*      GDALMaskFunc for reading source simple 8bit validity mask       */
     566                 : /*      information and building a one bit validity mask.               */
     567                 : /************************************************************************/
     568                 : 
     569                 : CPLErr 
     570               1 : GDALWarpSrcMaskMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType, 
     571                 :                        int nXOff, int nYOff, int nXSize, int nYSize,
     572                 :                        GByte ** /*ppImageData */,
     573                 :                        int bMaskIsFloat, void *pValidityMask )
     574                 : 
     575                 : {
     576               1 :     GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
     577               1 :     GUInt32  *panMask = (GUInt32 *) pValidityMask;
     578                 : 
     579                 : /* -------------------------------------------------------------------- */
     580                 : /*      Do some minimal checking.                                       */
     581                 : /* -------------------------------------------------------------------- */
     582               1 :     if( bMaskIsFloat )
     583                 :     {
     584               0 :         CPLAssert( FALSE );
     585               0 :         return CE_Failure;
     586                 :     }
     587                 : 
     588               1 :     if( psWO == NULL )
     589                 :     {
     590               0 :         CPLAssert( FALSE );
     591               0 :         return CE_Failure;
     592                 :     }
     593                 : 
     594                 : /* -------------------------------------------------------------------- */
     595                 : /*      Allocate a temporary buffer to read mask byte data into.        */
     596                 : /* -------------------------------------------------------------------- */
     597                 :     GByte *pabySrcMask;
     598                 : 
     599               1 :     pabySrcMask = (GByte *) VSIMalloc2(nXSize,nYSize);
     600               1 :     if( pabySrcMask == NULL )
     601                 :     {
     602                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
     603                 :                   "Failed to allocate pabySrcMask (%dx%d) in GDALWarpSrcMaskMasker()", 
     604               0 :                   nXSize, nYSize );
     605               0 :         return CE_Failure;
     606                 :     }
     607                 : 
     608                 : /* -------------------------------------------------------------------- */
     609                 : /*      Fetch our mask band.                                            */
     610                 : /* -------------------------------------------------------------------- */
     611               1 :     GDALRasterBandH hSrcBand, hMaskBand = NULL;
     612                 : 
     613               1 :     hSrcBand = GDALGetRasterBand( psWO->hSrcDS, psWO->panSrcBands[0] );
     614               1 :     if( hSrcBand != NULL )
     615               1 :         hMaskBand = GDALGetMaskBand( hSrcBand );
     616                 : 
     617               1 :     if( hMaskBand == NULL )
     618                 :     {
     619               0 :         CPLAssert( FALSE );
     620               0 :         return CE_Failure;
     621                 :     }
     622                 : 
     623                 : /* -------------------------------------------------------------------- */
     624                 : /*      Read the mask band.                                             */
     625                 : /* -------------------------------------------------------------------- */
     626                 :     CPLErr eErr;
     627                 : 
     628                 :     eErr = GDALRasterIO( hMaskBand, GF_Read, nXOff, nYOff, nXSize, nYSize, 
     629               1 :                          pabySrcMask, nXSize, nYSize, GDT_Byte, 0, 0 );
     630                 : 
     631               1 :     if( eErr != CE_None )
     632                 :     {
     633               0 :         CPLFree( pabySrcMask );
     634               0 :         return eErr;
     635                 :     }
     636                 : 
     637                 : /* -------------------------------------------------------------------- */
     638                 : /*      Pack into 1 bit per pixel for validity.                         */
     639                 : /* -------------------------------------------------------------------- */
     640          154578 :     for( int iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
     641                 :     {                                    
     642          154577 :         if( pabySrcMask[iPixel] == 0 )
     643           31659 :             panMask[iPixel>>5] &= ~(0x01 << (iPixel & 0x1f));
     644                 :     }
     645                 : 
     646               1 :     CPLFree( pabySrcMask );
     647                 : 
     648               1 :     return CE_None;
     649                 : }
     650                 : 
     651                 : /************************************************************************/
     652                 : /*                       GDALWarpDstAlphaMasker()                       */
     653                 : /*                                                                      */
     654                 : /*      GDALMaskFunc for reading or writing the destination simple      */
     655                 : /*      8bit alpha mask information and building a floating point       */
     656                 : /*      density mask from it.   Note, writing is distinguished          */
     657                 : /*      negative bandcount.                                             */
     658                 : /************************************************************************/
     659                 : 
     660                 : CPLErr 
     661              52 : GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
     662                 :                         int nXOff, int nYOff, int nXSize, int nYSize,
     663                 :                         GByte ** /*ppImageData */,
     664                 :                         int bMaskIsFloat, void *pValidityMask )
     665                 : 
     666                 : {
     667              52 :     GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
     668              52 :     float *pafMask = (float *) pValidityMask;
     669                 :     int iPixel;
     670                 :     CPLErr eErr;
     671                 : 
     672                 : /* -------------------------------------------------------------------- */
     673                 : /*      Do some minimal checking.                                       */
     674                 : /* -------------------------------------------------------------------- */
     675              52 :     if( !bMaskIsFloat )
     676                 :     {
     677               0 :         CPLAssert( FALSE );
     678               0 :         return CE_Failure;
     679                 :     }
     680                 : 
     681              52 :     if( psWO == NULL || psWO->nDstAlphaBand < 1 )
     682                 :     {
     683               0 :         CPLAssert( FALSE );
     684               0 :         return CE_Failure;
     685                 :     }
     686                 : 
     687                 :     GDALRasterBandH hAlphaBand = 
     688              52 :         GDALGetRasterBand( psWO->hDstDS, psWO->nDstAlphaBand );
     689              52 :     if (hAlphaBand == NULL)
     690               0 :         return CE_Failure;
     691                 : 
     692                 : /* -------------------------------------------------------------------- */
     693                 : /*      Read alpha case.            */
     694                 : /* -------------------------------------------------------------------- */
     695              52 :     if( nBandCount >= 0 )
     696                 :     {
     697                 :         const char *pszInitDest = 
     698              26 :             CSLFetchNameValue( psWO->papszWarpOptions, "INIT_DEST" );
     699                 : 
     700                 :         // Special logic for destinations being initialized on the fly.
     701              26 :         if( pszInitDest != NULL )
     702                 :         {
     703         1554900 :             for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
     704         1554876 :                 pafMask[iPixel] = 0.0;
     705              24 :             return CE_None;
     706                 :         }
     707                 : 
     708                 :         // Read data.
     709                 :         eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
     710               2 :                              pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
     711                 :         
     712               2 :         if( eErr != CE_None )
     713               0 :             return eErr;
     714                 : 
     715                 :         // rescale.
     716             127 :         for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
     717                 :         {
     718             125 :             pafMask[iPixel] = (float) (pafMask[iPixel] * 0.00392157);
     719             125 :             pafMask[iPixel] = MIN( 1.0F, pafMask[iPixel] );
     720                 :         }
     721                 : 
     722               2 :         return CE_None;
     723                 :     }
     724                 : 
     725                 : /* -------------------------------------------------------------------- */
     726                 : /*      Write alpha case.                                               */
     727                 : /* -------------------------------------------------------------------- */
     728                 :     else
     729                 :     {
     730         1555027 :         for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
     731         1555001 :             pafMask[iPixel] = (float)(int) ( pafMask[iPixel] * 255.1 );
     732                 :         
     733                 :         // Write data.
     734                 : 
     735                 :         /* The VRT warper will pass destination sizes that may exceed */
     736                 :         /* the size of the raster for the partial blocks at the right */
     737                 :         /* and bottom of the band. So let's adjust the size */
     738              26 :         int nDstXSize = nXSize;
     739              26 :         if (nXOff + nXSize > GDALGetRasterBandXSize(hAlphaBand))
     740              16 :             nDstXSize = GDALGetRasterBandXSize(hAlphaBand) - nXOff;
     741              26 :         int nDstYSize = nYSize;
     742              26 :         if (nYOff + nYSize > GDALGetRasterBandYSize(hAlphaBand))
     743              12 :             nDstYSize = GDALGetRasterBandYSize(hAlphaBand) - nYOff;
     744                 : 
     745                 :         eErr = GDALRasterIO( hAlphaBand, GF_Write, 
     746                 :                              nXOff, nYOff, nDstXSize, nDstYSize, 
     747                 :                              pafMask, nDstXSize, nDstYSize, GDT_Float32,
     748              26 :                              0, sizeof(float) * nXSize );
     749              26 :         return eErr;
     750                 :     }
     751                 : }
     752                 : 
     753                 : /************************************************************************/
     754                 : /* ==================================================================== */
     755                 : /*                           GDALWarpOptions                            */
     756                 : /* ==================================================================== */
     757                 : /************************************************************************/
     758                 : 
     759                 : /**
     760                 :  * \var char **GDALWarpOptions::papszWarpOptions;
     761                 :  *
     762                 :  * A string list of additional options controlling the warp operation in
     763                 :  * name=value format.  A suitable string list can be prepared with 
     764                 :  * CSLSetNameValue().
     765                 :  *
     766                 :  * The following values are currently supported:
     767                 :  * 
     768                 :  *  - INIT_DEST=[value] or INIT_DEST=NO_DATA: This option forces the 
     769                 :  * destination image to be initialized to the indicated value (for all bands)
     770                 :  * or indicates that it should be initialized to the NO_DATA value in
     771                 :  * padfDstNoDataReal/padfDstNoDataImag.  If this value isn't set the
     772                 :  * destination image will be read and overlayed.  
     773                 :  *
     774                 :  * - WRITE_FLUSH=YES/NO: This option forces a flush to disk of data after
     775                 :  * each chunk is processed.  In some cases this helps ensure a serial 
     776                 :  * writing of the output data otherwise a block of data may be written to disk
     777                 :  * each time a block of data is read for the input buffer resulting in alot
     778                 :  * of extra seeking around the disk, and reduced IO throughput.  The default
     779                 :  * at this time is NO.
     780                 :  *
     781                 :  * - SKIP_NOSOURCE=YES/NO: Skip all processing for chunks for which there
     782                 :  * is no corresponding input data.  This will disable initializing the 
     783                 :  * destination (INIT_DEST) and all other processing, and so should be used
     784                 :  * careful.  Mostly useful to short circuit a lot of extra work in mosaicing 
     785                 :  * situations.
     786                 :  * 
     787                 :  * - UNIFIED_SRC_NODATA=YES/[NO]: By default nodata masking values considered
     788                 :  * independently for each band.  However, sometimes it is desired to treat all
     789                 :  * bands as nodata if and only if, all bands match the corresponding nodata
     790                 :  * values.  To get this behavior set this option to YES. 
     791                 :  *
     792                 :  * Normally when computing the source raster data to 
     793                 :  * load to generate a particular output area, the warper samples transforms
     794                 :  * 21 points along each edge of the destination region back onto the source
     795                 :  * file, and uses this to compute a bounding window on the source image that
     796                 :  * is sufficient.  Depending on the transformation in effect, the source 
     797                 :  * window may be a bit too small, or even missing large areas.  Problem 
     798                 :  * situations are those where the transformation is very non-linear or 
     799                 :  * "inside out".  Examples are transforming from WGS84 to Polar Steregraphic
     800                 :  * for areas around the pole, or transformations where some of the image is
     801                 :  * untransformable.  The following options provide some additional control
     802                 :  * to deal with errors in computing the source window:
     803                 :  * 
     804                 :  * - SAMPLE_GRID=YES/NO: Setting this option to YES will force the sampling to 
     805                 :  * include internal points as well as edge points which can be important if
     806                 :  * the transformation is esoteric inside out, or if large sections of the
     807                 :  * destination image are not transformable into the source coordinate system.
     808                 :  *
     809                 :  * - SAMPLE_STEPS: Modifies the density of the sampling grid.  The default
     810                 :  * number of steps is 21.   Increasing this can increase the computational
     811                 :  * cost, but improves the accuracy with which the source region is computed.
     812                 :  *
     813                 :  * - SOURCE_EXTRA: This is a number of extra pixels added around the source
     814                 :  * window for a given request, and by default it is 1 to take care of rounding
     815                 :  * error.  Setting this larger will incease the amount of data that needs to
     816                 :  * be read, but can avoid missing source data.  
     817                 :  *
     818                 :  * - CUTLINE: This may contain the WKT geometry for a cutline.  It will
     819                 :  * be converted into a geometry by GDALWarpOperation::Initialize() and assigned
     820                 :  * to the GDALWarpOptions hCutline field. The coordinates must be expressed
     821                 :  * in source pixel/line coordinates. Note: this is different from the assumptions
     822                 :  * made for the -cutline option of the gdalwarp utility !
     823                 :  *
     824                 :  * - CUTLINE_BLEND_DIST: This may be set with a distance in pixels which
     825                 :  * will be assigned to the dfCutlineBlendDist field in the GDALWarpOptions.
     826                 :  *
     827                 :  * - CUTLINE_ALL_TOUCHED: This defaults to FALSE, but may be set to TRUE
     828                 :  * to enable ALL_TOUCHEd mode when rasterizing cutline polygons.  This is
     829                 :  * useful to ensure that that all pixels overlapping the cutline polygon
     830                 :  * will be selected, not just those whose center point falls within the 
     831                 :  * polygon.
     832                 :  *
     833                 :  * - OPTIMIZE_SIZE: This defaults to FALSE, but may be set to TRUE when
     834                 :  * outputing typically to a compressed dataset (GeoTIFF with COMPRESSED creation
     835                 :  * option set for example) for achieving a smaller file size. This is achieved
     836                 :  * by writing at once data aligned on full blocks of the target dataset, which
     837                 :  * avoids partial writes of compressed blocks and lost space when they are rewritten
     838                 :  * at the end of the file. However sticking to target block size may cause major
     839                 :  * processing slowdown for some particular reprojections.
     840                 :  *
     841                 :  * - NUM_THREADS: (GDAL >= 1.10) Can be set to a numeric value or ALL_CPUS to
     842                 :  * set the number of threads to use to parallelize the computation part of the
     843                 :  * warping. If not set, computation will be done in a single thread.
     844                 :  */
     845                 : 
     846                 : /************************************************************************/
     847                 : /*                       GDALCreateWarpOptions()                        */
     848                 : /************************************************************************/
     849                 : 
     850             738 : GDALWarpOptions * CPL_STDCALL GDALCreateWarpOptions()
     851                 : 
     852                 : {
     853                 :     GDALWarpOptions *psOptions;
     854                 : 
     855             738 :     psOptions = (GDALWarpOptions *) CPLCalloc(sizeof(GDALWarpOptions),1);
     856                 : 
     857             738 :     psOptions->eResampleAlg = GRA_NearestNeighbour;
     858             738 :     psOptions->pfnProgress = GDALDummyProgress;
     859             738 :     psOptions->eWorkingDataType = GDT_Unknown;
     860                 : 
     861             738 :     return psOptions;
     862                 : }
     863                 : 
     864                 : /************************************************************************/
     865                 : /*                       GDALDestroyWarpOptions()                       */
     866                 : /************************************************************************/
     867                 : 
     868             738 : void CPL_STDCALL GDALDestroyWarpOptions( GDALWarpOptions *psOptions )
     869                 : 
     870                 : {
     871             738 :     VALIDATE_POINTER0( psOptions, "GDALDestroyWarpOptions" );
     872                 : 
     873             738 :     CSLDestroy( psOptions->papszWarpOptions );
     874             738 :     CPLFree( psOptions->panSrcBands );
     875             738 :     CPLFree( psOptions->panDstBands );
     876             738 :     CPLFree( psOptions->padfSrcNoDataReal );
     877             738 :     CPLFree( psOptions->padfSrcNoDataImag );
     878             738 :     CPLFree( psOptions->padfDstNoDataReal );
     879             738 :     CPLFree( psOptions->padfDstNoDataImag );
     880             738 :     CPLFree( psOptions->papfnSrcPerBandValidityMaskFunc );
     881             738 :     CPLFree( psOptions->papSrcPerBandValidityMaskFuncArg );
     882                 : 
     883             738 :     if( psOptions->hCutline != NULL )
     884               9 :         OGR_G_DestroyGeometry( (OGRGeometryH) psOptions->hCutline );
     885                 : 
     886             738 :     CPLFree( psOptions );
     887                 : }
     888                 : 
     889                 : 
     890                 : #define COPY_MEM(target,type,count)         \
     891                 :    do { if( (psSrcOptions->target) != NULL && (count) != 0 )     \
     892                 :    {                  \
     893                 :        (psDstOptions->target) = (type *) CPLMalloc(sizeof(type)*(count)); \
     894                 :        memcpy( (psDstOptions->target), (psSrcOptions->target),    \
     895                 :          sizeof(type) * (count) );                \
     896                 :    } \
     897                 :    else \
     898                 :        (psDstOptions->target) = NULL; } while(0)
     899                 : 
     900                 : /************************************************************************/
     901                 : /*                        GDALCloneWarpOptions()                        */
     902                 : /************************************************************************/
     903                 : 
     904                 : GDALWarpOptions * CPL_STDCALL
     905             380 : GDALCloneWarpOptions( const GDALWarpOptions *psSrcOptions )
     906                 : 
     907                 : {
     908             380 :     GDALWarpOptions *psDstOptions = GDALCreateWarpOptions();
     909                 : 
     910             380 :     memcpy( psDstOptions, psSrcOptions, sizeof(GDALWarpOptions) );
     911                 : 
     912             380 :     if( psSrcOptions->papszWarpOptions != NULL )
     913                 :         psDstOptions->papszWarpOptions = 
     914             337 :             CSLDuplicate( psSrcOptions->papszWarpOptions );
     915                 : 
     916             380 :     COPY_MEM( panSrcBands, int, psSrcOptions->nBandCount );
     917             380 :     COPY_MEM( panDstBands, int, psSrcOptions->nBandCount );
     918             380 :     COPY_MEM( padfSrcNoDataReal, double, psSrcOptions->nBandCount );
     919             380 :     COPY_MEM( padfSrcNoDataImag, double, psSrcOptions->nBandCount );
     920             380 :     COPY_MEM( padfDstNoDataReal, double, psSrcOptions->nBandCount );
     921             380 :     COPY_MEM( padfDstNoDataImag, double, psSrcOptions->nBandCount );
     922             380 :     COPY_MEM( papfnSrcPerBandValidityMaskFunc, GDALMaskFunc, 
     923                 :               psSrcOptions->nBandCount );
     924             380 :     psDstOptions->papSrcPerBandValidityMaskFuncArg = NULL;
     925                 : 
     926             380 :     if( psSrcOptions->hCutline != NULL )
     927                 :         psDstOptions->hCutline = 
     928               3 :             OGR_G_Clone( (OGRGeometryH) psSrcOptions->hCutline );
     929             380 :     psDstOptions->dfCutlineBlendDist = psSrcOptions->dfCutlineBlendDist;
     930                 : 
     931             380 :     return psDstOptions;
     932                 : }
     933                 : 
     934                 : /************************************************************************/
     935                 : /*                      GDALSerializeWarpOptions()                      */
     936                 : /************************************************************************/
     937                 : 
     938                 : CPLXMLNode * CPL_STDCALL 
     939               6 : GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
     940                 : 
     941                 : {
     942                 :     CPLXMLNode *psTree;
     943                 : 
     944                 : /* -------------------------------------------------------------------- */
     945                 : /*      Create root.                                                    */
     946                 : /* -------------------------------------------------------------------- */
     947               6 :     psTree = CPLCreateXMLNode( NULL, CXT_Element, "GDALWarpOptions" );
     948                 :     
     949                 : /* -------------------------------------------------------------------- */
     950                 : /*      WarpMemoryLimit                                                 */
     951                 : /* -------------------------------------------------------------------- */
     952                 :     CPLCreateXMLElementAndValue( 
     953                 :         psTree, "WarpMemoryLimit", 
     954               6 :         CPLString().Printf("%g", psWO->dfWarpMemoryLimit ) );
     955                 : 
     956                 : /* -------------------------------------------------------------------- */
     957                 : /*      ResampleAlg                                                     */
     958                 : /* -------------------------------------------------------------------- */
     959                 :     const char *pszAlgName;
     960                 : 
     961               6 :     if( psWO->eResampleAlg == GRA_NearestNeighbour )
     962               6 :         pszAlgName = "NearestNeighbour";
     963               0 :     else if( psWO->eResampleAlg == GRA_Bilinear )
     964               0 :         pszAlgName = "Bilinear";
     965               0 :     else if( psWO->eResampleAlg == GRA_Cubic )
     966               0 :         pszAlgName = "Cubic";
     967               0 :     else if( psWO->eResampleAlg == GRA_CubicSpline )
     968               0 :         pszAlgName = "CubicSpline";
     969               0 :     else if( psWO->eResampleAlg == GRA_Lanczos )
     970               0 :         pszAlgName = "Lanczos";
     971                 :     else
     972               0 :         pszAlgName = "Unknown";
     973                 : 
     974                 :     CPLCreateXMLElementAndValue( 
     975               6 :         psTree, "ResampleAlg", pszAlgName );
     976                 : 
     977                 : /* -------------------------------------------------------------------- */
     978                 : /*      Working Data Type                                               */
     979                 : /* -------------------------------------------------------------------- */
     980                 : 
     981                 :     CPLCreateXMLElementAndValue( 
     982                 :         psTree, "WorkingDataType", 
     983               6 :         GDALGetDataTypeName( psWO->eWorkingDataType ) );
     984                 : 
     985                 : /* -------------------------------------------------------------------- */
     986                 : /*      Name/value warp options.                                        */
     987                 : /* -------------------------------------------------------------------- */
     988                 :     int iWO;
     989                 : 
     990              36 :     for( iWO = 0; psWO->papszWarpOptions != NULL 
     991              18 :              && psWO->papszWarpOptions[iWO] != NULL; iWO++ )
     992                 :     {
     993              12 :         char *pszName = NULL;
     994                 :         const char *pszValue = 
     995              12 :             CPLParseNameValue( psWO->papszWarpOptions[iWO], &pszName );
     996                 : 
     997                 :         CPLXMLNode *psOption = 
     998                 :             CPLCreateXMLElementAndValue( 
     999              12 :                 psTree, "Option", pszValue );
    1000                 : 
    1001                 :         CPLCreateXMLNode( 
    1002                 :             CPLCreateXMLNode( psOption, CXT_Attribute, "name" ),
    1003              12 :             CXT_Text, pszName );
    1004                 : 
    1005              12 :         CPLFree(pszName);
    1006                 :     }
    1007                 : 
    1008                 : /* -------------------------------------------------------------------- */
    1009                 : /*      Source and Destination Data Source                              */
    1010                 : /* -------------------------------------------------------------------- */
    1011               6 :     if( psWO->hSrcDS != NULL )
    1012                 :     {
    1013                 :         CPLCreateXMLElementAndValue( 
    1014                 :             psTree, "SourceDataset", 
    1015               6 :             GDALGetDescription( psWO->hSrcDS ) );
    1016                 :     }
    1017                 :     
    1018               6 :     if( psWO->hDstDS != NULL && strlen(GDALGetDescription(psWO->hDstDS)) != 0 )
    1019                 :     {
    1020                 :         CPLCreateXMLElementAndValue( 
    1021                 :             psTree, "DestinationDataset", 
    1022               0 :             GDALGetDescription( psWO->hDstDS ) );
    1023                 :     }
    1024                 :     
    1025                 : /* -------------------------------------------------------------------- */
    1026                 : /*      Serialize transformer.                                          */
    1027                 : /* -------------------------------------------------------------------- */
    1028               6 :     if( psWO->pfnTransformer != NULL )
    1029                 :     {
    1030                 :         CPLXMLNode *psTransformerContainer;
    1031                 :         CPLXMLNode *psTransformerTree;
    1032                 : 
    1033                 :         psTransformerContainer = 
    1034               6 :             CPLCreateXMLNode( psTree, CXT_Element, "Transformer" );
    1035                 : 
    1036                 :         psTransformerTree = 
    1037                 :             GDALSerializeTransformer( psWO->pfnTransformer,
    1038               6 :                                       psWO->pTransformerArg );
    1039                 : 
    1040               6 :         if( psTransformerTree != NULL )
    1041               6 :             CPLAddXMLChild( psTransformerContainer, psTransformerTree );
    1042                 :     }
    1043                 : 
    1044                 : /* -------------------------------------------------------------------- */
    1045                 : /*      Band count and lists.                                           */
    1046                 : /* -------------------------------------------------------------------- */
    1047               6 :     CPLXMLNode *psBandList = NULL;
    1048                 :     int i;
    1049                 : 
    1050               6 :     if( psWO->nBandCount != 0 )
    1051               6 :         psBandList = CPLCreateXMLNode( psTree, CXT_Element, "BandList" );
    1052                 : 
    1053              21 :     for( i = 0; i < psWO->nBandCount; i++ )
    1054                 :     {
    1055                 :         CPLXMLNode *psBand;
    1056                 : 
    1057              15 :         psBand = CPLCreateXMLNode( psBandList, CXT_Element, "BandMapping" );
    1058              15 :         if( psWO->panSrcBands != NULL )
    1059                 :             CPLCreateXMLNode( 
    1060                 :                 CPLCreateXMLNode( psBand, CXT_Attribute, "src" ),
    1061              15 :                 CXT_Text, CPLString().Printf( "%d", psWO->panSrcBands[i] ) );
    1062              15 :         if( psWO->panDstBands != NULL )
    1063                 :             CPLCreateXMLNode( 
    1064                 :                 CPLCreateXMLNode( psBand, CXT_Attribute, "dst" ),
    1065              15 :                 CXT_Text, CPLString().Printf( "%d", psWO->panDstBands[i] ) );
    1066                 :         
    1067              15 :         if( psWO->padfSrcNoDataReal != NULL )
    1068                 :         {
    1069               8 :             if (CPLIsNan(psWO->padfSrcNoDataReal[i]))
    1070               0 :                 CPLCreateXMLElementAndValue(psBand, "SrcNoDataReal", "nan");
    1071                 :             else
    1072                 :                 CPLCreateXMLElementAndValue( 
    1073                 :                     psBand, "SrcNoDataReal", 
    1074               8 :                     CPLString().Printf( "%.16g", psWO->padfSrcNoDataReal[i] ) );
    1075                 :         }
    1076                 : 
    1077              15 :         if( psWO->padfSrcNoDataImag != NULL )
    1078                 :         {
    1079               8 :             if (CPLIsNan(psWO->padfSrcNoDataImag[i]))
    1080               0 :                 CPLCreateXMLElementAndValue(psBand, "SrcNoDataImag", "nan");
    1081                 :             else
    1082                 :                 CPLCreateXMLElementAndValue( 
    1083                 :                     psBand, "SrcNoDataImag", 
    1084               8 :                     CPLString().Printf( "%.16g", psWO->padfSrcNoDataImag[i] ) );
    1085                 :         }
    1086                 : 
    1087              15 :         if( psWO->padfDstNoDataReal != NULL )
    1088                 :         {
    1089               0 :             if (CPLIsNan(psWO->padfDstNoDataReal[i]))
    1090               0 :                 CPLCreateXMLElementAndValue(psBand, "DstNoDataReal", "nan");
    1091                 :             else
    1092                 :                 CPLCreateXMLElementAndValue( 
    1093                 :                     psBand, "DstNoDataReal", 
    1094               0 :                     CPLString().Printf( "%.16g", psWO->padfDstNoDataReal[i] ) );
    1095                 :         }
    1096                 : 
    1097              15 :         if( psWO->padfDstNoDataImag != NULL )
    1098                 :         {
    1099               0 :             if (CPLIsNan(psWO->padfDstNoDataImag[i]))
    1100               0 :                 CPLCreateXMLElementAndValue(psBand, "DstNoDataImag", "nan");
    1101                 :             else
    1102                 :                 CPLCreateXMLElementAndValue( 
    1103                 :                     psBand, "DstNoDataImag", 
    1104               0 :                     CPLString().Printf( "%.16g", psWO->padfDstNoDataImag[i] ) );
    1105                 :         }
    1106                 :     }
    1107                 : 
    1108                 : /* -------------------------------------------------------------------- */
    1109                 : /*      Alpha bands.                                                    */
    1110                 : /* -------------------------------------------------------------------- */
    1111               6 :     if( psWO->nSrcAlphaBand > 0 )
    1112                 :         CPLCreateXMLElementAndValue( 
    1113                 :             psTree, "SrcAlphaBand", 
    1114               0 :             CPLString().Printf( "%d", psWO->nSrcAlphaBand ) );
    1115                 : 
    1116               6 :     if( psWO->nDstAlphaBand > 0 )
    1117                 :         CPLCreateXMLElementAndValue( 
    1118                 :             psTree, "DstAlphaBand", 
    1119               0 :             CPLString().Printf( "%d", psWO->nDstAlphaBand ) );
    1120                 : 
    1121                 : /* -------------------------------------------------------------------- */
    1122                 : /*      Cutline.                                                        */
    1123                 : /* -------------------------------------------------------------------- */
    1124               6 :     if( psWO->hCutline != NULL )
    1125                 :     {
    1126               0 :         char *pszWKT = NULL;
    1127               0 :         if( OGR_G_ExportToWkt( (OGRGeometryH) psWO->hCutline, &pszWKT )
    1128                 :             == OGRERR_NONE )
    1129                 :         {
    1130               0 :             CPLCreateXMLElementAndValue( psTree, "Cutline", pszWKT );
    1131               0 :             CPLFree( pszWKT );
    1132                 :         }
    1133                 :     }
    1134                 : 
    1135               6 :     if( psWO->dfCutlineBlendDist != 0.0 )
    1136                 :         CPLCreateXMLElementAndValue( 
    1137                 :             psTree, "CutlineBlendDist", 
    1138               0 :             CPLString().Printf( "%.5g", psWO->dfCutlineBlendDist ) );
    1139                 : 
    1140               6 :     return psTree;
    1141                 : }
    1142                 : 
    1143                 : /************************************************************************/
    1144                 : /*                     GDALDeserializeWarpOptions()                     */
    1145                 : /************************************************************************/
    1146                 : 
    1147              45 : GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
    1148                 : 
    1149                 : {
    1150              45 :     CPLErrorReset();
    1151                 : 
    1152                 : /* -------------------------------------------------------------------- */
    1153                 : /*      Verify this is the right kind of object.                        */
    1154                 : /* -------------------------------------------------------------------- */
    1155              45 :     if( psTree == NULL || psTree->eType != CXT_Element
    1156                 :         || !EQUAL(psTree->pszValue,"GDALWarpOptions") )
    1157                 :     {
    1158                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1159               0 :                   "Wrong node, unable to deserialize GDALWarpOptions." );
    1160               0 :         return NULL;
    1161                 :     }
    1162                 : 
    1163                 : /* -------------------------------------------------------------------- */
    1164                 : /*      Create pre-initialized warp options.                            */
    1165                 : /* -------------------------------------------------------------------- */
    1166              45 :     GDALWarpOptions *psWO = GDALCreateWarpOptions();
    1167                 : 
    1168                 : /* -------------------------------------------------------------------- */
    1169                 : /*      Warp memory limit.                                              */
    1170                 : /* -------------------------------------------------------------------- */
    1171                 :     psWO->dfWarpMemoryLimit = 
    1172              45 :         atof(CPLGetXMLValue(psTree,"WarpMemoryLimit","0.0"));
    1173                 : 
    1174                 : /* -------------------------------------------------------------------- */
    1175                 : /*      resample algorithm                                              */
    1176                 : /* -------------------------------------------------------------------- */
    1177                 :     const char *pszValue = 
    1178              45 :         CPLGetXMLValue(psTree,"ResampleAlg","Default");
    1179                 : 
    1180              45 :     if( EQUAL(pszValue,"NearestNeighbour") )
    1181              31 :         psWO->eResampleAlg = GRA_NearestNeighbour;
    1182              14 :     else if( EQUAL(pszValue,"Bilinear") )
    1183               4 :         psWO->eResampleAlg = GRA_Bilinear;
    1184              10 :     else if( EQUAL(pszValue,"Cubic") )
    1185               4 :         psWO->eResampleAlg = GRA_Cubic;
    1186               6 :     else if( EQUAL(pszValue,"CubicSpline") )
    1187               4 :         psWO->eResampleAlg = GRA_CubicSpline;
    1188               2 :     else if( EQUAL(pszValue,"Lanczos") )
    1189               2 :         psWO->eResampleAlg = GRA_Lanczos;
    1190               0 :     else if( EQUAL(pszValue,"Default") )
    1191                 :         /* leave as is */;
    1192                 :     else
    1193                 :     {
    1194                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1195                 :                   "Unrecognise ResampleAlg value '%s'.",
    1196               0 :                   pszValue );
    1197                 :     }
    1198                 : 
    1199                 : /* -------------------------------------------------------------------- */
    1200                 : /*      Working data type.                                              */
    1201                 : /* -------------------------------------------------------------------- */
    1202                 :     psWO->eWorkingDataType = 
    1203                 :         GDALGetDataTypeByName(
    1204              45 :             CPLGetXMLValue(psTree,"WorkingDataType","Unknown"));
    1205                 : 
    1206                 : /* -------------------------------------------------------------------- */
    1207                 : /*      Name/value warp options.                                        */
    1208                 : /* -------------------------------------------------------------------- */
    1209                 :     CPLXMLNode *psItem; 
    1210                 : 
    1211             372 :     for( psItem = psTree->psChild; psItem != NULL; psItem = psItem->psNext )
    1212                 :     {
    1213             327 :         if( psItem->eType == CXT_Element 
    1214                 :             && EQUAL(psItem->pszValue,"Option") )
    1215                 :         {
    1216              37 :             const char *pszName = CPLGetXMLValue(psItem, "Name", NULL );
    1217              37 :             const char *pszValue = CPLGetXMLValue(psItem, "", NULL );
    1218                 : 
    1219              37 :             if( pszName != NULL && pszValue != NULL )
    1220                 :             {
    1221                 :                 psWO->papszWarpOptions = 
    1222                 :                     CSLSetNameValue( psWO->papszWarpOptions, 
    1223              37 :                                      pszName, pszValue );
    1224                 :             }
    1225                 :         }
    1226                 :     }
    1227                 :     
    1228                 : /* -------------------------------------------------------------------- */
    1229                 : /*      Source Dataset.                                                 */
    1230                 : /* -------------------------------------------------------------------- */
    1231              45 :     pszValue = CPLGetXMLValue(psTree,"SourceDataset",NULL);
    1232                 : 
    1233              45 :     if( pszValue != NULL )
    1234              45 :         psWO->hSrcDS = GDALOpenShared( pszValue, GA_ReadOnly );
    1235                 : 
    1236                 : /* -------------------------------------------------------------------- */
    1237                 : /*      Destination Dataset.                                            */
    1238                 : /* -------------------------------------------------------------------- */
    1239              45 :     pszValue = CPLGetXMLValue(psTree,"DestinationDataset",NULL);
    1240                 : 
    1241              45 :     if( pszValue != NULL )
    1242               0 :         psWO->hDstDS = GDALOpenShared( pszValue, GA_Update );
    1243                 : 
    1244                 : /* -------------------------------------------------------------------- */
    1245                 : /*      First, count band mappings so we can establish the bandcount.   */
    1246                 : /* -------------------------------------------------------------------- */
    1247              45 :     CPLXMLNode *psBandTree = CPLGetXMLNode( psTree, "BandList" );
    1248              45 :     CPLXMLNode *psBand = NULL;
    1249                 : 
    1250              45 :     psWO->nBandCount = 0;
    1251                 :     
    1252              45 :     if (psBandTree)
    1253              45 :         psBand = psBandTree->psChild;
    1254                 :     else
    1255               0 :         psBand = NULL;
    1256                 : 
    1257             117 :     for( ; psBand != NULL; psBand = psBand->psNext )
    1258                 :     {
    1259              72 :         if( psBand->eType != CXT_Element 
    1260                 :             || !EQUAL(psBand->pszValue,"BandMapping") )
    1261               0 :             continue;
    1262                 : 
    1263              72 :         psWO->nBandCount++;
    1264                 :     }
    1265                 : 
    1266                 : /* ==================================================================== */
    1267                 : /*      Now actually process each bandmapping.                          */
    1268                 : /* ==================================================================== */
    1269              45 :     int iBand = 0;
    1270                 : 
    1271              45 :     if (psBandTree)
    1272              45 :         psBand = psBandTree->psChild;
    1273                 :     else
    1274               0 :         psBand = NULL;
    1275                 : 
    1276             117 :     for( ; psBand != NULL; psBand = psBand->psNext )
    1277                 :     {
    1278              72 :         if( psBand->eType != CXT_Element 
    1279                 :             || !EQUAL(psBand->pszValue,"BandMapping") )
    1280               0 :             continue;
    1281                 : 
    1282                 : /* -------------------------------------------------------------------- */
    1283                 : /*      Source band                                                     */
    1284                 : /* -------------------------------------------------------------------- */
    1285              72 :         if( psWO->panSrcBands == NULL )
    1286              45 :             psWO->panSrcBands = (int *)CPLMalloc(sizeof(int)*psWO->nBandCount);
    1287                 :         
    1288              72 :         pszValue = CPLGetXMLValue(psBand,"src",NULL);
    1289              72 :         if( pszValue == NULL )
    1290               0 :             psWO->panSrcBands[iBand] = iBand+1;
    1291                 :         else
    1292              72 :             psWO->panSrcBands[iBand] = atoi(pszValue);
    1293                 :         
    1294                 : /* -------------------------------------------------------------------- */
    1295                 : /*      Destination band.                                               */
    1296                 : /* -------------------------------------------------------------------- */
    1297              72 :         pszValue = CPLGetXMLValue(psBand,"dst",NULL);
    1298              72 :         if( pszValue != NULL )
    1299                 :         {
    1300              72 :             if( psWO->panDstBands == NULL )
    1301                 :                 psWO->panDstBands = 
    1302              45 :                     (int *) CPLMalloc(sizeof(int)*psWO->nBandCount);
    1303                 : 
    1304              72 :             psWO->panDstBands[iBand] = atoi(pszValue);
    1305                 :         }
    1306                 :         
    1307                 : /* -------------------------------------------------------------------- */
    1308                 : /*      Source nodata.                                                  */
    1309                 : /* -------------------------------------------------------------------- */
    1310              72 :         pszValue = CPLGetXMLValue(psBand,"SrcNoDataReal",NULL);
    1311              72 :         if( pszValue != NULL )
    1312                 :         {
    1313              16 :             if( psWO->padfSrcNoDataReal == NULL )
    1314                 :                 psWO->padfSrcNoDataReal = 
    1315               9 :                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
    1316                 : 
    1317              16 :             psWO->padfSrcNoDataReal[iBand] = CPLAtofM(pszValue);
    1318                 :         }
    1319                 :         
    1320              72 :         pszValue = CPLGetXMLValue(psBand,"SrcNoDataImag",NULL);
    1321              72 :         if( pszValue != NULL )
    1322                 :         {
    1323              16 :             if( psWO->padfSrcNoDataImag == NULL )
    1324                 :                 psWO->padfSrcNoDataImag = 
    1325               9 :                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
    1326                 : 
    1327              16 :             psWO->padfSrcNoDataImag[iBand] = CPLAtofM(pszValue);
    1328                 :         }
    1329                 :         
    1330                 : /* -------------------------------------------------------------------- */
    1331                 : /*      Destination nodata.                                             */
    1332                 : /* -------------------------------------------------------------------- */
    1333              72 :         pszValue = CPLGetXMLValue(psBand,"DstNoDataReal",NULL);
    1334              72 :         if( pszValue != NULL )
    1335                 :         {
    1336               8 :             if( psWO->padfDstNoDataReal == NULL )
    1337                 :                 psWO->padfDstNoDataReal = 
    1338               8 :                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
    1339                 : 
    1340               8 :             psWO->padfDstNoDataReal[iBand] = CPLAtofM(pszValue);
    1341                 :         }
    1342                 :         
    1343              72 :         pszValue = CPLGetXMLValue(psBand,"DstNoDataImag",NULL);
    1344              72 :         if( pszValue != NULL )
    1345                 :         {
    1346               8 :             if( psWO->padfDstNoDataImag == NULL )
    1347                 :                 psWO->padfDstNoDataImag = 
    1348               8 :                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
    1349                 : 
    1350               8 :             psWO->padfDstNoDataImag[iBand] = CPLAtofM(pszValue);
    1351                 :         }
    1352                 :         
    1353              72 :         iBand++;
    1354                 :     }
    1355                 : 
    1356                 : /* -------------------------------------------------------------------- */
    1357                 : /*      Alpha bands.                                                    */
    1358                 : /* -------------------------------------------------------------------- */
    1359                 :     psWO->nSrcAlphaBand = 
    1360              45 :         atoi( CPLGetXMLValue( psTree, "SrcAlphaBand", "0" ) );
    1361                 :     psWO->nDstAlphaBand = 
    1362              45 :         atoi( CPLGetXMLValue( psTree, "DstAlphaBand", "0" ) );
    1363                 : 
    1364                 : /* -------------------------------------------------------------------- */
    1365                 : /*      Cutline.                                                        */
    1366                 : /* -------------------------------------------------------------------- */
    1367              45 :     const char *pszWKT = CPLGetXMLValue( psTree, "Cutline", NULL );
    1368              45 :     if( pszWKT )
    1369                 :     {
    1370                 :         OGR_G_CreateFromWkt( (char **) &pszWKT, NULL, 
    1371               3 :                              (OGRGeometryH *) (&psWO->hCutline) );
    1372                 :     }
    1373                 : 
    1374                 :     psWO->dfCutlineBlendDist =
    1375              45 :         atof( CPLGetXMLValue( psTree, "CutlineBlendDist", "0" ) );
    1376                 : 
    1377                 : /* -------------------------------------------------------------------- */
    1378                 : /*      Transformation.                                                 */
    1379                 : /* -------------------------------------------------------------------- */
    1380              45 :     CPLXMLNode *psTransformer = CPLGetXMLNode( psTree, "Transformer" );
    1381                 : 
    1382              45 :     if( psTransformer != NULL && psTransformer->psChild != NULL )
    1383                 :     {
    1384                 :         GDALDeserializeTransformer( psTransformer->psChild, 
    1385                 :                                     &(psWO->pfnTransformer),
    1386              45 :                                     &(psWO->pTransformerArg) );
    1387                 :     }
    1388                 : 
    1389                 : /* -------------------------------------------------------------------- */
    1390                 : /*      If any error has occured, cleanup else return success.          */
    1391                 : /* -------------------------------------------------------------------- */
    1392              45 :     if( CPLGetLastErrorNo() != CE_None )
    1393                 :     {
    1394               0 :         if ( psWO->pTransformerArg )
    1395                 :         {
    1396               0 :             GDALDestroyTransformer( psWO->pTransformerArg );
    1397               0 :             psWO->pTransformerArg = NULL;
    1398                 :         }
    1399               0 :         if( psWO->hSrcDS != NULL )
    1400                 :         {
    1401               0 :             GDALClose( psWO->hSrcDS );
    1402               0 :             psWO->hSrcDS = NULL;
    1403                 :         }
    1404               0 :         if( psWO->hDstDS != NULL )
    1405                 :         {
    1406               0 :             GDALClose( psWO->hDstDS );
    1407               0 :             psWO->hDstDS = NULL;
    1408                 :         }
    1409               0 :         GDALDestroyWarpOptions( psWO );
    1410               0 :         return NULL;
    1411                 :     }
    1412                 :     else
    1413              45 :         return psWO;
    1414                 : }

Generated by: LCOV version 1.7