LCOV - code coverage report
Current view: directory - alg - gdalwarper.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 369 252 68.3 %
Date: 2010-01-09 Functions: 10 9 90.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalwarper.cpp 18092 2009-11-24 20:48:51Z 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                 : 
      35                 : CPL_CVSID("$Id: gdalwarper.cpp 18092 2009-11-24 20:48:51Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                         GDALReprojectImage()                         */
      39                 : /************************************************************************/
      40                 : 
      41                 : /**
      42                 :  * Reproject image.
      43                 :  *
      44                 :  * This is a convenience function utilizing the GDALWarpOperation class to
      45                 :  * reproject an image from a source to a destination.  In particular, this
      46                 :  * function takes care of establishing the transformation function to
      47                 :  * implement the reprojection, and will default a variety of other 
      48                 :  * warp options. 
      49                 :  *
      50                 :  * By default all bands are transferred, with no masking or nodata values
      51                 :  * in effect.  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              18 : 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              18 :                                          TRUE, 1000.0, 0 );
      95                 : 
      96              18 :     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              18 :     if( psOptions == NULL )
     104              18 :         psWOptions = GDALCreateWarpOptions();
     105                 :     else
     106               0 :         psWOptions = GDALCloneWarpOptions( psOptions );
     107                 : 
     108              18 :     psWOptions->eResampleAlg = eResampleAlg;
     109                 : 
     110                 : /* -------------------------------------------------------------------- */
     111                 : /*      Set transform.                                                  */
     112                 : /* -------------------------------------------------------------------- */
     113              18 :     if( dfMaxError > 0.0 )
     114                 :     {
     115                 :         psWOptions->pTransformerArg = 
     116                 :             GDALCreateApproxTransformer( GDALGenImgProjTransform, 
     117               0 :                                          hTransformArg, dfMaxError );
     118                 : 
     119               0 :         psWOptions->pfnTransformer = GDALApproxTransform;
     120                 :     }
     121                 :     else
     122                 :     {
     123              18 :         psWOptions->pfnTransformer = GDALGenImgProjTransform;
     124              18 :         psWOptions->pTransformerArg = hTransformArg;
     125                 :     }
     126                 : 
     127                 : /* -------------------------------------------------------------------- */
     128                 : /*      Set file and band mapping.                                      */
     129                 : /* -------------------------------------------------------------------- */
     130                 :     int  iBand;
     131                 : 
     132              18 :     psWOptions->hSrcDS = hSrcDS;
     133              18 :     psWOptions->hDstDS = hDstDS;
     134                 : 
     135              18 :     if( psWOptions->nBandCount == 0 )
     136                 :     {
     137                 :         psWOptions->nBandCount = MIN(GDALGetRasterCount(hSrcDS),
     138              18 :                                      GDALGetRasterCount(hDstDS));
     139                 :         
     140                 :         psWOptions->panSrcBands = (int *) 
     141              18 :             CPLMalloc(sizeof(int) * psWOptions->nBandCount);
     142                 :         psWOptions->panDstBands = (int *) 
     143              18 :             CPLMalloc(sizeof(int) * psWOptions->nBandCount);
     144                 : 
     145              36 :         for( iBand = 0; iBand < psWOptions->nBandCount; iBand++ )
     146                 :         {
     147              18 :             psWOptions->panSrcBands[iBand] = iBand+1;
     148              18 :             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              36 :     for( iBand = 0; iBand < psWOptions->nBandCount; iBand++ )
     157                 :     {
     158              18 :         GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, iBand+1 );
     159              18 :         int             bGotNoData = FALSE;
     160                 :         double          dfNoDataValue;
     161                 :         
     162              18 :         dfNoDataValue = GDALGetRasterNoDataValue( hBand, &bGotNoData );
     163              18 :         if( bGotNoData )
     164                 :         {
     165               5 :             if( psWOptions->padfSrcNoDataReal == NULL )
     166                 :             {
     167                 :                 int  ii;
     168                 : 
     169                 :                 psWOptions->padfSrcNoDataReal = (double *) 
     170               5 :                     CPLMalloc(sizeof(double) * psWOptions->nBandCount);
     171                 :                 psWOptions->padfSrcNoDataImag = (double *) 
     172               5 :                     CPLMalloc(sizeof(double) * psWOptions->nBandCount);
     173                 : 
     174              10 :                 for( ii = 0; ii < psWOptions->nBandCount; ii++ )
     175                 :                 {
     176               5 :                     psWOptions->padfSrcNoDataReal[ii] = -1.1e20;
     177               5 :                     psWOptions->padfSrcNoDataImag[ii] = 0.0;
     178                 :                 }
     179                 :             }
     180                 : 
     181               5 :             psWOptions->padfSrcNoDataReal[iBand] = dfNoDataValue;
     182                 :         }
     183                 :     }
     184                 : 
     185                 : /* -------------------------------------------------------------------- */
     186                 : /*      Set the progress function.                                      */
     187                 : /* -------------------------------------------------------------------- */
     188              18 :     if( pfnProgress != NULL )
     189                 :     {
     190               0 :         psWOptions->pfnProgress = pfnProgress;
     191               0 :         psWOptions->pProgressArg = pProgressArg;
     192                 :     }
     193                 : 
     194                 : /* -------------------------------------------------------------------- */
     195                 : /*      Create a warp options based on the options.                     */
     196                 : /* -------------------------------------------------------------------- */
     197              18 :     GDALWarpOperation  oWarper;
     198                 :     CPLErr eErr;
     199                 : 
     200              18 :     eErr = oWarper.Initialize( psWOptions );
     201                 : 
     202              18 :     if( eErr == CE_None )
     203                 :         eErr = oWarper.ChunkAndWarpImage( 0, 0, 
     204                 :                                           GDALGetRasterXSize(hDstDS),
     205              18 :                                           GDALGetRasterYSize(hDstDS) );
     206                 : 
     207                 : /* -------------------------------------------------------------------- */
     208                 : /*      Cleanup.                                                        */
     209                 : /* -------------------------------------------------------------------- */
     210              18 :     GDALDestroyGenImgProjTransformer( hTransformArg );
     211                 : 
     212              18 :     if( dfMaxError > 0.0 )
     213               0 :         GDALDestroyApproxTransformer( psWOptions->pTransformerArg );
     214                 :         
     215              18 :     GDALDestroyWarpOptions( psWOptions );
     216                 : 
     217              18 :     return eErr;
     218                 : }
     219                 : 
     220                 : /************************************************************************/
     221                 : /*                    GDALCreateAndReprojectImage()                     */
     222                 : /*                                                                      */
     223                 : /*      This is a "quicky" reprojection API.                            */
     224                 : /************************************************************************/
     225                 : 
     226               0 : CPLErr CPL_STDCALL GDALCreateAndReprojectImage( 
     227                 :     GDALDatasetH hSrcDS, const char *pszSrcWKT, 
     228                 :     const char *pszDstFilename, const char *pszDstWKT,
     229                 :     GDALDriverH hDstDriver, char **papszCreateOptions,
     230                 :     GDALResampleAlg eResampleAlg, double dfWarpMemoryLimit, double dfMaxError,
     231                 :     GDALProgressFunc pfnProgress, void *pProgressArg, 
     232                 :     GDALWarpOptions *psOptions )
     233                 :     
     234                 : {
     235               0 :     VALIDATE_POINTER1( hSrcDS, "GDALCreateAndReprojectImage", CE_Failure );
     236                 : 
     237                 : /* -------------------------------------------------------------------- */
     238                 : /*      Default a few parameters.                                       */
     239                 : /* -------------------------------------------------------------------- */
     240               0 :     if( hDstDriver == NULL )
     241                 :     {
     242               0 :         hDstDriver = GDALGetDriverByName( "GTiff" );
     243               0 :         if (hDstDriver == NULL)
     244                 :         {
     245                 :             CPLError(CE_Failure, CPLE_AppDefined,
     246               0 :                      "GDALCreateAndReprojectImage needs GTiff driver");
     247               0 :             return CE_Failure;
     248                 :         }
     249                 :     }
     250                 : 
     251               0 :     if( pszSrcWKT == NULL )
     252               0 :         pszSrcWKT = GDALGetProjectionRef( hSrcDS );
     253                 : 
     254               0 :     if( pszDstWKT == NULL )
     255               0 :         pszDstWKT = pszSrcWKT;
     256                 : 
     257                 : /* -------------------------------------------------------------------- */
     258                 : /*      Create a transformation object from the source to               */
     259                 : /*      destination coordinate system.                                  */
     260                 : /* -------------------------------------------------------------------- */
     261                 :     void *hTransformArg;
     262                 : 
     263                 :     hTransformArg = 
     264                 :         GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, NULL, pszDstWKT, 
     265               0 :                                          TRUE, 1000.0, 0 );
     266                 : 
     267               0 :     if( hTransformArg == NULL )
     268               0 :         return CE_Failure;
     269                 : 
     270                 : /* -------------------------------------------------------------------- */
     271                 : /*      Get approximate output definition.                              */
     272                 : /* -------------------------------------------------------------------- */
     273                 :     double adfDstGeoTransform[6];
     274                 :     int    nPixels, nLines;
     275                 : 
     276               0 :     if( GDALSuggestedWarpOutput( hSrcDS, 
     277                 :                                  GDALGenImgProjTransform, hTransformArg, 
     278                 :                                  adfDstGeoTransform, &nPixels, &nLines )
     279                 :         != CE_None )
     280               0 :         return CE_Failure;
     281                 : 
     282               0 :     GDALDestroyGenImgProjTransformer( hTransformArg );
     283                 : 
     284                 : /* -------------------------------------------------------------------- */
     285                 : /*      Create the output file.                                         */
     286                 : /* -------------------------------------------------------------------- */
     287                 :     GDALDatasetH hDstDS;
     288                 : 
     289                 :     hDstDS = GDALCreate( hDstDriver, pszDstFilename, nPixels, nLines, 
     290                 :                          GDALGetRasterCount(hSrcDS),
     291                 :                          GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1)),
     292               0 :                          papszCreateOptions );
     293                 : 
     294               0 :     if( hDstDS == NULL )
     295               0 :         return CE_Failure;
     296                 : 
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      Write out the projection definition.                            */
     299                 : /* -------------------------------------------------------------------- */
     300               0 :     GDALSetProjection( hDstDS, pszDstWKT );
     301               0 :     GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
     302                 : 
     303                 : /* -------------------------------------------------------------------- */
     304                 : /*      Perform the reprojection.                                       */
     305                 : /* -------------------------------------------------------------------- */
     306                 :     CPLErr eErr ;
     307                 : 
     308                 :     eErr = 
     309                 :         GDALReprojectImage( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT, 
     310                 :                             eResampleAlg, dfWarpMemoryLimit, dfMaxError,
     311               0 :                             pfnProgress, pProgressArg, psOptions );
     312                 : 
     313               0 :     GDALClose( hDstDS );
     314                 : 
     315               0 :     return eErr;
     316                 : }
     317                 : 
     318                 : /************************************************************************/
     319                 : /*                        GDALWarpNoDataMasker()                        */
     320                 : /*                                                                      */
     321                 : /*      GDALMaskFunc for establishing a validity mask for a source      */
     322                 : /*      band based on a provided NODATA value.                          */
     323                 : /************************************************************************/
     324                 : 
     325                 : CPLErr 
     326               8 : GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType, 
     327                 :                       int /* nXOff */, int /* nYOff */, int nXSize, int nYSize,
     328                 :                       GByte **ppImageData, 
     329                 :                       int bMaskIsFloat, void *pValidityMask )
     330                 : 
     331                 : {
     332               8 :     double *padfNoData = (double *) pMaskFuncArg;
     333               8 :     GUInt32 *panValidityMask = (GUInt32 *) pValidityMask;
     334                 : 
     335               8 :     if( nBandCount != 1 || bMaskIsFloat )
     336                 :     {
     337                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     338               0 :                   "Invalid nBandCount or bMaskIsFloat argument in SourceNoDataMask" );
     339               0 :         return CE_Failure;
     340                 :     }
     341                 : 
     342               8 :     switch( eType )
     343                 :     {
     344                 :       case GDT_Byte:
     345                 :       {
     346               3 :           int nNoData = (int) padfNoData[0];
     347               3 :           GByte *pabyData = (GByte *) *ppImageData;
     348                 :           int iOffset;
     349                 : 
     350                 :           // nothing to do if value is out of range.
     351               6 :           if( padfNoData[0] < 0.0 || padfNoData[0] > 255.000001 
     352               3 :               || padfNoData[1] != 0.0 )
     353               0 :               return CE_None;
     354                 : 
     355           66380 :           for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
     356                 :           {
     357           66377 :               if( pabyData[iOffset] == nNoData )
     358                 :               {
     359           66077 :                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
     360                 :               }
     361                 :           }
     362                 :       }
     363               3 :       break;
     364                 :       
     365                 :       case GDT_Int16:
     366                 :       {
     367               5 :           int nNoData = (int) padfNoData[0];
     368               5 :           GInt16 *panData = (GInt16 *) *ppImageData;
     369                 :           int iOffset;
     370                 : 
     371                 :           // nothing to do if value is out of range.
     372              10 :           if( padfNoData[0] < -32768 || padfNoData[0] > 32767
     373               5 :               || padfNoData[1] != 0.0 )
     374               0 :               return CE_None;
     375                 : 
     376           45829 :           for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
     377                 :           {
     378           45824 :               if( panData[iOffset] == nNoData )
     379                 :               {
     380             715 :                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
     381                 :               }
     382                 :           }
     383                 :       }
     384               5 :       break;
     385                 :       
     386                 :       case GDT_UInt16:
     387                 :       {
     388               0 :           int nNoData = (int) padfNoData[0];
     389               0 :           GUInt16 *panData = (GUInt16 *) *ppImageData;
     390                 :           int iOffset;
     391                 : 
     392                 :           // nothing to do if value is out of range.
     393               0 :           if( padfNoData[0] < 0 || padfNoData[0] > 65535
     394               0 :               || padfNoData[1] != 0.0 )
     395               0 :               return CE_None;
     396                 : 
     397               0 :           for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
     398                 :           {
     399               0 :               if( panData[iOffset] == nNoData )
     400                 :               {
     401               0 :                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
     402                 :               }
     403                 :           }
     404                 :       }
     405               0 :       break;
     406                 :       
     407                 :       case GDT_Float32:
     408                 :       {
     409               0 :           float fNoData = (float) padfNoData[0];
     410               0 :           float *pafData = (float *) *ppImageData;
     411                 :           int iOffset;
     412                 : 
     413                 :           // nothing to do if value is out of range.
     414               0 :           if( padfNoData[1] != 0.0 )
     415               0 :               return CE_None;
     416                 : 
     417               0 :           for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
     418                 :           {
     419               0 :               if( pafData[iOffset] == fNoData )
     420                 :               {
     421               0 :                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
     422                 :               }
     423                 :           }
     424                 :       }
     425               0 :       break;
     426                 :       
     427                 :       default:
     428                 :       {
     429                 :           double  *padfWrk;
     430                 :           int     iLine, iPixel;
     431               0 :           int     nWordSize = GDALGetDataTypeSize(eType)/8;
     432                 : 
     433               0 :           padfWrk = (double *) CPLMalloc(nXSize * sizeof(double) * 2);
     434               0 :           for( iLine = 0; iLine < nYSize; iLine++ )
     435                 :           {
     436                 :               GDALCopyWords( ((GByte *) *ppImageData)+nWordSize*iLine*nXSize, 
     437                 :                              eType, nWordSize,
     438               0 :                              padfWrk, GDT_CFloat64, 16, nXSize );
     439                 :               
     440               0 :               for( iPixel = 0; iPixel < nXSize; iPixel++ )
     441                 :               {
     442               0 :                   if( padfWrk[iPixel*2] == padfNoData[0]
     443               0 :                       && padfWrk[iPixel*2+1] == padfNoData[1] )
     444                 :                   {
     445               0 :                       int iOffset = iPixel + iLine * nXSize;
     446                 :                       
     447                 :                       panValidityMask[iOffset>>5] &=
     448               0 :                           ~(0x01 << (iOffset & 0x1f));
     449                 :                   }
     450                 :               }
     451                 :               
     452                 :           }
     453                 : 
     454               0 :           CPLFree( padfWrk );
     455                 :       }
     456                 :       break;
     457                 :     }
     458                 : 
     459               8 :     return CE_None;
     460                 : }
     461                 : 
     462                 : /************************************************************************/
     463                 : /*                       GDALWarpSrcAlphaMasker()                       */
     464                 : /*                                                                      */
     465                 : /*      GDALMaskFunc for reading source simple 8bit alpha mask          */
     466                 : /*      information and building a floating point density mask from     */
     467                 : /*      it.                                                             */
     468                 : /************************************************************************/
     469                 : 
     470                 : CPLErr 
     471               7 : GDALWarpSrcAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType, 
     472                 :                         int nXOff, int nYOff, int nXSize, int nYSize,
     473                 :                         GByte ** /*ppImageData */,
     474                 :                         int bMaskIsFloat, void *pValidityMask )
     475                 : 
     476                 : {
     477               7 :     GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
     478               7 :     float *pafMask = (float *) pValidityMask;
     479                 : 
     480                 : /* -------------------------------------------------------------------- */
     481                 : /*      Do some minimal checking.                                       */
     482                 : /* -------------------------------------------------------------------- */
     483               7 :     if( !bMaskIsFloat )
     484                 :     {
     485                 :         CPLAssert( FALSE );
     486               0 :         return CE_Failure;
     487                 :     }
     488                 : 
     489               7 :     if( psWO == NULL || psWO->nSrcAlphaBand < 1 )
     490                 :     {
     491                 :         CPLAssert( FALSE );
     492               0 :         return CE_Failure;
     493                 :     }
     494                 : 
     495                 : /* -------------------------------------------------------------------- */
     496                 : /*      Read the alpha band.                                            */
     497                 : /* -------------------------------------------------------------------- */
     498                 :     CPLErr eErr;
     499                 :     GDALRasterBandH hAlphaBand = GDALGetRasterBand( psWO->hSrcDS, 
     500               7 :                                                     psWO->nSrcAlphaBand );
     501               7 :     if (hAlphaBand == NULL)
     502               0 :         return CE_Failure;
     503                 : 
     504                 :     eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize, 
     505               7 :                          pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
     506                 : 
     507               7 :     if( eErr != CE_None )
     508               0 :         return eErr;
     509                 : 
     510                 : /* -------------------------------------------------------------------- */
     511                 : /*      Rescale from 0-255 to 0.0-1.0.                                  */
     512                 : /* -------------------------------------------------------------------- */
     513            2807 :     for( int iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
     514                 :     {                                    //  (1/255)
     515            2800 :         pafMask[iPixel] = (float)( pafMask[iPixel] * 0.00392157 );
     516            2800 :         pafMask[iPixel] = MIN( 1.0F, pafMask[iPixel] );
     517                 :     }
     518                 : 
     519               7 :     return CE_None;
     520                 : }
     521                 : 
     522                 : /************************************************************************/
     523                 : /*                       GDALWarpDstAlphaMasker()                       */
     524                 : /*                                                                      */
     525                 : /*      GDALMaskFunc for reading or writing the destination simple      */
     526                 : /*      8bit alpha mask information and building a floating point       */
     527                 : /*      density mask from it.   Note, writing is distinguished          */
     528                 : /*      negative bandcount.                                             */
     529                 : /************************************************************************/
     530                 : 
     531                 : CPLErr 
     532              18 : GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
     533                 :                         int nXOff, int nYOff, int nXSize, int nYSize,
     534                 :                         GByte ** /*ppImageData */,
     535                 :                         int bMaskIsFloat, void *pValidityMask )
     536                 : 
     537                 : {
     538              18 :     GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
     539              18 :     float *pafMask = (float *) pValidityMask;
     540                 :     int iPixel;
     541                 :     CPLErr eErr;
     542                 : 
     543                 : /* -------------------------------------------------------------------- */
     544                 : /*      Do some minimal checking.                                       */
     545                 : /* -------------------------------------------------------------------- */
     546              18 :     if( !bMaskIsFloat )
     547                 :     {
     548                 :         CPLAssert( FALSE );
     549               0 :         return CE_Failure;
     550                 :     }
     551                 : 
     552              18 :     if( psWO == NULL || psWO->nDstAlphaBand < 1 )
     553                 :     {
     554                 :         CPLAssert( FALSE );
     555               0 :         return CE_Failure;
     556                 :     }
     557                 : 
     558                 :     GDALRasterBandH hAlphaBand = 
     559              18 :         GDALGetRasterBand( psWO->hDstDS, psWO->nDstAlphaBand );
     560              18 :     if (hAlphaBand == NULL)
     561               0 :         return CE_Failure;
     562                 : 
     563                 : /* -------------------------------------------------------------------- */
     564                 : /*      Read alpha case.            */
     565                 : /* -------------------------------------------------------------------- */
     566              18 :     if( nBandCount >= 0 )
     567                 :     {
     568                 :         const char *pszInitDest = 
     569               9 :             CSLFetchNameValue( psWO->papszWarpOptions, "INIT_DEST" );
     570                 : 
     571                 :         // Special logic for destinations being initialized on the fly.
     572               9 :         if( pszInitDest != NULL )
     573                 :         {
     574          526797 :             for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
     575          526788 :                 pafMask[iPixel] = 0.0;
     576               9 :             return CE_None;
     577                 :         }
     578                 : 
     579                 :         // Read data.
     580                 :         eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
     581               0 :                              pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
     582                 :         
     583               0 :         if( eErr != CE_None )
     584               0 :             return eErr;
     585                 : 
     586                 :         // rescale.
     587               0 :         for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
     588                 :         {
     589               0 :             pafMask[iPixel] = (float) (pafMask[iPixel] * 0.00392157);
     590               0 :             pafMask[iPixel] = MIN( 1.0F, pafMask[iPixel] );
     591                 :         }
     592                 : 
     593               0 :         return CE_None;
     594                 :     }
     595                 : 
     596                 : /* -------------------------------------------------------------------- */
     597                 : /*      Write alpha case.                                               */
     598                 : /* -------------------------------------------------------------------- */
     599                 :     else
     600                 :     {
     601          526797 :         for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
     602          526788 :             pafMask[iPixel] = (int) ( pafMask[iPixel] * 255.1 );
     603                 :         
     604                 :         // Write data.
     605                 : 
     606                 :         /* The VRT warper will pass destination sizes that may exceed */
     607                 :         /* the size of the raster for the partial blocks at the right */
     608                 :         /* and bottom of the band. So let's adjust the size */
     609               9 :         int nDstXSize = nXSize;
     610               9 :         if (nXOff + nXSize > GDALGetRasterXSize(hAlphaBand))
     611               8 :             nDstXSize = GDALGetRasterXSize(hAlphaBand) - nXOff;
     612               9 :         int nDstYSize = nYSize;
     613               9 :         if (nYOff + nYSize > GDALGetRasterYSize(hAlphaBand))
     614               8 :             nDstYSize = GDALGetRasterYSize(hAlphaBand) - nYOff;
     615                 : 
     616                 :         eErr = GDALRasterIO( hAlphaBand, GF_Write, 
     617                 :                              nXOff, nYOff, nDstXSize, nDstYSize, 
     618                 :                              pafMask, nDstXSize, nDstYSize, GDT_Float32,
     619               9 :                              0, sizeof(float) * nXSize );
     620               9 :         return eErr;
     621                 :     }
     622                 : }
     623                 : 
     624                 : /************************************************************************/
     625                 : /* ==================================================================== */
     626                 : /*                           GDALWarpOptions                            */
     627                 : /* ==================================================================== */
     628                 : /************************************************************************/
     629                 : 
     630                 : /**
     631                 :  * \var char **GDALWarpOptions::papszWarpOptions;
     632                 :  *
     633                 :  * A string list of additional options controlling the warp operation in
     634                 :  * name=value format.  A suitable string list can be prepared with 
     635                 :  * CSLSetNameValue().
     636                 :  *
     637                 :  * The following values are currently supported:
     638                 :  * 
     639                 :  *  - INIT_DEST=[value] or INIT_DEST=NO_DATA: This option forces the 
     640                 :  * destination image to be initialized to the indicated value (for all bands)
     641                 :  * or indicates that it should be initialized to the NO_DATA value in
     642                 :  * padfDstNoDataReal/padfDstNoDataImag.  If this value isn't set the
     643                 :  * destination image will be read and overlayed.  
     644                 :  *
     645                 :  * - WRITE_FLUSH=YES/NO: This option forces a flush to disk of data after
     646                 :  * each chunk is processed.  In some cases this helps ensure a serial 
     647                 :  * writing of the output data otherwise a block of data may be written to disk
     648                 :  * each time a block of data is read for the input buffer resulting in alot
     649                 :  * of extra seeking around the disk, and reduced IO throughput.  The default
     650                 :  * at this time is NO.
     651                 :  *
     652                 :  * - SKIP_NOSOURCE=YES/NO: Skip all processing for chunks for which there
     653                 :  * is no corresponding input data.  This will disable initializing the 
     654                 :  * destination (INIT_DEST) and all other processing, and so should be used
     655                 :  * careful.  Mostly useful to short circuit a lot of extra work in mosaicing 
     656                 :  * situations.
     657                 :  * 
     658                 :  * - UNIFIED_SRC_NODATA=YES/[NO]: By default nodata masking values considered
     659                 :  * independently for each band.  However, sometimes it is desired to treat all
     660                 :  * bands as nodata if and only if, all bands match the corresponding nodata
     661                 :  * values.  To get this behavior set this option to YES. 
     662                 :  *
     663                 :  * Normally when computing the source raster data to 
     664                 :  * load to generate a particular output area, the warper samples transforms
     665                 :  * 21 points along each edge of the destination region back onto the source
     666                 :  * file, and uses this to compute a bounding window on the source image that
     667                 :  * is sufficient.  Depending on the transformation in effect, the source 
     668                 :  * window may be a bit too small, or even missing large areas.  Problem 
     669                 :  * situations are those where the transformation is very non-linear or 
     670                 :  * "inside out".  Examples are transforming from WGS84 to Polar Steregraphic
     671                 :  * for areas around the pole, or transformations where some of the image is
     672                 :  * untransformable.  The following options provide some additional control
     673                 :  * to deal with errors in computing the source window:
     674                 :  * 
     675                 :  * - SAMPLE_GRID=YES/NO: Setting this option to YES will force the sampling to 
     676                 :  * include internal points as well as edge points which can be important if
     677                 :  * the transformation is esoteric inside out, or if large sections of the
     678                 :  * destination image are not transformable into the source coordinate system.
     679                 :  *
     680                 :  * - SAMPLE_STEPS: Modifies the density of the sampling grid.  The default
     681                 :  * number of steps is 21.   Increasing this can increase the computational
     682                 :  * cost, but improves the accuracy with which the source region is computed.
     683                 :  *
     684                 :  * - SOURCE_EXTRA: This is a number of extra pixels added around the source
     685                 :  * window for a given request, and by default it is 1 to take care of rounding
     686                 :  * error.  Setting this larger will incease the amount of data that needs to
     687                 :  * be read, but can avoid missing source data.  
     688                 :  *
     689                 :  * - CUTLINE: This may contain the WKT geometry for a cutline.  It will
     690                 :  * be converted into a geometry by GDALWarpOperation::Initialize() and assigned
     691                 :  * to the GDALWarpOptions hCutline field.
     692                 :  *
     693                 :  * - CUTLINE_BLEND_DIST: This may be set with a distance in pixels which
     694                 :  * will be assigned to the dfCutlineBlendDist field in the GDALWarpOptions.
     695                 :  *
     696                 :  * - CUTLINE_ALL_TOUCHED: This defaults to FALSE, but may be set to TRUE
     697                 :  * to enable ALL_TOUCHEd mode when rasterizing cutline polygons.  This is
     698                 :  * useful to ensure that that all pixels overlapping the cutline polygon
     699                 :  * will be selected, not just those whose center point falls within the 
     700                 :  * polygon.
     701                 :  */
     702                 : 
     703                 : /************************************************************************/
     704                 : /*                       GDALCreateWarpOptions()                        */
     705                 : /************************************************************************/
     706                 : 
     707             606 : GDALWarpOptions * CPL_STDCALL GDALCreateWarpOptions()
     708                 : 
     709                 : {
     710                 :     GDALWarpOptions *psOptions;
     711                 : 
     712             606 :     psOptions = (GDALWarpOptions *) CPLCalloc(sizeof(GDALWarpOptions),1);
     713                 : 
     714             606 :     psOptions->eResampleAlg = GRA_NearestNeighbour;
     715             606 :     psOptions->pfnProgress = GDALDummyProgress;
     716             606 :     psOptions->eWorkingDataType = GDT_Unknown;
     717                 : 
     718             606 :     return psOptions;
     719                 : }
     720                 : 
     721                 : /************************************************************************/
     722                 : /*                       GDALDestroyWarpOptions()                       */
     723                 : /************************************************************************/
     724                 : 
     725             606 : void CPL_STDCALL GDALDestroyWarpOptions( GDALWarpOptions *psOptions )
     726                 : 
     727                 : {
     728             606 :     VALIDATE_POINTER0( psOptions, "GDALDestroyWarpOptions" );
     729                 : 
     730             606 :     CSLDestroy( psOptions->papszWarpOptions );
     731             606 :     CPLFree( psOptions->panSrcBands );
     732             606 :     CPLFree( psOptions->panDstBands );
     733             606 :     CPLFree( psOptions->padfSrcNoDataReal );
     734             606 :     CPLFree( psOptions->padfSrcNoDataImag );
     735             606 :     CPLFree( psOptions->padfDstNoDataReal );
     736             606 :     CPLFree( psOptions->padfDstNoDataImag );
     737             606 :     CPLFree( psOptions->papfnSrcPerBandValidityMaskFunc );
     738             606 :     CPLFree( psOptions->papSrcPerBandValidityMaskFuncArg );
     739                 : 
     740             606 :     if( psOptions->hCutline != NULL )
     741               9 :         OGR_G_DestroyGeometry( (OGRGeometryH) psOptions->hCutline );
     742                 : 
     743             606 :     CPLFree( psOptions );
     744                 : }
     745                 : 
     746                 : 
     747                 : #define COPY_MEM(target,type,count)         \
     748                 :    if( (psSrcOptions->target) != NULL && (count) != 0 )    \
     749                 :    {                  \
     750                 :        (psDstOptions->target) = (type *) CPLMalloc(sizeof(type)*count); \
     751                 :        memcpy( (psDstOptions->target), (psSrcOptions->target),    \
     752                 :          sizeof(type) * count );                \
     753                 :    }
     754                 : 
     755                 : /************************************************************************/
     756                 : /*                        GDALCloneWarpOptions()                        */
     757                 : /************************************************************************/
     758                 : 
     759                 : GDALWarpOptions * CPL_STDCALL
     760             304 : GDALCloneWarpOptions( const GDALWarpOptions *psSrcOptions )
     761                 : 
     762                 : {
     763             304 :     GDALWarpOptions *psDstOptions = GDALCreateWarpOptions();
     764                 : 
     765             304 :     memcpy( psDstOptions, psSrcOptions, sizeof(GDALWarpOptions) );
     766                 : 
     767             304 :     if( psSrcOptions->papszWarpOptions != NULL )
     768                 :         psDstOptions->papszWarpOptions = 
     769             264 :             CSLDuplicate( psSrcOptions->papszWarpOptions );
     770                 : 
     771             304 :     COPY_MEM( panSrcBands, int, psSrcOptions->nBandCount );
     772             304 :     COPY_MEM( panDstBands, int, psSrcOptions->nBandCount );
     773             304 :     COPY_MEM( padfSrcNoDataReal, double, psSrcOptions->nBandCount );
     774             304 :     COPY_MEM( padfSrcNoDataImag, double, psSrcOptions->nBandCount );
     775             304 :     COPY_MEM( padfDstNoDataReal, double, psSrcOptions->nBandCount );
     776             304 :     COPY_MEM( padfDstNoDataImag, double, psSrcOptions->nBandCount );
     777             304 :     COPY_MEM( papfnSrcPerBandValidityMaskFunc, GDALMaskFunc, 
     778                 :               psSrcOptions->nBandCount );
     779                 : 
     780             304 :     if( psSrcOptions->hCutline != NULL )
     781                 :         psDstOptions->hCutline = 
     782               3 :             OGR_G_Clone( (OGRGeometryH) psSrcOptions->hCutline );
     783             304 :     psDstOptions->dfCutlineBlendDist = psSrcOptions->dfCutlineBlendDist;
     784                 : 
     785             304 :     return psDstOptions;
     786                 : }
     787                 : 
     788                 : /************************************************************************/
     789                 : /*                      GDALSerializeWarpOptions()                      */
     790                 : /************************************************************************/
     791                 : 
     792                 : CPLXMLNode * CPL_STDCALL 
     793               4 : GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
     794                 : 
     795                 : {
     796                 :     CPLXMLNode *psTree;
     797                 : 
     798                 : /* -------------------------------------------------------------------- */
     799                 : /*      Create root.                                                    */
     800                 : /* -------------------------------------------------------------------- */
     801               4 :     psTree = CPLCreateXMLNode( NULL, CXT_Element, "GDALWarpOptions" );
     802                 :     
     803                 : /* -------------------------------------------------------------------- */
     804                 : /*      WarpMemoryLimit                                                 */
     805                 : /* -------------------------------------------------------------------- */
     806                 :     CPLCreateXMLElementAndValue( 
     807                 :         psTree, "WarpMemoryLimit", 
     808               4 :         CPLString().Printf("%g", psWO->dfWarpMemoryLimit ) );
     809                 : 
     810                 : /* -------------------------------------------------------------------- */
     811                 : /*      ResampleAlg                                                     */
     812                 : /* -------------------------------------------------------------------- */
     813                 :     const char *pszAlgName;
     814                 : 
     815               4 :     if( psWO->eResampleAlg == GRA_NearestNeighbour )
     816               4 :         pszAlgName = "NearestNeighbour";
     817               0 :     else if( psWO->eResampleAlg == GRA_Bilinear )
     818               0 :         pszAlgName = "Bilinear";
     819               0 :     else if( psWO->eResampleAlg == GRA_Cubic )
     820               0 :         pszAlgName = "Cubic";
     821               0 :     else if( psWO->eResampleAlg == GRA_CubicSpline )
     822               0 :         pszAlgName = "CubicSpline";
     823               0 :     else if( psWO->eResampleAlg == GRA_Lanczos )
     824               0 :         pszAlgName = "Lanczos";
     825                 :     else
     826               0 :         pszAlgName = "Unknown";
     827                 : 
     828                 :     CPLCreateXMLElementAndValue( 
     829               4 :         psTree, "ResampleAlg", pszAlgName );
     830                 : 
     831                 : /* -------------------------------------------------------------------- */
     832                 : /*      Working Data Type                                               */
     833                 : /* -------------------------------------------------------------------- */
     834                 : 
     835                 :     CPLCreateXMLElementAndValue( 
     836                 :         psTree, "WorkingDataType", 
     837               4 :         GDALGetDataTypeName( psWO->eWorkingDataType ) );
     838                 : 
     839                 : /* -------------------------------------------------------------------- */
     840                 : /*      Name/value warp options.                                        */
     841                 : /* -------------------------------------------------------------------- */
     842                 :     int iWO;
     843                 : 
     844              10 :     for( iWO = 0; psWO->papszWarpOptions != NULL 
     845               4 :              && psWO->papszWarpOptions[iWO] != NULL; iWO++ )
     846                 :     {
     847               2 :         char *pszName = NULL;
     848                 :         const char *pszValue = 
     849               2 :             CPLParseNameValue( psWO->papszWarpOptions[iWO], &pszName );
     850                 : 
     851                 :         CPLXMLNode *psOption = 
     852                 :             CPLCreateXMLElementAndValue( 
     853               2 :                 psTree, "Option", pszValue );
     854                 : 
     855                 :         CPLCreateXMLNode( 
     856                 :             CPLCreateXMLNode( psOption, CXT_Attribute, "name" ),
     857               2 :             CXT_Text, pszName );
     858                 : 
     859               2 :         CPLFree(pszName);
     860                 :     }
     861                 : 
     862                 : /* -------------------------------------------------------------------- */
     863                 : /*      Source and Destination Data Source                              */
     864                 : /* -------------------------------------------------------------------- */
     865               4 :     if( psWO->hSrcDS != NULL )
     866                 :     {
     867                 :         CPLCreateXMLElementAndValue( 
     868                 :             psTree, "SourceDataset", 
     869               4 :             GDALGetDescription( psWO->hSrcDS ) );
     870                 :     }
     871                 :     
     872               4 :     if( psWO->hDstDS != NULL && strlen(GDALGetDescription(psWO->hDstDS)) != 0 )
     873                 :     {
     874                 :         CPLCreateXMLElementAndValue( 
     875                 :             psTree, "DestinationDataset", 
     876               0 :             GDALGetDescription( psWO->hDstDS ) );
     877                 :     }
     878                 :     
     879                 : /* -------------------------------------------------------------------- */
     880                 : /*      Serialize transformer.                                          */
     881                 : /* -------------------------------------------------------------------- */
     882               4 :     if( psWO->pfnTransformer != NULL )
     883                 :     {
     884                 :         CPLXMLNode *psTransformerContainer;
     885                 :         CPLXMLNode *psTransformerTree;
     886                 : 
     887                 :         psTransformerContainer = 
     888               4 :             CPLCreateXMLNode( psTree, CXT_Element, "Transformer" );
     889                 : 
     890                 :         psTransformerTree = 
     891                 :             GDALSerializeTransformer( psWO->pfnTransformer,
     892               4 :                                       psWO->pTransformerArg );
     893                 : 
     894               4 :         if( psTransformerTree != NULL )
     895               4 :             CPLAddXMLChild( psTransformerContainer, psTransformerTree );
     896                 :     }
     897                 : 
     898                 : /* -------------------------------------------------------------------- */
     899                 : /*      Band count and lists.                                           */
     900                 : /* -------------------------------------------------------------------- */
     901               4 :     CPLXMLNode *psBandList = NULL;
     902                 :     int i;
     903                 : 
     904               4 :     if( psWO->nBandCount != 0 )
     905               4 :         psBandList = CPLCreateXMLNode( psTree, CXT_Element, "BandList" );
     906                 : 
     907              10 :     for( i = 0; i < psWO->nBandCount; i++ )
     908                 :     {
     909                 :         CPLXMLNode *psBand;
     910                 : 
     911               6 :         psBand = CPLCreateXMLNode( psBandList, CXT_Element, "BandMapping" );
     912               6 :         if( psWO->panSrcBands != NULL )
     913                 :             CPLCreateXMLNode( 
     914                 :                 CPLCreateXMLNode( psBand, CXT_Attribute, "src" ),
     915               6 :                 CXT_Text, CPLString().Printf( "%d", psWO->panSrcBands[i] ) );
     916               6 :         if( psWO->panDstBands != NULL )
     917                 :             CPLCreateXMLNode( 
     918                 :                 CPLCreateXMLNode( psBand, CXT_Attribute, "dst" ),
     919               6 :                 CXT_Text, CPLString().Printf( "%d", psWO->panDstBands[i] ) );
     920                 :         
     921               6 :         if( psWO->padfSrcNoDataReal != NULL )
     922                 :             CPLCreateXMLElementAndValue( 
     923                 :                 psBand, "SrcNoDataReal", 
     924               0 :                 CPLString().Printf( "%.16g", psWO->padfSrcNoDataReal[i] ) );
     925                 : 
     926               6 :         if( psWO->padfSrcNoDataImag != NULL )
     927                 :             CPLCreateXMLElementAndValue( 
     928                 :                 psBand, "SrcNoDataImag", 
     929               0 :                 CPLString().Printf( "%.16g", psWO->padfSrcNoDataImag[i] ) );
     930                 : 
     931               6 :         if( psWO->padfDstNoDataReal != NULL )
     932                 :             CPLCreateXMLElementAndValue( 
     933                 :                 psBand, "DstNoDataReal", 
     934               0 :                 CPLString().Printf( "%.16g", psWO->padfDstNoDataReal[i] ) );
     935                 : 
     936               6 :         if( psWO->padfDstNoDataImag != NULL )
     937                 :             CPLCreateXMLElementAndValue( 
     938                 :                 psBand, "DstNoDataImag", 
     939               0 :                 CPLString().Printf( "%.16g", psWO->padfDstNoDataImag[i] ) );
     940                 :     }
     941                 : 
     942                 : /* -------------------------------------------------------------------- */
     943                 : /*      Alpha bands.                                                    */
     944                 : /* -------------------------------------------------------------------- */
     945               4 :     if( psWO->nSrcAlphaBand > 0 )
     946                 :         CPLCreateXMLElementAndValue( 
     947                 :             psTree, "SrcAlphaBand", 
     948               0 :             CPLString().Printf( "%d", psWO->nSrcAlphaBand ) );
     949                 : 
     950               4 :     if( psWO->nDstAlphaBand > 0 )
     951                 :         CPLCreateXMLElementAndValue( 
     952                 :             psTree, "DstAlphaBand", 
     953               0 :             CPLString().Printf( "%d", psWO->nDstAlphaBand ) );
     954                 : 
     955                 : /* -------------------------------------------------------------------- */
     956                 : /*      Cutline.                                                        */
     957                 : /* -------------------------------------------------------------------- */
     958               4 :     if( psWO->hCutline != NULL )
     959                 :     {
     960               0 :         char *pszWKT = NULL;
     961               0 :         if( OGR_G_ExportToWkt( (OGRGeometryH) psWO->hCutline, &pszWKT )
     962                 :             == OGRERR_NONE )
     963                 :         {
     964               0 :             CPLCreateXMLElementAndValue( psTree, "Cutline", pszWKT );
     965               0 :             CPLFree( pszWKT );
     966                 :         }
     967                 :     }
     968                 : 
     969               4 :     if( psWO->dfCutlineBlendDist != 0.0 )
     970                 :         CPLCreateXMLElementAndValue( 
     971                 :             psTree, "CutlineBlendDist", 
     972               0 :             CPLString().Printf( "%.5g", psWO->dfCutlineBlendDist ) );
     973                 : 
     974               4 :     return psTree;
     975                 : }
     976                 : 
     977                 : /************************************************************************/
     978                 : /*                     GDALDeserializeWarpOptions()                     */
     979                 : /************************************************************************/
     980                 : 
     981              34 : GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
     982                 : 
     983                 : {
     984              34 :     CPLErrorReset();
     985                 : 
     986                 : /* -------------------------------------------------------------------- */
     987                 : /*      Verify this is the right kind of object.                        */
     988                 : /* -------------------------------------------------------------------- */
     989              34 :     if( psTree == NULL || psTree->eType != CXT_Element
     990                 :         || !EQUAL(psTree->pszValue,"GDALWarpOptions") )
     991                 :     {
     992                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     993               0 :                   "Wrong node, unable to deserialize GDALWarpOptions." );
     994               0 :         return NULL;
     995                 :     }
     996                 : 
     997                 : /* -------------------------------------------------------------------- */
     998                 : /*      Create pre-initialized warp options.                            */
     999                 : /* -------------------------------------------------------------------- */
    1000              34 :     GDALWarpOptions *psWO = GDALCreateWarpOptions();
    1001                 : 
    1002                 : /* -------------------------------------------------------------------- */
    1003                 : /*      Warp memory limit.                                              */
    1004                 : /* -------------------------------------------------------------------- */
    1005                 :     psWO->dfWarpMemoryLimit = 
    1006              34 :         atof(CPLGetXMLValue(psTree,"WarpMemoryLimit","0.0"));
    1007                 : 
    1008                 : /* -------------------------------------------------------------------- */
    1009                 : /*      resample algorithm                                              */
    1010                 : /* -------------------------------------------------------------------- */
    1011                 :     const char *pszValue = 
    1012              34 :         CPLGetXMLValue(psTree,"ResampleAlg","Default");
    1013                 : 
    1014              34 :     if( EQUAL(pszValue,"NearestNeighbour") )
    1015              20 :         psWO->eResampleAlg = GRA_NearestNeighbour;
    1016              14 :     else if( EQUAL(pszValue,"Bilinear") )
    1017               4 :         psWO->eResampleAlg = GRA_Bilinear;
    1018              10 :     else if( EQUAL(pszValue,"Cubic") )
    1019               4 :         psWO->eResampleAlg = GRA_Cubic;
    1020               6 :     else if( EQUAL(pszValue,"CubicSpline") )
    1021               4 :         psWO->eResampleAlg = GRA_CubicSpline;
    1022               2 :     else if( EQUAL(pszValue,"Lanczos") )
    1023               2 :         psWO->eResampleAlg = GRA_Lanczos;
    1024               0 :     else if( EQUAL(pszValue,"Default") )
    1025                 :         /* leave as is */;
    1026                 :     else
    1027                 :     {
    1028                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1029                 :                   "Unrecognise ResampleAlg value '%s'.",
    1030               0 :                   pszValue );
    1031                 :     }
    1032                 : 
    1033                 : /* -------------------------------------------------------------------- */
    1034                 : /*      Working data type.                                              */
    1035                 : /* -------------------------------------------------------------------- */
    1036                 :     psWO->eWorkingDataType = 
    1037                 :         GDALGetDataTypeByName(
    1038              34 :             CPLGetXMLValue(psTree,"WorkingDataType","Unknown"));
    1039                 : 
    1040                 : /* -------------------------------------------------------------------- */
    1041                 : /*      Name/value warp options.                                        */
    1042                 : /* -------------------------------------------------------------------- */
    1043                 :     CPLXMLNode *psItem; 
    1044                 : 
    1045             273 :     for( psItem = psTree->psChild; psItem != NULL; psItem = psItem->psNext )
    1046                 :     {
    1047             239 :         if( psItem->eType == CXT_Element 
    1048                 :             && EQUAL(psItem->pszValue,"Option") )
    1049                 :         {
    1050              16 :             const char *pszName = CPLGetXMLValue(psItem, "Name", NULL );
    1051              16 :             const char *pszValue = CPLGetXMLValue(psItem, "", NULL );
    1052                 : 
    1053              16 :             if( pszName != NULL && pszValue != NULL )
    1054                 :             {
    1055                 :                 psWO->papszWarpOptions = 
    1056                 :                     CSLSetNameValue( psWO->papszWarpOptions, 
    1057              16 :                                      pszName, pszValue );
    1058                 :             }
    1059                 :         }
    1060                 :     }
    1061                 :     
    1062                 : /* -------------------------------------------------------------------- */
    1063                 : /*      Source Dataset.                                                 */
    1064                 : /* -------------------------------------------------------------------- */
    1065              34 :     pszValue = CPLGetXMLValue(psTree,"SourceDataset",NULL);
    1066                 : 
    1067              34 :     if( pszValue != NULL )
    1068              34 :         psWO->hSrcDS = GDALOpenShared( pszValue, GA_ReadOnly );
    1069                 : 
    1070                 : /* -------------------------------------------------------------------- */
    1071                 : /*      Destination Dataset.                                            */
    1072                 : /* -------------------------------------------------------------------- */
    1073              34 :     pszValue = CPLGetXMLValue(psTree,"DestinationDataset",NULL);
    1074                 : 
    1075              34 :     if( pszValue != NULL )
    1076               0 :         psWO->hDstDS = GDALOpenShared( pszValue, GA_Update );
    1077                 : 
    1078                 : /* -------------------------------------------------------------------- */
    1079                 : /*      First, count band mappings so we can establish the bandcount.   */
    1080                 : /* -------------------------------------------------------------------- */
    1081              34 :     CPLXMLNode *psBandTree = CPLGetXMLNode( psTree, "BandList" );
    1082              34 :     CPLXMLNode *psBand = NULL;
    1083                 : 
    1084              34 :     psWO->nBandCount = 0;
    1085                 :     
    1086              88 :     for( psBand=psBandTree->psChild; psBand != NULL; psBand = psBand->psNext )
    1087                 :     {
    1088              54 :         if( psBand->eType != CXT_Element 
    1089                 :             || !EQUAL(psBand->pszValue,"BandMapping") )
    1090               0 :             continue;
    1091                 : 
    1092              54 :         psWO->nBandCount++;
    1093                 :     }
    1094                 : 
    1095                 : /* ==================================================================== */
    1096                 : /*      Now actually process each bandmapping.                          */
    1097                 : /* ==================================================================== */
    1098              34 :     int iBand = 0;
    1099                 : 
    1100              88 :     for( psBand=psBandTree->psChild; psBand != NULL; psBand = psBand->psNext )
    1101                 :     {
    1102              54 :         if( psBand->eType != CXT_Element 
    1103                 :             || !EQUAL(psBand->pszValue,"BandMapping") )
    1104               0 :             continue;
    1105                 : 
    1106                 : /* -------------------------------------------------------------------- */
    1107                 : /*      Source band                                                     */
    1108                 : /* -------------------------------------------------------------------- */
    1109              54 :         if( psWO->panSrcBands == NULL )
    1110              34 :             psWO->panSrcBands = (int *)CPLMalloc(sizeof(int)*psWO->nBandCount);
    1111                 :         
    1112              54 :         pszValue = CPLGetXMLValue(psBand,"src",NULL);
    1113              54 :         if( pszValue == NULL )
    1114               0 :             psWO->panSrcBands[iBand] = iBand+1;
    1115                 :         else
    1116              54 :             psWO->panSrcBands[iBand] = atoi(pszValue);
    1117                 :         
    1118                 : /* -------------------------------------------------------------------- */
    1119                 : /*      Destination band.                                               */
    1120                 : /* -------------------------------------------------------------------- */
    1121              54 :         pszValue = CPLGetXMLValue(psBand,"dst",NULL);
    1122              54 :         if( pszValue != NULL )
    1123                 :         {
    1124              54 :             if( psWO->panDstBands == NULL )
    1125                 :                 psWO->panDstBands = 
    1126              34 :                     (int *) CPLMalloc(sizeof(int)*psWO->nBandCount);
    1127                 : 
    1128              54 :             psWO->panDstBands[iBand] = atoi(pszValue);
    1129                 :         }
    1130                 :         
    1131                 : /* -------------------------------------------------------------------- */
    1132                 : /*      Source nodata.                                                  */
    1133                 : /* -------------------------------------------------------------------- */
    1134              54 :         pszValue = CPLGetXMLValue(psBand,"SrcNoDataReal",NULL);
    1135              54 :         if( pszValue != NULL )
    1136                 :         {
    1137               1 :             if( psWO->padfSrcNoDataReal == NULL )
    1138                 :                 psWO->padfSrcNoDataReal = 
    1139               1 :                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
    1140                 : 
    1141               1 :             psWO->padfSrcNoDataReal[iBand] = atof(pszValue);
    1142                 :         }
    1143                 :         
    1144              54 :         pszValue = CPLGetXMLValue(psBand,"SrcNoDataImag",NULL);
    1145              54 :         if( pszValue != NULL )
    1146                 :         {
    1147               1 :             if( psWO->padfSrcNoDataImag == NULL )
    1148                 :                 psWO->padfSrcNoDataImag = 
    1149               1 :                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
    1150                 : 
    1151               1 :             psWO->padfSrcNoDataImag[iBand] = atof(pszValue);
    1152                 :         }
    1153                 :         
    1154                 : /* -------------------------------------------------------------------- */
    1155                 : /*      Destination nodata.                                             */
    1156                 : /* -------------------------------------------------------------------- */
    1157              54 :         pszValue = CPLGetXMLValue(psBand,"DstNoDataReal",NULL);
    1158              54 :         if( pszValue != NULL )
    1159                 :         {
    1160               1 :             if( psWO->padfDstNoDataReal == NULL )
    1161                 :                 psWO->padfDstNoDataReal = 
    1162               1 :                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
    1163                 : 
    1164               1 :             psWO->padfDstNoDataReal[iBand] = atof(pszValue);
    1165                 :         }
    1166                 :         
    1167              54 :         pszValue = CPLGetXMLValue(psBand,"DstNoDataImag",NULL);
    1168              54 :         if( pszValue != NULL )
    1169                 :         {
    1170               1 :             if( psWO->padfDstNoDataImag == NULL )
    1171                 :                 psWO->padfDstNoDataImag = 
    1172               1 :                     (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
    1173                 : 
    1174               1 :             psWO->padfDstNoDataImag[iBand] = atof(pszValue);
    1175                 :         }
    1176                 :         
    1177              54 :         iBand++;
    1178                 :     }
    1179                 : 
    1180                 : /* -------------------------------------------------------------------- */
    1181                 : /*      Alpha bands.                                                    */
    1182                 : /* -------------------------------------------------------------------- */
    1183                 :     psWO->nSrcAlphaBand = 
    1184              34 :         atoi( CPLGetXMLValue( psTree, "SrcAlphaBand", "0" ) );
    1185                 :     psWO->nDstAlphaBand = 
    1186              34 :         atoi( CPLGetXMLValue( psTree, "DstAlphaBand", "0" ) );
    1187                 : 
    1188                 : /* -------------------------------------------------------------------- */
    1189                 : /*      Cutline.                                                        */
    1190                 : /* -------------------------------------------------------------------- */
    1191              34 :     const char *pszWKT = CPLGetXMLValue( psTree, "Cutline", NULL );
    1192              34 :     if( pszWKT )
    1193                 :     {
    1194                 :         OGR_G_CreateFromWkt( (char **) &pszWKT, NULL, 
    1195               3 :                              (OGRGeometryH *) (&psWO->hCutline) );
    1196                 :     }
    1197                 : 
    1198                 :     psWO->dfCutlineBlendDist =
    1199              34 :         atof( CPLGetXMLValue( psTree, "CutlineBlendDist", "0" ) );
    1200                 : 
    1201                 : /* -------------------------------------------------------------------- */
    1202                 : /*      Transformation.                                                 */
    1203                 : /* -------------------------------------------------------------------- */
    1204              34 :     CPLXMLNode *psTransformer = CPLGetXMLNode( psTree, "Transformer" );
    1205                 : 
    1206              34 :     if( psTransformer != NULL && psTransformer->psChild != NULL )
    1207                 :     {
    1208                 :         GDALDeserializeTransformer( psTransformer->psChild, 
    1209                 :                                     &(psWO->pfnTransformer),
    1210              34 :                                     &(psWO->pTransformerArg) );
    1211                 :     }
    1212                 : 
    1213                 : /* -------------------------------------------------------------------- */
    1214                 : /*      If any error has occured, cleanup else return success.          */
    1215                 : /* -------------------------------------------------------------------- */
    1216              34 :     if( CPLGetLastErrorNo() != CE_None )
    1217                 :     {
    1218               0 :         if ( psWO->pTransformerArg )
    1219                 :         {
    1220               0 :             GDALDestroyTransformer( psWO->pTransformerArg );
    1221               0 :             psWO->pTransformerArg = NULL;
    1222                 :         }
    1223               0 :         if( psWO->hSrcDS != NULL )
    1224                 :         {
    1225               0 :             GDALClose( psWO->hSrcDS );
    1226               0 :             psWO->hSrcDS = NULL;
    1227                 :         }
    1228               0 :         if( psWO->hDstDS != NULL )
    1229                 :         {
    1230               0 :             GDALClose( psWO->hDstDS );
    1231               0 :             psWO->hDstDS = NULL;
    1232                 :         }
    1233               0 :         GDALDestroyWarpOptions( psWO );
    1234               0 :         return NULL;
    1235                 :     }
    1236                 :     else
    1237              34 :         return psWO;
    1238                 : }

Generated by: LCOV version 1.7