LTP GCOV extension - code coverage report
Current view: directory - alg - gdalwarper.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 396
Code covered: 66.2 % Executed lines: 262

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

Generated by: LTP GCOV extension version 1.5