LCOV - code coverage report
Current view: directory - apps - gdalwarp.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 650 452 69.5 %
Date: 2010-01-09 Functions: 13 10 76.9 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalwarp.cpp 18306 2009-12-15 18:57:11Z rouault $
       3                 :  *
       4                 :  * Project:  High Performance Image Reprojector
       5                 :  * Purpose:  Test program for high performance warper API.
       6                 :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2002, i3 - information integration and imaging 
      10                 :  *                          Fort Collin, CO
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "gdalwarper.h"
      32                 : #include "cpl_string.h"
      33                 : #include "ogr_spatialref.h"
      34                 : #include "ogr_api.h"
      35                 : 
      36                 : CPL_CVSID("$Id: gdalwarp.cpp 18306 2009-12-15 18:57:11Z rouault $");
      37                 : 
      38                 : static void
      39                 : LoadCutline( const char *pszCutlineDSName, const char *pszCLayer, 
      40                 :              const char *pszCWHERE, const char *pszCSQL, 
      41                 :              void **phCutlineRet );
      42                 : static void
      43                 : TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
      44                 :                           char ***ppapszWarpOptions, char **papszTO );
      45                 : static GDALDatasetH 
      46                 : GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename, 
      47                 :                       const char *pszFormat, char **papszTO,
      48                 :                       char ***ppapszCreateOptions, GDALDataType eDT );
      49                 : 
      50                 : static double        dfMinX=0.0, dfMinY=0.0, dfMaxX=0.0, dfMaxY=0.0;
      51                 : static double        dfXRes=0.0, dfYRes=0.0;
      52                 : static int             nForcePixels=0, nForceLines=0, bQuiet = FALSE;
      53                 : static int             bEnableDstAlpha = FALSE, bEnableSrcAlpha = FALSE;
      54                 : 
      55                 : static int             bVRT = FALSE;
      56                 : 
      57                 : /******************************************************************************/
      58                 : /*! \page gdalwarp gdalwarp
      59                 : 
      60                 : image reprojection and warping utility
      61                 : 
      62                 : \section wsynopsis SYNOPSIS
      63                 : 
      64                 : \htmlonly
      65                 : Usage: 
      66                 : \endhtmlonly
      67                 : 
      68                 : \verbatim
      69                 : gdalwarp [--help-general] [--formats]
      70                 :     [-s_srs srs_def] [-t_srs srs_def] [-to "NAME=VALUE"]
      71                 :     [-order n] [-tps] [-rpc] [-geoloc] [-et err_threshold]
      72                 :     [-te xmin ymin xmax ymax] [-tr xres yres] [-ts width height]
      73                 :     [-wo "NAME=VALUE"] [-ot Byte/Int16/...] [-wt Byte/Int16]
      74                 :     [-srcnodata "value [value...]"] [-dstnodata "value [value...]"] -dstalpha
      75                 :     [-r resampling_method] [-wm memory_in_mb] [-multi] [-q]
      76                 :     [-cutline datasource] [-cl layer] [-cwhere expression]
      77                 :     [-csql statement] [-cblend dist_in_pixels]
      78                 :     [-of format] [-co "NAME=VALUE"]*
      79                 :     srcfile* dstfile
      80                 : \endverbatim
      81                 : 
      82                 : \section wdescription DESCRIPTION
      83                 : 
      84                 : <p>
      85                 : The gdalwarp utility is an image mosaicing, reprojection and warping
      86                 : utility. The program can reproject to any supported projection,
      87                 : and can also apply GCPs stored with the image if the image is "raw"
      88                 : with control information.
      89                 : 
      90                 : <p>
      91                 : <dl>
      92                 : <dt> <b>-s_srs</b> <em>srs def</em>:</dt><dd> source spatial reference set.
      93                 : The coordinate systems that can be passed are anything supported by the
      94                 : OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
      95                 : (ie. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prf file
      96                 : containing well known text.</dd>
      97                 : <dt> <b>-t_srs</b> <em>srs_def</em>:</dt><dd> target spatial reference set.
      98                 : The coordinate systems that can be passed are anything supported by the
      99                 : OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
     100                 : (ie. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prf file
     101                 : containing well known text.</dd>
     102                 : <dt> <b>-to</b> <em>NAME=VALUE</em>:</dt><dd> set a transformer option suitable
     103                 : to pass to GDALCreateGenImgProjTransformer2(). </dd>
     104                 : <dt> <b>-order</b> <em>n</em>:</dt><dd> order of polynomial used for warping
     105                 : (1 to 3). The default is to select a polynomial order based on the number of
     106                 : GCPs.</dd>
     107                 : <dt> <b>-tps</b>:</dt><dd>Force use of thin plate spline transformer based on
     108                 : available GCPs.</dd>
     109                 : <dt> <b>-rpc</b>:</dt> <dd>Force use of RPCs.</dd>
     110                 : <dt> <b>-geoloc</b>:</dt><dd>Force use of Geolocation Arrays.</dd>
     111                 : <dt> <b>-et</b> <em>err_threshold</em>:</dt><dd> error threshold for
     112                 : transformation approximation (in pixel units - defaults to 0.125).</dd>
     113                 : <dt> <b>-te</b> <em>xmin ymin xmax ymax</em>:</dt><dd> set georeferenced
     114                 : extents of output file to be created (in target SRS).</dd>
     115                 : <dt> <b>-tr</b> <em>xres yres</em>:</dt><dd> set output file resolution (in
     116                 : target georeferenced units)</dd>
     117                 : <dt> <b>-ts</b> <em>width height</em>:</dt><dd> set output file size in
     118                 : pixels and lines. If width or height is set to 0, the other dimension will be
     119                 : guessed from the computed resolution. Note that -ts cannot be used with -tr</dd>
     120                 : <dt> <b>-wo</b> <em>"NAME=VALUE"</em>:</dt><dd> Set a warp options.  The 
     121                 : GDALWarpOptions::papszWarpOptions docs show all options.  Multiple
     122                 :  <b>-wo</b> options may be listed.</dd>
     123                 : <dt> <b>-ot</b> <em>type</em>:</dt><dd> For the output bands to be of the
     124                 : indicated data type.</dd>
     125                 : <dt> <b>-wt</b> <em>type</em>:</dt><dd> Working pixel data type. The data type
     126                 : of pixels in the source image and destination image buffers.</dd>
     127                 : <dt> <b>-r</b> <em>resampling_method</em>:</dt><dd> Resampling method to use. Available methods are:
     128                 : <dl>
     129                 : <dt><b>near</b></dt>: <dd>nearest neighbour resampling (default, fastest
     130                 : algorithm, worst interpolation quality).</dd>
     131                 : <dt><b>bilinear</b></dt>: <dd>bilinear resampling.</dd>
     132                 : <dt><b>cubic</b></dt>: <dd>cubic resampling.</dd>
     133                 : <dt><b>cubicspline</b></dt>: <dd>cubic spline resampling.</dd>
     134                 : <dt><b>lanczos</b></dt>: <dd>Lanczos windowed sinc resampling.</dd>
     135                 : </dl>
     136                 : <dt> <b>-srcnodata</b> <em>value [value...]</em>:</dt><dd> Set nodata masking
     137                 : values for input bands (different values can be supplied for each band).  If 
     138                 : more than one value is supplied all values should be quoted to keep them 
     139                 : together as a single operating system argument.  Masked values will not be 
     140                 : used in interpolation.  Use a value of <tt>None</tt> to ignore intrinsic nodata settings on the source dataset.</dd>
     141                 : <dt> <b>-dstnodata</b> <em>value [value...]</em>:</dt><dd> Set nodata values
     142                 : for output bands (different values can be supplied for each band).  If more
     143                 : than one value is supplied all values should be quoted to keep them together
     144                 : as a single operating system argument.  New files will be initialized to this
     145                 : value and if possible the nodata value will be recorded in the output
     146                 : file.</dd>
     147                 : <dt> <b>-dstalpha</b>:</dt><dd> Create an output alpha band to identify 
     148                 : nodata (unset/transparent) pixels. </dd>
     149                 : <dt> <b>-wm</b> <em>memory_in_mb</em>:</dt><dd> Set the amount of memory (in
     150                 : megabytes) that the warp API is allowed to use for caching.</dd>
     151                 : <dt> <b>-multi</b>:</dt><dd> Use multithreaded warping implementation.
     152                 : Multiple threads will be used to process chunks of image and perform
     153                 : input/output operation simultaneously.</dd>
     154                 : <dt> <b>-q</b>:</dt><dd> Be quiet.</dd>
     155                 : <dt> <b>-of</b> <em>format</em>:</dt><dd> Select the output format. The default is GeoTIFF (GTiff). Use the short format name. </dd>
     156                 : <dt> <b>-co</b> <em>"NAME=VALUE"</em>:</dt><dd> passes a creation option to
     157                 : the output format driver. Multiple <b>-co</b> options may be listed. See
     158                 : format specific documentation for legal creation options for each format.
     159                 : </dd>
     160                 : 
     161                 : <dt> <b>-cutline</b> <em>datasource</em>:</dt><dd>Enable use of a blend cutline from the name OGR support datasource.</dd>
     162                 : <dt> <b>-cl</b> <em>layername</em>:</dt><dd>Select the named layer from the 
     163                 : cutline datasource.</dd>
     164                 : <dt> <b>-cwhere</b> <em>expression</em>:</dt><dd>Restrict desired cutline features based on attribute query.</dd>
     165                 : <dt> <b>-csql</b> <em>query</em>:</dt><dd>Select cutline features using an SQL query instead of from a layer with -cl.</dd>
     166                 : <dt> <b>-cblend</b> <em>distance</em>:</dt><dd>Set a blend distance to use to blend over cutlines (in pixels).</dd>
     167                 : 
     168                 : <dt> <em>srcfile</em>:</dt><dd> The source file name(s). </dd>
     169                 : <dt> <em>dstfile</em>:</dt><dd> The destination file name. </dd>
     170                 : </dl>
     171                 : 
     172                 : Mosaicing into an existing output file is supported if the output file 
     173                 : already exists. The spatial extent of the existing file will not
     174                 : be modified to accomodate new data, so you may have to remove it in that case.
     175                 : 
     176                 : Polygon cutlines may be used to restrict the the area of the destination file 
     177                 : that may be updated, including blending.  Cutline features must be in the 
     178                 : georeferenced units of the destination file. 
     179                 : 
     180                 : <p>
     181                 : \section wexample EXAMPLE
     182                 : 
     183                 : For instance, an eight bit spot scene stored in GeoTIFF with
     184                 : control points mapping the corners to lat/long could be warped to a UTM
     185                 : projection with a command like this:<p>
     186                 : 
     187                 : \verbatim
     188                 : gdalwarp -t_srs '+proj=utm +zone=11 +datum=WGS84' raw_spot.tif utm11.tif
     189                 : \endverbatim
     190                 : 
     191                 : For instance, the second channel of an ASTER image stored in HDF with
     192                 : control points mapping the corners to lat/long could be warped to a UTM
     193                 : projection with a command like this:<p>
     194                 : 
     195                 : \verbatim
     196                 : gdalwarp HDF4_SDS:ASTER_L1B:"pg-PR1B0000-2002031402_100_001":2 pg-PR1B0000-2002031402_100_001_2.tif
     197                 : \endverbatim
     198                 : 
     199                 : \if man
     200                 : \section wauthor AUTHORS
     201                 : Frank Warmerdam <warmerdam@pobox.com>, Silke Reimer <silke@intevation.de>
     202                 : \endif
     203                 : */
     204                 : 
     205                 : /************************************************************************/
     206                 : /*                               Usage()                                */
     207                 : /************************************************************************/
     208                 : 
     209               0 : static void Usage()
     210                 : 
     211                 : {
     212                 :     printf( 
     213                 :         "Usage: gdalwarp [--help-general] [--formats]\n"
     214                 :         "    [-s_srs srs_def] [-t_srs srs_def] [-to \"NAME=VALUE\"]\n"
     215                 :         "    [-order n] [-tps] [-rpc] [-geoloc] [-et err_threshold]\n"
     216                 :         "    [-te xmin ymin xmax ymax] [-tr xres yres] [-ts width height]\n"
     217                 :         "    [-wo \"NAME=VALUE\"] [-ot Byte/Int16/...] [-wt Byte/Int16]\n"
     218                 :         "    [-srcnodata \"value [value...]\"] [-dstnodata \"value [value...]\"] -dstalpha\n" 
     219                 :         "    [-r resampling_method] [-wm memory_in_mb] [-multi] [-q]\n"
     220                 :         "    [-cutline datasource] [-cl layer] [-cwhere expression]\n"
     221                 :         "    [-csql statement] [-cblend dist_in_pixels]\n"
     222                 : 
     223                 :         "    [-of format] [-co \"NAME=VALUE\"]*\n"
     224                 :         "    srcfile* dstfile\n"
     225                 :         "\n"
     226                 :         "Available resampling methods:\n"
     227               0 :         "    near (default), bilinear, cubic, cubicspline, lanczos.\n" );
     228               0 :     exit( 1 );
     229                 : }
     230                 : 
     231                 : /************************************************************************/
     232                 : /*                             SanitizeSRS                              */
     233                 : /************************************************************************/
     234                 : 
     235               8 : char *SanitizeSRS( const char *pszUserInput )
     236                 : 
     237                 : {
     238                 :     OGRSpatialReferenceH hSRS;
     239               8 :     char *pszResult = NULL;
     240                 : 
     241               8 :     CPLErrorReset();
     242                 :     
     243               8 :     hSRS = OSRNewSpatialReference( NULL );
     244               8 :     if( OSRSetFromUserInput( hSRS, pszUserInput ) == OGRERR_NONE )
     245               8 :         OSRExportToWkt( hSRS, &pszResult );
     246                 :     else
     247                 :     {
     248                 :         CPLError( CE_Failure, CPLE_AppDefined,
     249                 :                   "Translating source or target SRS failed:\n%s",
     250               0 :                   pszUserInput );
     251               0 :         exit( 1 );
     252                 :     }
     253                 :     
     254               8 :     OSRDestroySpatialReference( hSRS );
     255                 : 
     256               8 :     return pszResult;
     257                 : }
     258                 : 
     259                 : /************************************************************************/
     260                 : /*                                main()                                */
     261                 : /************************************************************************/
     262                 : 
     263             250 : int main( int argc, char ** argv )
     264                 : 
     265                 : {
     266                 :     GDALDatasetH  hDstDS;
     267             250 :     const char         *pszFormat = "GTiff";
     268             250 :     char              **papszSrcFiles = NULL;
     269             250 :     char               *pszDstFilename = NULL;
     270             250 :     int                 bCreateOutput = FALSE, i;
     271             250 :     void               *hTransformArg, *hGenImgProjArg=NULL, *hApproxArg=NULL;
     272             250 :     char               **papszWarpOptions = NULL;
     273             250 :     double             dfErrorThreshold = 0.125;
     274             250 :     double             dfWarpMemoryLimit = 0.0;
     275             250 :     GDALTransformerFunc pfnTransformer = NULL;
     276             250 :     char                **papszCreateOptions = NULL;
     277             250 :     GDALDataType        eOutputType = GDT_Unknown, eWorkingType = GDT_Unknown; 
     278             250 :     GDALResampleAlg     eResampleAlg = GRA_NearestNeighbour;
     279             250 :     const char          *pszSrcNodata = NULL;
     280             250 :     const char          *pszDstNodata = NULL;
     281             250 :     int                 bMulti = FALSE;
     282             250 :     char                **papszTO = NULL;
     283             250 :     char                *pszCutlineDSName = NULL;
     284             250 :     char                *pszCLayer = NULL, *pszCWHERE = NULL, *pszCSQL = NULL;
     285             250 :     void                *hCutline = NULL;
     286                 : 
     287                 :     /* Check that we are running against at least GDAL 1.6 */
     288                 :     /* Note to developers : if we use newer API, please change the requirement */
     289             250 :     if (atoi(GDALVersionInfo("VERSION_NUM")) < 1600)
     290                 :     {
     291                 :         fprintf(stderr, "At least, GDAL >= 1.6.0 is required for this version of %s, "
     292               0 :                 "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
     293               0 :         exit(1);
     294                 :     }
     295                 : 
     296             250 :     GDALAllRegister();
     297             250 :     argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
     298             250 :     if( argc < 1 )
     299               0 :         exit( -argc );
     300                 : 
     301                 : /* -------------------------------------------------------------------- */
     302                 : /*      Parse arguments.                                                */
     303                 : /* -------------------------------------------------------------------- */
     304            1008 :     for( i = 1; i < argc; i++ )
     305                 :     {
     306             759 :         if( EQUAL(argv[i], "--utility_version") )
     307                 :         {
     308                 :             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
     309               1 :                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
     310               1 :             return 0;
     311                 :         }
     312             758 :         else if( EQUAL(argv[i],"-co") && i < argc-1 )
     313                 :         {
     314               0 :             papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
     315               0 :             bCreateOutput = TRUE;
     316                 :         }   
     317             759 :         else if( EQUAL(argv[i],"-wo") && i < argc-1 )
     318                 :         {
     319               1 :             papszWarpOptions = CSLAddString( papszWarpOptions, argv[++i] );
     320                 :         }   
     321             757 :         else if( EQUAL(argv[i],"-multi") )
     322                 :         {
     323               1 :             bMulti = TRUE;
     324                 :         }   
     325             756 :         else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet"))
     326                 :         {
     327               0 :             bQuiet = TRUE;
     328                 :         }   
     329             756 :         else if( EQUAL(argv[i],"-dstalpha") )
     330                 :         {
     331               1 :             bEnableDstAlpha = TRUE;
     332                 :         }
     333             755 :         else if( EQUAL(argv[i],"-srcalpha") )
     334                 :         {
     335               0 :             bEnableSrcAlpha = TRUE;
     336                 :         }
     337             758 :         else if( EQUAL(argv[i],"-of") && i < argc-1 )
     338                 :         {
     339               3 :             pszFormat = argv[++i];
     340               3 :             bCreateOutput = TRUE;
     341               3 :             if( EQUAL(pszFormat,"VRT") )
     342               2 :                 bVRT = TRUE;
     343                 :         }
     344             760 :         else if( EQUAL(argv[i],"-t_srs") && i < argc-1 )
     345                 :         {
     346               8 :             char *pszSRS = SanitizeSRS(argv[++i]);
     347               8 :             papszTO = CSLSetNameValue( papszTO, "DST_SRS", pszSRS );
     348               8 :             CPLFree( pszSRS );
     349                 :         }
     350             744 :         else if( EQUAL(argv[i],"-s_srs") && i < argc-1 )
     351                 :         {
     352               0 :             char *pszSRS = SanitizeSRS(argv[++i]);
     353               0 :             papszTO = CSLSetNameValue( papszTO, "SRC_SRS", pszSRS );
     354               0 :             CPLFree( pszSRS );
     355                 :         }
     356             744 :         else if( EQUAL(argv[i],"-order") && i < argc-1 )
     357                 :         {
     358               0 :             papszTO = CSLSetNameValue( papszTO, "MAX_GCP_ORDER", argv[++i] );
     359                 :         }
     360             744 :         else if( EQUAL(argv[i],"-tps") )
     361                 :         {
     362               1 :             papszTO = CSLSetNameValue( papszTO, "METHOD", "GCP_TPS" );
     363                 :         }
     364             743 :         else if( EQUAL(argv[i],"-rpc") )
     365                 :         {
     366               0 :             papszTO = CSLSetNameValue( papszTO, "METHOD", "RPC" );
     367                 :         }
     368             743 :         else if( EQUAL(argv[i],"-geoloc") )
     369                 :         {
     370               0 :             papszTO = CSLSetNameValue( papszTO, "METHOD", "GEOLOC_ARRAY" );
     371                 :         }
     372             743 :         else if( EQUAL(argv[i],"-to") && i < argc-1 )
     373                 :         {
     374               0 :             papszTO = CSLAddString( papszTO, argv[++i] );
     375                 :         }
     376             745 :         else if( EQUAL(argv[i],"-et") && i < argc-1 )
     377                 :         {
     378               2 :             dfErrorThreshold = atof(argv[++i]);
     379                 :         }
     380             742 :         else if( EQUAL(argv[i],"-wm") && i < argc-1 )
     381                 :         {
     382               1 :             if( atof(argv[i+1]) < 10000 )
     383               1 :                 dfWarpMemoryLimit = atof(argv[i+1]) * 1024 * 1024;
     384                 :             else
     385               0 :                 dfWarpMemoryLimit = atof(argv[i+1]);
     386               1 :             i++;
     387                 :         }
     388             740 :         else if( EQUAL(argv[i],"-srcnodata") && i < argc-1 )
     389                 :         {
     390               0 :             pszSrcNodata = argv[++i];
     391                 :         }
     392             741 :         else if( EQUAL(argv[i],"-dstnodata") && i < argc-1 )
     393                 :         {
     394               1 :             pszDstNodata = argv[++i];
     395                 :         }
     396             741 :         else if( EQUAL(argv[i],"-tr") && i < argc-2 )
     397                 :         {
     398               2 :             dfXRes = atof(argv[++i]);
     399               2 :             dfYRes = fabs(atof(argv[++i]));
     400               2 :             if( dfXRes == 0 || dfYRes == 0 )
     401                 :             {
     402               0 :                 printf( "Wrong value for -tr parameters\n");
     403               0 :                 Usage();
     404               0 :                 exit( 2 );
     405                 :             }
     406               2 :             bCreateOutput = TRUE;
     407                 :         }
     408             738 :         else if( EQUAL(argv[i],"-ot") && i < argc-1 )
     409                 :         {
     410                 :             int iType;
     411                 :             
     412              12 :             for( iType = 1; iType < GDT_TypeCount; iType++ )
     413                 :             {
     414              22 :                 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
     415              11 :                     && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
     416                 :                              argv[i+1]) )
     417                 :                 {
     418               1 :                     eOutputType = (GDALDataType) iType;
     419                 :                 }
     420                 :             }
     421                 : 
     422               1 :             if( eOutputType == GDT_Unknown )
     423                 :             {
     424               0 :                 printf( "Unknown output pixel type: %s\n", argv[i+1] );
     425               0 :                 Usage();
     426               0 :                 exit( 2 );
     427                 :             }
     428               1 :             i++;
     429               1 :             bCreateOutput = TRUE;
     430                 :         }
     431             736 :         else if( EQUAL(argv[i],"-wt") && i < argc-1 )
     432                 :         {
     433                 :             int iType;
     434                 :             
     435               0 :             for( iType = 1; iType < GDT_TypeCount; iType++ )
     436                 :             {
     437               0 :                 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
     438               0 :                     && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
     439                 :                              argv[i+1]) )
     440                 :                 {
     441               0 :                     eWorkingType = (GDALDataType) iType;
     442                 :                 }
     443                 :             }
     444                 : 
     445               0 :             if( eWorkingType == GDT_Unknown )
     446                 :             {
     447               0 :                 printf( "Unknown output pixel type: %s\n", argv[i+1] );
     448               0 :                 Usage();
     449               0 :                 exit( 2 );
     450                 :             }
     451               0 :             i++;
     452                 :         }
     453             742 :         else if( EQUAL(argv[i],"-ts") && i < argc-2 )
     454                 :         {
     455               6 :             nForcePixels = atoi(argv[++i]);
     456               6 :             nForceLines = atoi(argv[++i]);
     457               6 :             bCreateOutput = TRUE;
     458                 :         }
     459             731 :         else if( EQUAL(argv[i],"-te") && i < argc-4 )
     460                 :         {
     461               1 :             dfMinX = atof(argv[++i]);
     462               1 :             dfMinY = atof(argv[++i]);
     463               1 :             dfMaxX = atof(argv[++i]);
     464               1 :             dfMaxY = atof(argv[++i]);
     465               1 :             bCreateOutput = TRUE;
     466                 :         }
     467             729 :         else if( EQUAL(argv[i],"-rn") )
     468               1 :             eResampleAlg = GRA_NearestNeighbour;
     469                 : 
     470             728 :         else if( EQUAL(argv[i],"-rb") )
     471               1 :             eResampleAlg = GRA_Bilinear;
     472                 : 
     473             727 :         else if( EQUAL(argv[i],"-rc") )
     474               1 :             eResampleAlg = GRA_Cubic;
     475                 : 
     476             726 :         else if( EQUAL(argv[i],"-rcs") )
     477               1 :             eResampleAlg = GRA_CubicSpline;
     478                 : 
     479             946 :         else if( EQUAL(argv[i],"-r") && i < argc - 1 )
     480                 :         {
     481             221 :             if ( EQUAL(argv[++i], "near") )
     482              44 :                 eResampleAlg = GRA_NearestNeighbour;
     483             177 :             else if ( EQUAL(argv[i], "bilinear") )
     484              44 :                 eResampleAlg = GRA_Bilinear;
     485             133 :             else if ( EQUAL(argv[i], "cubic") )
     486              44 :                 eResampleAlg = GRA_Cubic;
     487              89 :             else if ( EQUAL(argv[i], "cubicspline") )
     488              44 :                 eResampleAlg = GRA_CubicSpline;
     489              45 :             else if ( EQUAL(argv[i], "lanczos") )
     490              45 :                 eResampleAlg = GRA_Lanczos;
     491                 :             else
     492                 :             {
     493               0 :                 printf( "Unknown resampling method: \"%s\".\n", argv[i] );
     494               0 :                 Usage();
     495                 :             }
     496                 :         }
     497                 : 
     498             507 :         else if( EQUAL(argv[i],"-cutline") && i < argc-1 )
     499                 :         {
     500               3 :             pszCutlineDSName = argv[++i];
     501                 :         }
     502             501 :         else if( EQUAL(argv[i],"-cwhere") && i < argc-1 )
     503                 :         {
     504               0 :             pszCWHERE = argv[++i];
     505                 :         }
     506             504 :         else if( EQUAL(argv[i],"-cl") && i < argc-1 )
     507                 :         {
     508               3 :             pszCLayer = argv[++i];
     509                 :         }
     510             498 :         else if( EQUAL(argv[i],"-csql") && i < argc-1 )
     511                 :         {
     512               0 :             pszCSQL = argv[++i];
     513                 :         }
     514             498 :         else if( EQUAL(argv[i],"-cblend") && i < argc-1 )
     515                 :         {
     516                 :             papszWarpOptions = 
     517                 :                 CSLSetNameValue( papszWarpOptions, 
     518               0 :                                  "CUTLINE_BLEND_DIST", argv[++i] );
     519                 :         }
     520             498 :         else if( argv[i][0] == '-' )
     521               0 :             Usage();
     522                 : 
     523                 :         else 
     524             498 :             papszSrcFiles = CSLAddString( papszSrcFiles, argv[i] );
     525                 :     }
     526                 : /* -------------------------------------------------------------------- */
     527                 : /*      Check that incompatible options are not used                    */
     528                 : /* -------------------------------------------------------------------- */
     529                 : 
     530             249 :     if ((nForcePixels != 0 || nForceLines != 0) && 
     531                 :         (dfXRes != 0 && dfYRes != 0))
     532                 :     {
     533               0 :         printf( "-tr and -ts options cannot be used at the same time\n");
     534               0 :         Usage();
     535               0 :         exit( 2 );
     536                 :     }
     537                 : 
     538                 : /* -------------------------------------------------------------------- */
     539                 : /*      The last filename in the file list is really our destination    */
     540                 : /*      file.                                                           */
     541                 : /* -------------------------------------------------------------------- */
     542             249 :     if( CSLCount(papszSrcFiles) > 1 )
     543                 :     {
     544             249 :         pszDstFilename = papszSrcFiles[CSLCount(papszSrcFiles)-1];
     545             249 :         papszSrcFiles[CSLCount(papszSrcFiles)-1] = NULL;
     546                 :     }
     547                 : 
     548             249 :     if( pszDstFilename == NULL )
     549               0 :         Usage();
     550                 : 
     551                 : /* -------------------------------------------------------------------- */
     552                 : /*      Does the output dataset already exist?                          */
     553                 : /* -------------------------------------------------------------------- */
     554             249 :     CPLPushErrorHandler( CPLQuietErrorHandler );
     555             249 :     hDstDS = GDALOpen( pszDstFilename, GA_Update );
     556             249 :     CPLPopErrorHandler();
     557                 : 
     558             249 :     if( hDstDS != NULL && bCreateOutput )
     559                 :     {
     560                 :         fprintf( stderr, 
     561                 :                  "Output dataset %s exists,\n"
     562                 :                  "but some commandline options were provided indicating a new dataset\n"
     563                 :                  "should be created.  Please delete existing dataset and run again.\n",
     564               0 :                  pszDstFilename );
     565               0 :         exit( 1 );
     566                 :     }
     567                 : 
     568                 :     /* Avoid overwriting an existing destination file that cannot be opened in */
     569                 :     /* update mode with a new GTiff file */
     570             249 :     if ( hDstDS == NULL )
     571                 :     {
     572             249 :         CPLPushErrorHandler( CPLQuietErrorHandler );
     573             249 :         hDstDS = GDALOpen( pszDstFilename, GA_ReadOnly );
     574             249 :         CPLPopErrorHandler();
     575                 :         
     576             249 :         if (hDstDS)
     577                 :         {
     578                 :             fprintf( stderr, 
     579                 :                      "Output dataset %s exists, but cannot be opened in update mode\n",
     580               0 :                      pszDstFilename );
     581               0 :             GDALClose(hDstDS);
     582               0 :             exit( 1 );
     583                 :         }
     584                 :     }
     585                 : 
     586                 : /* -------------------------------------------------------------------- */
     587                 : /*      If not, we need to create it.                                   */
     588                 : /* -------------------------------------------------------------------- */
     589             249 :     int   bInitDestSetForFirst = FALSE;
     590                 : 
     591             249 :     if( hDstDS == NULL )
     592                 :     {
     593                 :         hDstDS = GDALWarpCreateOutput( papszSrcFiles, pszDstFilename,pszFormat,
     594                 :                                        papszTO, &papszCreateOptions, 
     595             249 :                                        eOutputType );
     596             249 :         bCreateOutput = TRUE;
     597                 : 
     598             249 :         if( CSLFetchNameValue( papszWarpOptions, "INIT_DEST" ) == NULL 
     599                 :             && pszDstNodata == NULL )
     600                 :         {
     601                 :             papszWarpOptions = CSLSetNameValue(papszWarpOptions,
     602             248 :                                                "INIT_DEST", "0");
     603             248 :             bInitDestSetForFirst = TRUE;
     604                 :         }
     605               1 :         else if( CSLFetchNameValue( papszWarpOptions, "INIT_DEST" ) == NULL )
     606                 :         {
     607                 :             papszWarpOptions = CSLSetNameValue(papszWarpOptions,
     608               1 :                                                "INIT_DEST", "NO_DATA" );
     609               1 :             bInitDestSetForFirst = TRUE;
     610                 :         }
     611                 : 
     612             249 :         CSLDestroy( papszCreateOptions );
     613             249 :         papszCreateOptions = NULL;
     614                 :     }
     615                 : 
     616             249 :     if( hDstDS == NULL )
     617               0 :         exit( 1 );
     618                 : 
     619                 : /* -------------------------------------------------------------------- */
     620                 : /*      If we have a cutline datasource read it and attach it in the    */
     621                 : /*      warp options.                                                   */
     622                 : /* -------------------------------------------------------------------- */
     623             249 :     if( pszCutlineDSName != NULL )
     624                 :     {
     625                 :         LoadCutline( pszCutlineDSName, pszCLayer, pszCWHERE, pszCSQL, 
     626               3 :                      &hCutline );
     627                 :     }
     628                 : 
     629                 : /* -------------------------------------------------------------------- */
     630                 : /*      Loop over all source files, processing each in turn.            */
     631                 : /* -------------------------------------------------------------------- */
     632                 :     int iSrc;
     633                 : 
     634             992 :     for( iSrc = 0; papszSrcFiles[iSrc] != NULL; iSrc++ )
     635                 :     {
     636                 :         GDALDatasetH hSrcDS;
     637                 :        
     638                 : /* -------------------------------------------------------------------- */
     639                 : /*      Open this file.                                                 */
     640                 : /* -------------------------------------------------------------------- */
     641             249 :         hSrcDS = GDALOpen( papszSrcFiles[iSrc], GA_ReadOnly );
     642                 :     
     643             249 :         if( hSrcDS == NULL )
     644               0 :             exit( 2 );
     645                 : 
     646             249 :         if( !bQuiet )
     647             249 :             printf( "Processing input file %s.\n", papszSrcFiles[iSrc] );
     648                 : 
     649                 : /* -------------------------------------------------------------------- */
     650                 : /*      Warns if the file has a color table and something more          */
     651                 : /*      complicated than nearest neighbour resampling is asked          */
     652                 : /* -------------------------------------------------------------------- */
     653                 : 
     654             249 :         if ( eResampleAlg != GRA_NearestNeighbour &&
     655                 :              GDALGetRasterColorTable(GDALGetRasterBand(hSrcDS, 1)) != NULL)
     656                 :         {
     657               0 :             if( !bQuiet )
     658                 :                 fprintf( stderr, "Warning: Input file %s has a color table, which will likely lead to "
     659                 :                         "bad results when using a resampling method other than "
     660                 :                         "nearest neighbour. Converting the dataset prior to 24/32 bit "
     661               0 :                         "is advised.\n", papszSrcFiles[iSrc] );
     662                 :         }
     663                 : 
     664                 : /* -------------------------------------------------------------------- */
     665                 : /*      Do we have a source alpha band?                                 */
     666                 : /* -------------------------------------------------------------------- */
     667             249 :         if( GDALGetRasterColorInterpretation( 
     668                 :                 GDALGetRasterBand(hSrcDS,GDALGetRasterCount(hSrcDS)) ) 
     669                 :             == GCI_AlphaBand 
     670                 :             && !bEnableSrcAlpha )
     671                 :         {
     672               0 :             bEnableSrcAlpha = TRUE;
     673               0 :             if( !bQuiet )
     674                 :                 printf( "Using band %d of source image as alpha.\n", 
     675               0 :                         GDALGetRasterCount(hSrcDS) );
     676                 :         }
     677                 : 
     678                 : /* -------------------------------------------------------------------- */
     679                 : /*      Create a transformation object from the source to               */
     680                 : /*      destination coordinate system.                                  */
     681                 : /* -------------------------------------------------------------------- */
     682                 :         hTransformArg = hGenImgProjArg = 
     683             249 :             GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszTO );
     684                 :         
     685             249 :         if( hTransformArg == NULL )
     686               0 :             exit( 1 );
     687                 :         
     688             249 :         pfnTransformer = GDALGenImgProjTransform;
     689                 : 
     690                 : /* -------------------------------------------------------------------- */
     691                 : /*      Warp the transformer with a linear approximator unless the      */
     692                 : /*      acceptable error is zero.                                       */
     693                 : /* -------------------------------------------------------------------- */
     694             249 :         if( dfErrorThreshold != 0.0 )
     695                 :         {
     696                 :             hTransformArg = hApproxArg = 
     697                 :                 GDALCreateApproxTransformer( GDALGenImgProjTransform, 
     698             247 :                                              hGenImgProjArg, dfErrorThreshold);
     699             247 :             pfnTransformer = GDALApproxTransform;
     700                 :         }
     701                 : 
     702                 : /* -------------------------------------------------------------------- */
     703                 : /*      Clear temporary INIT_DEST settings after the first image.       */
     704                 : /* -------------------------------------------------------------------- */
     705             249 :         if( bInitDestSetForFirst && iSrc == 1 )
     706                 :             papszWarpOptions = CSLSetNameValue( papszWarpOptions, 
     707               0 :                                                 "INIT_DEST", NULL );
     708                 : 
     709                 : /* -------------------------------------------------------------------- */
     710                 : /*      Setup warp options.                                             */
     711                 : /* -------------------------------------------------------------------- */
     712             249 :         GDALWarpOptions *psWO = GDALCreateWarpOptions();
     713                 : 
     714             249 :         psWO->papszWarpOptions = CSLDuplicate(papszWarpOptions);
     715             249 :         psWO->eWorkingDataType = eWorkingType;
     716             249 :         psWO->eResampleAlg = eResampleAlg;
     717                 : 
     718             249 :         psWO->hSrcDS = hSrcDS;
     719             249 :         psWO->hDstDS = hDstDS;
     720                 : 
     721             249 :         psWO->pfnTransformer = pfnTransformer;
     722             249 :         psWO->pTransformerArg = hTransformArg;
     723                 : 
     724             249 :         if( !bQuiet )
     725             249 :             psWO->pfnProgress = GDALTermProgress;
     726                 : 
     727             249 :         if( dfWarpMemoryLimit != 0.0 )
     728               1 :             psWO->dfWarpMemoryLimit = dfWarpMemoryLimit;
     729                 : 
     730                 : /* -------------------------------------------------------------------- */
     731                 : /*      Setup band mapping.                                             */
     732                 : /* -------------------------------------------------------------------- */
     733             249 :         if( bEnableSrcAlpha )
     734               0 :             psWO->nBandCount = GDALGetRasterCount(hSrcDS) - 1;
     735                 :         else
     736             249 :             psWO->nBandCount = GDALGetRasterCount(hSrcDS);
     737                 : 
     738             249 :         psWO->panSrcBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
     739             249 :         psWO->panDstBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
     740                 : 
     741             510 :         for( i = 0; i < psWO->nBandCount; i++ )
     742                 :         {
     743             261 :             psWO->panSrcBands[i] = i+1;
     744             261 :             psWO->panDstBands[i] = i+1;
     745                 :         }
     746                 : 
     747                 : /* -------------------------------------------------------------------- */
     748                 : /*      Setup alpha bands used if any.                                  */
     749                 : /* -------------------------------------------------------------------- */
     750             249 :         if( bEnableSrcAlpha )
     751               0 :             psWO->nSrcAlphaBand = GDALGetRasterCount(hSrcDS);
     752                 : 
     753             249 :         if( !bEnableDstAlpha 
     754                 :             && GDALGetRasterCount(hDstDS) == psWO->nBandCount+1 
     755                 :             && GDALGetRasterColorInterpretation( 
     756                 :                 GDALGetRasterBand(hDstDS,GDALGetRasterCount(hDstDS))) 
     757                 :             == GCI_AlphaBand )
     758                 :         {
     759               0 :             if( !bQuiet )
     760                 :                 printf( "Using band %d of destination image as alpha.\n", 
     761               0 :                         GDALGetRasterCount(hDstDS) );
     762                 :                 
     763               0 :             bEnableDstAlpha = TRUE;
     764                 :         }
     765                 : 
     766             249 :         if( bEnableDstAlpha )
     767               1 :             psWO->nDstAlphaBand = GDALGetRasterCount(hDstDS);
     768                 : 
     769                 : /* -------------------------------------------------------------------- */
     770                 : /*      Setup NODATA options.                                           */
     771                 : /* -------------------------------------------------------------------- */
     772             249 :         if( pszSrcNodata != NULL && !EQUALN(pszSrcNodata,"n",1) )
     773                 :         {
     774               0 :             char **papszTokens = CSLTokenizeString( pszSrcNodata );
     775               0 :             int  nTokenCount = CSLCount(papszTokens);
     776                 : 
     777                 :             psWO->padfSrcNoDataReal = (double *) 
     778               0 :                 CPLMalloc(psWO->nBandCount*sizeof(double));
     779                 :             psWO->padfSrcNoDataImag = (double *) 
     780               0 :                 CPLMalloc(psWO->nBandCount*sizeof(double));
     781                 : 
     782               0 :             for( i = 0; i < psWO->nBandCount; i++ )
     783                 :             {
     784               0 :                 if( i < nTokenCount )
     785                 :                 {
     786               0 :                     CPLStringToComplex( papszTokens[i], 
     787                 :                                         psWO->padfSrcNoDataReal + i,
     788               0 :                                         psWO->padfSrcNoDataImag + i );
     789                 :                 }
     790                 :                 else
     791                 :                 {
     792               0 :                     psWO->padfSrcNoDataReal[i] = psWO->padfSrcNoDataReal[i-1];
     793               0 :                     psWO->padfSrcNoDataImag[i] = psWO->padfSrcNoDataImag[i-1];
     794                 :                 }
     795                 :             }
     796                 : 
     797               0 :             CSLDestroy( papszTokens );
     798                 : 
     799                 :             psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
     800               0 :                                                "UNIFIED_SRC_NODATA", "YES" );
     801                 :         }
     802                 : 
     803                 : /* -------------------------------------------------------------------- */
     804                 : /*      If -srcnodata was not specified, but the data has nodata        */
     805                 : /*      values, use them.                                               */
     806                 : /* -------------------------------------------------------------------- */
     807             249 :         if( pszSrcNodata == NULL )
     808                 :         {
     809             249 :             int bHaveNodata = FALSE;
     810             249 :             double dfReal = 0.0;
     811                 : 
     812             510 :             for( i = 0; !bHaveNodata && i < psWO->nBandCount; i++ )
     813                 :             {
     814             261 :                 GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, i+1 );
     815             261 :                 dfReal = GDALGetRasterNoDataValue( hBand, &bHaveNodata );
     816                 :             }
     817                 : 
     818             249 :             if( bHaveNodata )
     819                 :             {
     820               0 :                 if( !bQuiet )
     821                 :                     printf( "Using internal nodata values (eg. %g) for image %s.\n",
     822               0 :                             dfReal, papszSrcFiles[iSrc] );
     823                 :                 psWO->padfSrcNoDataReal = (double *) 
     824               0 :                     CPLMalloc(psWO->nBandCount*sizeof(double));
     825                 :                 psWO->padfSrcNoDataImag = (double *) 
     826               0 :                     CPLMalloc(psWO->nBandCount*sizeof(double));
     827                 :                 
     828               0 :                 for( i = 0; i < psWO->nBandCount; i++ )
     829                 :                 {
     830               0 :                     GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, i+1 );
     831                 : 
     832               0 :                     dfReal = GDALGetRasterNoDataValue( hBand, &bHaveNodata );
     833                 : 
     834               0 :                     if( bHaveNodata )
     835                 :                     {
     836               0 :                         psWO->padfSrcNoDataReal[i] = dfReal;
     837               0 :                         psWO->padfSrcNoDataImag[i] = 0.0;
     838                 :                     }
     839                 :                     else
     840                 :                     {
     841               0 :                         psWO->padfSrcNoDataReal[i] = -123456.789;
     842               0 :                         psWO->padfSrcNoDataImag[i] = 0.0;
     843                 :                     }
     844                 :                 }
     845                 :             }
     846                 :         }
     847                 : 
     848                 : /* -------------------------------------------------------------------- */
     849                 : /*      If the output dataset was created, and we have a destination    */
     850                 : /*      nodata value, go through marking the bands with the information.*/
     851                 : /* -------------------------------------------------------------------- */
     852             249 :         if( pszDstNodata != NULL )
     853                 :         {
     854               1 :             char **papszTokens = CSLTokenizeString( pszDstNodata );
     855               1 :             int  nTokenCount = CSLCount(papszTokens);
     856                 : 
     857                 :             psWO->padfDstNoDataReal = (double *) 
     858               1 :                 CPLMalloc(psWO->nBandCount*sizeof(double));
     859                 :             psWO->padfDstNoDataImag = (double *) 
     860               1 :                 CPLMalloc(psWO->nBandCount*sizeof(double));
     861                 : 
     862               2 :             for( i = 0; i < psWO->nBandCount; i++ )
     863                 :             {
     864               1 :                 if( i < nTokenCount )
     865                 :                 {
     866               1 :                     CPLStringToComplex( papszTokens[i], 
     867                 :                                         psWO->padfDstNoDataReal + i,
     868               2 :                                         psWO->padfDstNoDataImag + i );
     869                 :                 }
     870                 :                 else
     871                 :                 {
     872               0 :                     psWO->padfDstNoDataReal[i] = psWO->padfDstNoDataReal[i-1];
     873               0 :                     psWO->padfDstNoDataImag[i] = psWO->padfDstNoDataImag[i-1];
     874                 :                 }
     875                 :                 
     876               1 :                 GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, i+1 );
     877               1 :                 int bClamped = FALSE, bRounded = FALSE;
     878                 : 
     879                 : #define CLAMP(val,type,minval,maxval) \
     880                 :     do { if (val < minval) { bClamped = TRUE; val = minval; } \
     881                 :     else if (val > maxval) { bClamped = TRUE; val = maxval; } \
     882                 :     else if (val != (type)val) { bRounded = TRUE; val = (type)(val + 0.5); } } \
     883                 :     while(0)
     884                 : 
     885               1 :                 switch(GDALGetRasterDataType(hBand))
     886                 :                 {
     887                 :                     case GDT_Byte:
     888               1 :                         CLAMP(psWO->padfDstNoDataReal[i], GByte,
     889                 :                               0.0, 255.0);
     890               1 :                         break;
     891                 :                     case GDT_Int16:
     892               0 :                         CLAMP(psWO->padfDstNoDataReal[i], GInt16,
     893                 :                               -32768.0, 32767.0);
     894               0 :                         break;
     895                 :                     case GDT_UInt16:
     896               0 :                         CLAMP(psWO->padfDstNoDataReal[i], GUInt16,
     897                 :                               0.0, 65535.0);
     898               0 :                         break;
     899                 :                     case GDT_Int32:
     900               0 :                         CLAMP(psWO->padfDstNoDataReal[i], GInt32,
     901                 :                               -2147483648.0, 2147483647.0);
     902               0 :                         break;
     903                 :                     case GDT_UInt32:
     904               0 :                         CLAMP(psWO->padfDstNoDataReal[i], GUInt32,
     905                 :                               0.0, 4294967295.0);
     906                 :                         break;
     907                 :                     default:
     908                 :                         break;
     909                 :                 }
     910                 :                     
     911               1 :                 if (bClamped)
     912                 :                 {
     913                 :                     printf( "for band %d, destination nodata value has been clamped "
     914                 :                            "to %.0f, the original value being out of range.\n",
     915               0 :                            i + 1, psWO->padfDstNoDataReal[i]);
     916                 :                 }
     917               1 :                 else if(bRounded)
     918                 :                 {
     919                 :                     printf("for band %d, destination nodata value has been rounded "
     920                 :                            "to %.0f, %s being an integer datatype.\n",
     921                 :                            i + 1, psWO->padfDstNoDataReal[i],
     922               0 :                            GDALGetDataTypeName(GDALGetRasterDataType(hBand)));
     923                 :                 }
     924                 : 
     925               1 :                 if( bCreateOutput )
     926                 :                 {
     927                 :                     GDALSetRasterNoDataValue( 
     928                 :                         GDALGetRasterBand( hDstDS, psWO->panDstBands[i] ), 
     929               1 :                         psWO->padfDstNoDataReal[i] );
     930                 :                 }
     931                 :             }
     932                 : 
     933               1 :             CSLDestroy( papszTokens );
     934                 :         }
     935                 : 
     936                 : /* -------------------------------------------------------------------- */
     937                 : /*      If we have a cutline, transform it into the source              */
     938                 : /*      pixel/line coordinate system and insert into warp options.      */
     939                 : /* -------------------------------------------------------------------- */
     940             249 :         if( hCutline != NULL )
     941                 :         {
     942                 :             TransformCutlineToSource( hSrcDS, hCutline, 
     943                 :                                       &(psWO->papszWarpOptions), 
     944               3 :                                       papszTO );
     945                 :         }
     946                 : 
     947                 : /* -------------------------------------------------------------------- */
     948                 : /*      If we are producing VRT output, then just initialize it with    */
     949                 : /*      the warp options and write out now rather than proceeding       */
     950                 : /*      with the operations.                                            */
     951                 : /* -------------------------------------------------------------------- */
     952             249 :         if( bVRT )
     953                 :         {
     954               2 :             if( GDALInitializeWarpedVRT( hDstDS, psWO ) != CE_None )
     955               0 :                 exit( 1 );
     956                 : 
     957               2 :             GDALClose( hDstDS );
     958               2 :             GDALClose( hSrcDS );
     959                 : 
     960                 :             /* The warped VRT will clean itself the transformer used */
     961                 :             /* So we have only to destroy the hGenImgProjArg if we */
     962                 :             /* have wrapped it inside the hApproxArg */
     963               2 :             if (pfnTransformer == GDALApproxTransform)
     964                 :             {
     965               1 :                 if( hGenImgProjArg != NULL )
     966               1 :                     GDALDestroyGenImgProjTransformer( hGenImgProjArg );
     967                 :             }
     968                 : 
     969               2 :             GDALDestroyWarpOptions( psWO );
     970                 : 
     971               2 :             CPLFree( pszDstFilename );
     972               2 :             CSLDestroy( argv );
     973               2 :             CSLDestroy( papszSrcFiles );
     974               2 :             CSLDestroy( papszWarpOptions );
     975               2 :             CSLDestroy( papszTO );
     976                 :     
     977               2 :             GDALDumpOpenDatasets( stderr );
     978                 :         
     979               2 :             GDALDestroyDriverManager();
     980                 :         
     981               2 :             return 0;
     982                 :         }
     983                 : 
     984                 : /* -------------------------------------------------------------------- */
     985                 : /*      Initialize and execute the warp.                                */
     986                 : /* -------------------------------------------------------------------- */
     987             247 :         GDALWarpOperation oWO;
     988                 : 
     989             247 :         if( oWO.Initialize( psWO ) == CE_None )
     990                 :         {
     991             247 :             if( bMulti )
     992                 :                 oWO.ChunkAndWarpMulti( 0, 0, 
     993                 :                                        GDALGetRasterXSize( hDstDS ),
     994               1 :                                        GDALGetRasterYSize( hDstDS ) );
     995                 :             else
     996                 :                 oWO.ChunkAndWarpImage( 0, 0, 
     997                 :                                        GDALGetRasterXSize( hDstDS ),
     998             246 :                                        GDALGetRasterYSize( hDstDS ) );
     999                 :         }
    1000                 : 
    1001                 : /* -------------------------------------------------------------------- */
    1002                 : /*      Cleanup                                                         */
    1003                 : /* -------------------------------------------------------------------- */
    1004             247 :         if( hApproxArg != NULL )
    1005             246 :             GDALDestroyApproxTransformer( hApproxArg );
    1006                 :         
    1007             247 :         if( hGenImgProjArg != NULL )
    1008             247 :             GDALDestroyGenImgProjTransformer( hGenImgProjArg );
    1009                 :         
    1010             247 :         GDALDestroyWarpOptions( psWO );
    1011                 : 
    1012             247 :         GDALClose( hSrcDS );
    1013             247 :     }
    1014                 : 
    1015                 : /* -------------------------------------------------------------------- */
    1016                 : /*      Final Cleanup.                                                  */
    1017                 : /* -------------------------------------------------------------------- */
    1018             247 :     GDALClose( hDstDS );
    1019                 :     
    1020             247 :     CPLFree( pszDstFilename );
    1021             247 :     CSLDestroy( argv );
    1022             247 :     CSLDestroy( papszSrcFiles );
    1023             247 :     CSLDestroy( papszWarpOptions );
    1024             247 :     CSLDestroy( papszTO );
    1025                 : 
    1026             247 :     GDALDumpOpenDatasets( stderr );
    1027                 : 
    1028             247 :     GDALDestroyDriverManager();
    1029                 :     
    1030                 : #ifdef OGR_ENABLED
    1031             247 :     if( hCutline != NULL )
    1032               3 :         OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
    1033             247 :     OGRCleanupAll();
    1034                 : #endif
    1035                 : 
    1036             247 :     return 0;
    1037                 : }
    1038                 : 
    1039                 : /************************************************************************/
    1040                 : /*                        GDALWarpCreateOutput()                        */
    1041                 : /*                                                                      */
    1042                 : /*      Create the output file based on various commandline options,    */
    1043                 : /*      and the input file.                                             */
    1044                 : /************************************************************************/
    1045                 : 
    1046                 : static GDALDatasetH 
    1047             249 : GDALWarpCreateOutput( char **papszSrcFiles, const char *pszFilename, 
    1048                 :                       const char *pszFormat, char **papszTO, 
    1049                 :                       char ***ppapszCreateOptions, GDALDataType eDT )
    1050                 : 
    1051                 : 
    1052                 : {
    1053                 :     GDALDriverH hDriver;
    1054                 :     GDALDatasetH hDstDS;
    1055                 :     void *hTransformArg;
    1056             249 :     GDALColorTableH hCT = NULL;
    1057             249 :     double dfWrkMinX=0, dfWrkMaxX=0, dfWrkMinY=0, dfWrkMaxY=0;
    1058             249 :     double dfWrkResX=0, dfWrkResY=0;
    1059             249 :     int nDstBandCount = 0;
    1060                 : 
    1061                 : /* -------------------------------------------------------------------- */
    1062                 : /*      Find the output driver.                                         */
    1063                 : /* -------------------------------------------------------------------- */
    1064             249 :     hDriver = GDALGetDriverByName( pszFormat );
    1065             249 :     if( hDriver == NULL 
    1066                 :         || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
    1067                 :     {
    1068                 :         int iDr;
    1069                 :         
    1070                 :         printf( "Output driver `%s' not recognised or does not support\n", 
    1071               0 :                 pszFormat );
    1072                 :         printf( "direct output file creation.  The following format drivers are configured\n"
    1073               0 :                 "and support direct output:\n" );
    1074                 : 
    1075               0 :         for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
    1076                 :         {
    1077               0 :             GDALDriverH hDriver = GDALGetDriver(iDr);
    1078                 : 
    1079               0 :             if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL )
    1080                 :             {
    1081                 :                 printf( "  %s: %s\n",
    1082                 :                         GDALGetDriverShortName( hDriver  ),
    1083               0 :                         GDALGetDriverLongName( hDriver ) );
    1084                 :             }
    1085                 :         }
    1086               0 :         printf( "\n" );
    1087               0 :         exit( 1 );
    1088                 :     }
    1089                 : 
    1090                 : /* -------------------------------------------------------------------- */
    1091                 : /*      For virtual output files, we have to set a special subclass     */
    1092                 : /*      of dataset to create.                                           */
    1093                 : /* -------------------------------------------------------------------- */
    1094             249 :     if( bVRT )
    1095                 :         *ppapszCreateOptions = 
    1096                 :             CSLSetNameValue( *ppapszCreateOptions, "SUBCLASS", 
    1097               2 :                              "VRTWarpedDataset" );
    1098                 : 
    1099                 : /* -------------------------------------------------------------------- */
    1100                 : /*      Loop over all input files to collect extents.                   */
    1101                 : /* -------------------------------------------------------------------- */
    1102                 :     int     iSrc;
    1103             249 :     char    *pszThisTargetSRS = (char*)CSLFetchNameValue( papszTO, "DST_SRS" );
    1104             249 :     if( pszThisTargetSRS != NULL )
    1105               8 :         pszThisTargetSRS = CPLStrdup( pszThisTargetSRS );
    1106                 : 
    1107             498 :     for( iSrc = 0; papszSrcFiles[iSrc] != NULL; iSrc++ )
    1108                 :     {
    1109                 :         GDALDatasetH hSrcDS;
    1110             249 :         const char *pszThisSourceSRS = CSLFetchNameValue(papszTO,"SRC_SRS");
    1111                 : 
    1112             249 :         hSrcDS = GDALOpen( papszSrcFiles[iSrc], GA_ReadOnly );
    1113             249 :         if( hSrcDS == NULL )
    1114               0 :             exit( 1 );
    1115                 : 
    1116                 : /* -------------------------------------------------------------------- */
    1117                 : /*      Check that there's at least one raster band                     */
    1118                 : /* -------------------------------------------------------------------- */
    1119             249 :         if ( GDALGetRasterCount(hSrcDS) == 0 )
    1120                 :         {
    1121               0 :             fprintf(stderr, "Input file %s has no raster bands.\n", papszSrcFiles[iSrc] );
    1122               0 :             exit( 1 );
    1123                 :         }
    1124                 : 
    1125             249 :         if( eDT == GDT_Unknown )
    1126             248 :             eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1));
    1127                 : 
    1128                 : /* -------------------------------------------------------------------- */
    1129                 : /*      If we are processing the first file, and it has a color         */
    1130                 : /*      table, then we will copy it to the destination file.            */
    1131                 : /* -------------------------------------------------------------------- */
    1132             249 :         if( iSrc == 0 )
    1133                 :         {
    1134             249 :             nDstBandCount = GDALGetRasterCount(hSrcDS);
    1135             249 :             hCT = GDALGetRasterColorTable( GDALGetRasterBand(hSrcDS,1) );
    1136             249 :             if( hCT != NULL )
    1137                 :             {
    1138               0 :                 hCT = GDALCloneColorTable( hCT );
    1139               0 :                 if( !bQuiet )
    1140                 :                     printf( "Copying color table from %s to new file.\n", 
    1141               0 :                             papszSrcFiles[iSrc] );
    1142                 :             }
    1143                 :         }
    1144                 : 
    1145                 : /* -------------------------------------------------------------------- */
    1146                 : /*      Get the sourcesrs from the dataset, if not set already.         */
    1147                 : /* -------------------------------------------------------------------- */
    1148             249 :         if( pszThisSourceSRS == NULL )
    1149                 :         {
    1150             249 :             const char *pszMethod = CSLFetchNameValue( papszTO, "METHOD" );
    1151                 : 
    1152             249 :             if( GDALGetProjectionRef( hSrcDS ) != NULL 
    1153                 :                 && strlen(GDALGetProjectionRef( hSrcDS )) > 0
    1154                 :                 && (pszMethod == NULL || EQUAL(pszMethod,"GEOTRANSFORM")) )
    1155             235 :                 pszThisSourceSRS = GDALGetProjectionRef( hSrcDS );
    1156                 :             
    1157              14 :             else if( GDALGetGCPProjection( hSrcDS ) != NULL
    1158                 :                      && strlen(GDALGetGCPProjection(hSrcDS)) > 0 
    1159                 :                      && GDALGetGCPCount( hSrcDS ) > 1 
    1160                 :                      && (pszMethod == NULL || EQUALN(pszMethod,"GCP_",4)) )
    1161              14 :                 pszThisSourceSRS = GDALGetGCPProjection( hSrcDS );
    1162               0 :             else if( pszMethod != NULL && EQUAL(pszMethod,"RPC") )
    1163               0 :                 pszThisSourceSRS = SRS_WKT_WGS84;
    1164                 :             else
    1165               0 :                 pszThisSourceSRS = "";
    1166                 :         }
    1167                 : 
    1168             249 :         if( pszThisTargetSRS == NULL )
    1169             241 :             pszThisTargetSRS = CPLStrdup( pszThisSourceSRS );
    1170                 :         
    1171                 : /* -------------------------------------------------------------------- */
    1172                 : /*      Create a transformation object from the source to               */
    1173                 : /*      destination coordinate system.                                  */
    1174                 : /* -------------------------------------------------------------------- */
    1175                 :         hTransformArg = 
    1176             249 :             GDALCreateGenImgProjTransformer2( hSrcDS, NULL, papszTO );
    1177                 :         
    1178             249 :         if( hTransformArg == NULL )
    1179                 :         {
    1180               0 :             CPLFree( pszThisTargetSRS );
    1181               0 :             GDALClose( hSrcDS );
    1182               0 :             return NULL;
    1183                 :         }
    1184                 : 
    1185                 : /* -------------------------------------------------------------------- */
    1186                 : /*      Get approximate output definition.                              */
    1187                 : /* -------------------------------------------------------------------- */
    1188                 :         double adfThisGeoTransform[6];
    1189                 :         double adfExtent[4];
    1190                 :         int    nThisPixels, nThisLines;
    1191                 : 
    1192             249 :         if( GDALSuggestedWarpOutput2( hSrcDS, 
    1193                 :                                       GDALGenImgProjTransform, hTransformArg, 
    1194                 :                                       adfThisGeoTransform, 
    1195                 :                                       &nThisPixels, &nThisLines, 
    1196                 :                                       adfExtent, 0 ) != CE_None )
    1197                 :         {
    1198               0 :             CPLFree( pszThisTargetSRS );
    1199               0 :             GDALClose( hSrcDS );
    1200               0 :             return NULL;
    1201                 :         }
    1202                 :         
    1203             249 :         if (CPLGetConfigOption( "CHECK_WITH_INVERT_PROJ", NULL ) == NULL)
    1204                 :         {
    1205             249 :             double MinX = adfExtent[0];
    1206             249 :             double MaxX = adfExtent[2];
    1207             249 :             double MaxY = adfExtent[3];
    1208             249 :             double MinY = adfExtent[1];
    1209             249 :             int bSuccess = TRUE;
    1210                 :             
    1211                 :             /* Check that the the edges of the target image are in the validity area */
    1212                 :             /* of the target projection */
    1213                 : #define N_STEPS 20
    1214                 :             int i,j;
    1215            5398 :             for(i=0;i<=N_STEPS && bSuccess;i++)
    1216                 :             {
    1217          113198 :                 for(j=0;j<=N_STEPS && bSuccess;j++)
    1218                 :                 {
    1219          108049 :                     double dfRatioI = i * 1.0 / N_STEPS;
    1220          108049 :                     double dfRatioJ = j * 1.0 / N_STEPS;
    1221          108049 :                     double expected_x = (1 - dfRatioI) * MinX + dfRatioI * MaxX;
    1222          108049 :                     double expected_y = (1 - dfRatioJ) * MinY + dfRatioJ * MaxY;
    1223          108049 :                     double x = expected_x;
    1224          108049 :                     double y = expected_y;
    1225          108049 :                     double z = 0;
    1226                 :                     /* Target SRS coordinates to source image pixel coordinates */
    1227          108049 :                     if (!GDALGenImgProjTransform(hTransformArg, TRUE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
    1228               0 :                         bSuccess = FALSE;
    1229                 :                     /* Source image pixel coordinates to target SRS coordinates */
    1230          108049 :                     if (!GDALGenImgProjTransform(hTransformArg, FALSE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
    1231               0 :                         bSuccess = FALSE;
    1232          108049 :                     if (fabs(x - expected_x) > (MaxX - MinX) / nThisPixels ||
    1233                 :                         fabs(y - expected_y) > (MaxY - MinY) / nThisLines)
    1234               4 :                         bSuccess = FALSE;
    1235                 :                 }
    1236                 :             }
    1237                 :             
    1238                 :             /* If not, retry with CHECK_WITH_INVERT_PROJ=TRUE that forces ogrct.cpp */
    1239                 :             /* to check the consistency of each requested projection result with the */
    1240                 :             /* invert projection */
    1241             249 :             if (!bSuccess)
    1242                 :             {
    1243               4 :                 CPLSetConfigOption( "CHECK_WITH_INVERT_PROJ", "TRUE" );
    1244               4 :                 CPLDebug("WARP", "Recompute out extent with CHECK_WITH_INVERT_PROJ=TRUE");
    1245               4 :                 GDALDestroyGenImgProjTransformer(hTransformArg);
    1246                 :                 hTransformArg = 
    1247               4 :                     GDALCreateGenImgProjTransformer2( hSrcDS, NULL, papszTO );
    1248                 :                     
    1249               4 :                 if( GDALSuggestedWarpOutput2( hSrcDS, 
    1250                 :                                       GDALGenImgProjTransform, hTransformArg, 
    1251                 :                                       adfThisGeoTransform, 
    1252                 :                                       &nThisPixels, &nThisLines, 
    1253                 :                                       adfExtent, 0 ) != CE_None )
    1254                 :                 {
    1255               0 :                     CPLFree( pszThisTargetSRS );
    1256               0 :                     GDALClose( hSrcDS );
    1257               0 :                     return NULL;
    1258                 :                 }
    1259                 :             }
    1260                 :         }
    1261                 : 
    1262                 : /* -------------------------------------------------------------------- */
    1263                 : /*      Expand the working bounds to include this region, ensure the    */
    1264                 : /*      working resolution is no more than this resolution.             */
    1265                 : /* -------------------------------------------------------------------- */
    1266             498 :         if( dfWrkMaxX == 0.0 && dfWrkMinX == 0.0 )
    1267                 :         {
    1268             249 :             dfWrkMinX = adfExtent[0];
    1269             249 :             dfWrkMaxX = adfExtent[2];
    1270             249 :             dfWrkMaxY = adfExtent[3];
    1271             249 :             dfWrkMinY = adfExtent[1];
    1272             249 :             dfWrkResX = adfThisGeoTransform[1];
    1273             249 :             dfWrkResY = ABS(adfThisGeoTransform[5]);
    1274                 :         }
    1275                 :         else
    1276                 :         {
    1277               0 :             dfWrkMinX = MIN(dfWrkMinX,adfExtent[0]);
    1278               0 :             dfWrkMaxX = MAX(dfWrkMaxX,adfExtent[2]);
    1279               0 :             dfWrkMaxY = MAX(dfWrkMaxY,adfExtent[3]);
    1280               0 :             dfWrkMinY = MIN(dfWrkMinY,adfExtent[1]);
    1281               0 :             dfWrkResX = MIN(dfWrkResX,adfThisGeoTransform[1]);
    1282               0 :             dfWrkResY = MIN(dfWrkResY,ABS(adfThisGeoTransform[5]));
    1283                 :         }
    1284                 :         
    1285             249 :         GDALDestroyGenImgProjTransformer( hTransformArg );
    1286                 : 
    1287             249 :         GDALClose( hSrcDS );
    1288                 :     }
    1289                 : 
    1290                 : /* -------------------------------------------------------------------- */
    1291                 : /*      Did we have any usable sources?                                 */
    1292                 : /* -------------------------------------------------------------------- */
    1293             249 :     if( nDstBandCount == 0 )
    1294                 :     {
    1295                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1296               0 :                   "No usable source images." );
    1297               0 :         CPLFree( pszThisTargetSRS );
    1298               0 :         return NULL;
    1299                 :     }
    1300                 : 
    1301                 : /* -------------------------------------------------------------------- */
    1302                 : /*      Turn the suggested region into a geotransform and suggested     */
    1303                 : /*      number of pixels and lines.                                     */
    1304                 : /* -------------------------------------------------------------------- */
    1305                 :     double adfDstGeoTransform[6];
    1306                 :     int nPixels, nLines;
    1307                 : 
    1308             249 :     adfDstGeoTransform[0] = dfWrkMinX;
    1309             249 :     adfDstGeoTransform[1] = dfWrkResX;
    1310             249 :     adfDstGeoTransform[2] = 0.0;
    1311             249 :     adfDstGeoTransform[3] = dfWrkMaxY;
    1312             249 :     adfDstGeoTransform[4] = 0.0;
    1313             249 :     adfDstGeoTransform[5] = -1 * dfWrkResY;
    1314                 : 
    1315             249 :     nPixels = (int) ((dfWrkMaxX - dfWrkMinX) / dfWrkResX + 0.5);
    1316             249 :     nLines = (int) ((dfWrkMaxY - dfWrkMinY) / dfWrkResY + 0.5);
    1317                 : 
    1318                 : /* -------------------------------------------------------------------- */
    1319                 : /*      Did the user override some parameters?                          */
    1320                 : /* -------------------------------------------------------------------- */
    1321             251 :     if( dfXRes != 0.0 && dfYRes != 0.0 )
    1322                 :     {
    1323               2 :         if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
    1324                 :         {
    1325               2 :             dfMinX = adfDstGeoTransform[0];
    1326               2 :             dfMaxX = adfDstGeoTransform[0] + adfDstGeoTransform[1] * nPixels;
    1327               2 :             dfMaxY = adfDstGeoTransform[3];
    1328               2 :             dfMinY = adfDstGeoTransform[3] + adfDstGeoTransform[5] * nLines;
    1329                 :         }
    1330                 : 
    1331               2 :         nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes);
    1332               2 :         nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes);
    1333               2 :         adfDstGeoTransform[0] = dfMinX;
    1334               2 :         adfDstGeoTransform[3] = dfMaxY;
    1335               2 :         adfDstGeoTransform[1] = dfXRes;
    1336               2 :         adfDstGeoTransform[5] = -dfYRes;
    1337                 :     }
    1338                 : 
    1339             253 :     else if( nForcePixels != 0 && nForceLines != 0 )
    1340                 :     {
    1341               6 :         if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
    1342                 :         {
    1343               6 :             dfMinX = dfWrkMinX;
    1344               6 :             dfMaxX = dfWrkMaxX;
    1345               6 :             dfMaxY = dfWrkMaxY;
    1346               6 :             dfMinY = dfWrkMinY;
    1347                 :         }
    1348                 : 
    1349               6 :         dfXRes = (dfMaxX - dfMinX) / nForcePixels;
    1350               6 :         dfYRes = (dfMaxY - dfMinY) / nForceLines;
    1351                 : 
    1352               6 :         adfDstGeoTransform[0] = dfMinX;
    1353               6 :         adfDstGeoTransform[3] = dfMaxY;
    1354               6 :         adfDstGeoTransform[1] = dfXRes;
    1355               6 :         adfDstGeoTransform[5] = -dfYRes;
    1356                 : 
    1357               6 :         nPixels = nForcePixels;
    1358               6 :         nLines = nForceLines;
    1359                 :     }
    1360                 : 
    1361             241 :     else if( nForcePixels != 0 )
    1362                 :     {
    1363               0 :         if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
    1364                 :         {
    1365               0 :             dfMinX = dfWrkMinX;
    1366               0 :             dfMaxX = dfWrkMaxX;
    1367               0 :             dfMaxY = dfWrkMaxY;
    1368               0 :             dfMinY = dfWrkMinY;
    1369                 :         }
    1370                 : 
    1371               0 :         dfXRes = (dfMaxX - dfMinX) / nForcePixels;
    1372               0 :         dfYRes = dfXRes;
    1373                 : 
    1374               0 :         adfDstGeoTransform[0] = dfMinX;
    1375               0 :         adfDstGeoTransform[3] = dfMaxY;
    1376               0 :         adfDstGeoTransform[1] = dfXRes;
    1377               0 :         adfDstGeoTransform[5] = -dfYRes;
    1378                 : 
    1379               0 :         nPixels = nForcePixels;
    1380               0 :         nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes);
    1381                 :     }
    1382                 : 
    1383             241 :     else if( nForceLines != 0 )
    1384                 :     {
    1385               0 :         if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
    1386                 :         {
    1387               0 :             dfMinX = dfWrkMinX;
    1388               0 :             dfMaxX = dfWrkMaxX;
    1389               0 :             dfMaxY = dfWrkMaxY;
    1390               0 :             dfMinY = dfWrkMinY;
    1391                 :         }
    1392                 : 
    1393               0 :         dfYRes = (dfMaxY - dfMinY) / nForceLines;
    1394               0 :         dfXRes = dfYRes;
    1395                 : 
    1396               0 :         adfDstGeoTransform[0] = dfMinX;
    1397               0 :         adfDstGeoTransform[3] = dfMaxY;
    1398               0 :         adfDstGeoTransform[1] = dfXRes;
    1399               0 :         adfDstGeoTransform[5] = -dfYRes;
    1400                 : 
    1401               0 :         nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes);
    1402               0 :         nLines = nForceLines;
    1403                 :     }
    1404                 : 
    1405             241 :     else if( dfMinX != 0.0 || dfMinY != 0.0 || dfMaxX != 0.0 || dfMaxY != 0.0 )
    1406                 :     {
    1407               1 :         dfXRes = adfDstGeoTransform[1];
    1408               1 :         dfYRes = fabs(adfDstGeoTransform[5]);
    1409                 : 
    1410               1 :         nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes);
    1411               1 :         nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes);
    1412                 : 
    1413               1 :         dfXRes = (dfMaxX - dfMinX) / nPixels;
    1414               1 :         dfYRes = (dfMaxY - dfMinY) / nLines;
    1415                 : 
    1416               1 :         adfDstGeoTransform[0] = dfMinX;
    1417               1 :         adfDstGeoTransform[3] = dfMaxY;
    1418               1 :         adfDstGeoTransform[1] = dfXRes;
    1419               1 :         adfDstGeoTransform[5] = -dfYRes;
    1420                 :     }
    1421                 : 
    1422                 : /* -------------------------------------------------------------------- */
    1423                 : /*      Do we want to generate an alpha band in the output file?        */
    1424                 : /* -------------------------------------------------------------------- */
    1425             249 :     if( bEnableSrcAlpha )
    1426               0 :         nDstBandCount--;
    1427                 : 
    1428             249 :     if( bEnableDstAlpha )
    1429               1 :         nDstBandCount++;
    1430                 : 
    1431                 : /* -------------------------------------------------------------------- */
    1432                 : /*      Create the output file.                                         */
    1433                 : /* -------------------------------------------------------------------- */
    1434             249 :     if( !bQuiet )
    1435             249 :         printf( "Creating output file that is %dP x %dL.\n", nPixels, nLines );
    1436                 : 
    1437                 :     hDstDS = GDALCreate( hDriver, pszFilename, nPixels, nLines, 
    1438             249 :                          nDstBandCount, eDT, *ppapszCreateOptions );
    1439                 :     
    1440             249 :     if( hDstDS == NULL )
    1441                 :     {
    1442               0 :         CPLFree( pszThisTargetSRS );
    1443               0 :         return NULL;
    1444                 :     }
    1445                 : 
    1446                 : /* -------------------------------------------------------------------- */
    1447                 : /*      Write out the projection definition.                            */
    1448                 : /* -------------------------------------------------------------------- */
    1449             249 :     GDALSetProjection( hDstDS, pszThisTargetSRS );
    1450             249 :     GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
    1451                 : 
    1452                 : /* -------------------------------------------------------------------- */
    1453                 : /*      Try to set color interpretation of output file alpha band.      */
    1454                 : /*      TODO: We should likely try to copy the other bands too.         */
    1455                 : /* -------------------------------------------------------------------- */
    1456             249 :     if( bEnableDstAlpha )
    1457                 :     {
    1458                 :         GDALSetRasterColorInterpretation( 
    1459                 :             GDALGetRasterBand( hDstDS, nDstBandCount ), 
    1460               1 :             GCI_AlphaBand );
    1461                 :     }
    1462                 : 
    1463                 : /* -------------------------------------------------------------------- */
    1464                 : /*      Copy the color table, if required.                              */
    1465                 : /* -------------------------------------------------------------------- */
    1466             249 :     if( hCT != NULL )
    1467                 :     {
    1468               0 :         GDALSetRasterColorTable( GDALGetRasterBand(hDstDS,1), hCT );
    1469               0 :         GDALDestroyColorTable( hCT );
    1470                 :     }
    1471                 : 
    1472             249 :     CPLFree( pszThisTargetSRS );
    1473             249 :     return hDstDS;
    1474                 : }
    1475                 : 
    1476                 : /************************************************************************/
    1477                 : /*                      GeoTransform_Transformer()                      */
    1478                 : /*                                                                      */
    1479                 : /*      Convert points from georef coordinates to pixel/line based      */
    1480                 : /*      on a geotransform.                                              */
    1481                 : /************************************************************************/
    1482                 : 
    1483                 : class CutlineTransformer : public OGRCoordinateTransformation
    1484               6 : {
    1485                 : public:
    1486                 : 
    1487                 :     void         *hSrcImageTransformer;
    1488                 : 
    1489               0 :     virtual OGRSpatialReference *GetSourceCS() { return NULL; }
    1490               9 :     virtual OGRSpatialReference *GetTargetCS() { return NULL; }
    1491                 : 
    1492               3 :     virtual int Transform( int nCount, 
    1493                 :                            double *x, double *y, double *z = NULL ) {
    1494                 :         int nResult;
    1495                 : 
    1496               3 :         int *pabSuccess = (int *) CPLCalloc(sizeof(int),nCount);
    1497               3 :         nResult = TransformEx( nCount, x, y, z, pabSuccess );
    1498               3 :         CPLFree( pabSuccess );
    1499                 : 
    1500               3 :         return nResult;
    1501                 :     }
    1502                 : 
    1503               3 :     virtual int TransformEx( int nCount, 
    1504                 :                              double *x, double *y, double *z = NULL,
    1505                 :                              int *pabSuccess = NULL ) {
    1506                 :         return GDALGenImgProjTransform( hSrcImageTransformer, TRUE, 
    1507               3 :                                         nCount, x, y, z, pabSuccess );
    1508                 :     }
    1509                 : };
    1510                 : 
    1511                 : 
    1512                 : /************************************************************************/
    1513                 : /*                            LoadCutline()                             */
    1514                 : /*                                                                      */
    1515                 : /*      Load blend cutline from OGR datasource and attach in warp       */
    1516                 : /*      options, after potentially transforming to destination          */
    1517                 : /*      pixel/line coordinates.                                         */
    1518                 : /************************************************************************/
    1519                 : 
    1520                 : static void
    1521               3 : LoadCutline( const char *pszCutlineDSName, const char *pszCLayer, 
    1522                 :              const char *pszCWHERE, const char *pszCSQL, 
    1523                 :              void **phCutlineRet )
    1524                 : 
    1525                 : {
    1526                 : #ifndef OGR_ENABLED
    1527                 :     CPLError( CE_Failure, CPLE_AppDefined, 
    1528                 :               "Request to load a cutline failed, this build does not support OGR features.\n" );
    1529                 :     exit( 1 );
    1530                 : #else // def OGR_ENABLED
    1531               3 :     OGRRegisterAll();
    1532                 : 
    1533                 : /* -------------------------------------------------------------------- */
    1534                 : /*      Open source vector dataset.                                     */
    1535                 : /* -------------------------------------------------------------------- */
    1536                 :     OGRDataSourceH hSrcDS;
    1537                 : 
    1538               3 :     hSrcDS = OGROpen( pszCutlineDSName, FALSE, NULL );
    1539               3 :     if( hSrcDS == NULL )
    1540               0 :         exit( 1 );
    1541                 : 
    1542                 : /* -------------------------------------------------------------------- */
    1543                 : /*      Get the source layer                                            */
    1544                 : /* -------------------------------------------------------------------- */
    1545               3 :     OGRLayerH hLayer = NULL;
    1546                 : 
    1547               3 :     if( pszCSQL != NULL )
    1548               0 :         hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszCSQL, NULL, NULL ); 
    1549               3 :     else if( pszCLayer != NULL )
    1550               3 :         hLayer = OGR_DS_GetLayerByName( hSrcDS, pszCLayer );
    1551                 :     else
    1552               0 :         hLayer = OGR_DS_GetLayer( hSrcDS, 0 );
    1553                 : 
    1554               3 :     if( hLayer == NULL )
    1555                 :     {
    1556               0 :         fprintf( stderr, "Failed to identify source layer from datasource.\n" );
    1557               0 :         exit( 1 );
    1558                 :     }
    1559                 : 
    1560                 : /* -------------------------------------------------------------------- */
    1561                 : /*      Apply WHERE clause if there is one.                             */
    1562                 : /* -------------------------------------------------------------------- */
    1563               3 :     if( pszCWHERE != NULL )
    1564               0 :         OGR_L_SetAttributeFilter( hLayer, pszCWHERE );
    1565                 : 
    1566                 : /* -------------------------------------------------------------------- */
    1567                 : /*      Collect the geometries from this layer, and build list of       */
    1568                 : /*      burn values.                                                    */
    1569                 : /* -------------------------------------------------------------------- */
    1570                 :     OGRFeatureH hFeat;
    1571               3 :     OGRGeometryH hMultiPolygon = OGR_G_CreateGeometry( wkbMultiPolygon );
    1572                 : 
    1573               3 :     OGR_L_ResetReading( hLayer );
    1574                 :     
    1575               9 :     while( (hFeat = OGR_L_GetNextFeature( hLayer )) != NULL )
    1576                 :     {
    1577               3 :         OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat);
    1578                 : 
    1579               3 :         if( hGeom == NULL )
    1580                 :         {
    1581               0 :             fprintf( stderr, "ERROR: Cutline feature without a geometry.\n" );
    1582               0 :             exit( 1 );
    1583                 :         }
    1584                 :         
    1585               3 :         OGRwkbGeometryType eType = wkbFlatten(OGR_G_GetGeometryType( hGeom ));
    1586                 : 
    1587               3 :         if( eType == wkbPolygon )
    1588               3 :             OGR_G_AddGeometry( hMultiPolygon, hGeom );
    1589               0 :         else if( eType == wkbMultiPolygon )
    1590                 :         {
    1591                 :             int iGeom;
    1592                 : 
    1593               0 :             for( iGeom = 0; iGeom < OGR_G_GetGeometryCount( hGeom ); iGeom++ )
    1594                 :             {
    1595                 :                 OGR_G_AddGeometry( hMultiPolygon, 
    1596               0 :                                    OGR_G_GetGeometryRef(hGeom,iGeom) );
    1597                 :             }
    1598                 :         }
    1599                 :         else
    1600                 :         {
    1601               0 :             fprintf( stderr, "ERROR: Cutline not of polygon type.\n" );
    1602               0 :             exit( 1 );
    1603                 :         }
    1604                 : 
    1605               3 :         OGR_F_Destroy( hFeat );
    1606                 :     }
    1607                 : 
    1608               3 :     if( OGR_G_GetGeometryCount( hMultiPolygon ) == 0 )
    1609                 :     {
    1610               0 :         fprintf( stderr, "ERROR: Did not get any cutline features.\n" );
    1611               0 :         exit( 1 );
    1612                 :     }
    1613                 : 
    1614                 : /* -------------------------------------------------------------------- */
    1615                 : /*      Ensure the coordinate system gets set on the geometry.          */
    1616                 : /* -------------------------------------------------------------------- */
    1617                 :     OGR_G_AssignSpatialReference(
    1618               3 :         hMultiPolygon, OGR_L_GetSpatialRef(hLayer) );
    1619                 : 
    1620               3 :     *phCutlineRet = (void *) hMultiPolygon;
    1621                 : 
    1622                 : /* -------------------------------------------------------------------- */
    1623                 : /*      Cleanup                                                         */
    1624                 : /* -------------------------------------------------------------------- */
    1625               3 :     if( pszCSQL != NULL )
    1626               0 :         OGR_DS_ReleaseResultSet( hSrcDS, hLayer );
    1627                 : 
    1628               3 :     OGR_DS_Destroy( hSrcDS );
    1629                 : #endif
    1630               3 : }
    1631                 : 
    1632                 : /************************************************************************/
    1633                 : /*                      TransformCutlineToSource()                      */
    1634                 : /************************************************************************/
    1635                 : 
    1636                 : static void
    1637               3 : TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
    1638                 :                           char ***ppapszWarpOptions, char **papszTO_In )
    1639                 : 
    1640                 : {
    1641                 : #ifdef OGR_ENABLED
    1642               3 :     OGRGeometryH hMultiPolygon = OGR_G_Clone( (OGRGeometryH) hCutline );
    1643               3 :     char **papszTO = CSLDuplicate( papszTO_In );
    1644                 : 
    1645                 : /* -------------------------------------------------------------------- */
    1646                 : /*      Checkout that SRS are the same.                                 */
    1647                 : /* -------------------------------------------------------------------- */
    1648               3 :     OGRSpatialReferenceH  hRasterSRS = NULL;
    1649               3 :     const char *pszProjection = NULL;
    1650                 : 
    1651               3 :     if( GDALGetProjectionRef( hSrcDS ) != NULL 
    1652                 :         && strlen(GDALGetProjectionRef( hSrcDS )) > 0 )
    1653               3 :         pszProjection = GDALGetProjectionRef( hSrcDS );
    1654               0 :     else if( GDALGetGCPProjection( hSrcDS ) != NULL )
    1655               0 :         pszProjection = GDALGetGCPProjection( hSrcDS );
    1656                 : 
    1657               3 :     if( pszProjection != NULL )
    1658                 :     {
    1659               3 :         hRasterSRS = OSRNewSpatialReference(NULL);
    1660               3 :         if( OSRImportFromWkt( hRasterSRS, (char **)&pszProjection ) != CE_None )
    1661                 :         {
    1662               0 :             OSRDestroySpatialReference(hRasterSRS);
    1663               0 :             hRasterSRS = NULL;
    1664                 :         }
    1665                 :     }
    1666                 : 
    1667               3 :     OGRSpatialReferenceH hSrcSRS = OGR_G_GetSpatialReference( hMultiPolygon );
    1668               3 :     if( hRasterSRS != NULL && hSrcSRS != NULL )
    1669                 :     {
    1670                 :         /* ok, we will reproject */
    1671                 :     }
    1672               0 :     else if( hRasterSRS != NULL && hSrcSRS == NULL )
    1673                 :     {
    1674                 :         fprintf(stderr,
    1675                 :                 "Warning : the source raster dataset has a SRS, but the input vector layer\n"
    1676               0 :                 "not.  Cutline results may be incorrect.\n");
    1677                 :     }
    1678               0 :     else if( hRasterSRS == NULL && hSrcSRS != NULL )
    1679                 :     {
    1680                 :         fprintf(stderr,
    1681                 :                 "Warning : the input vector layer has a SRS, but the source raster dataset does not.\n"
    1682               0 :                 "Cutline results may be incorrect.\n");
    1683                 :     }
    1684                 : 
    1685               3 :     if( hRasterSRS != NULL )
    1686               3 :         OSRDestroySpatialReference(hRasterSRS);
    1687                 : 
    1688                 : /* -------------------------------------------------------------------- */
    1689                 : /*      Extract the cutline SRS WKT.                                    */
    1690                 : /* -------------------------------------------------------------------- */
    1691               3 :     if( hSrcSRS != NULL )
    1692                 :     {
    1693               3 :         char *pszCutlineSRS_WKT = NULL;
    1694                 : 
    1695               3 :         OSRExportToWkt( hSrcSRS, &pszCutlineSRS_WKT );
    1696               3 :         papszTO = CSLSetNameValue( papszTO, "DST_SRS", pszCutlineSRS_WKT );
    1697               3 :         CPLFree( pszCutlineSRS_WKT );
    1698                 :     }
    1699                 :     else
    1700                 :     {
    1701               0 :         int iDstSRS = CSLFindString( papszTO, "DST_SRS" );
    1702               0 :         if( iDstSRS >= 0 )
    1703               0 :             papszTO = CSLRemoveStrings( papszTO, iDstSRS, 1, NULL );
    1704                 :     }
    1705                 : 
    1706                 : /* -------------------------------------------------------------------- */
    1707                 : /*      Transform the geometry to pixel/line coordinates.               */
    1708                 : /* -------------------------------------------------------------------- */
    1709               3 :     CutlineTransformer oTransformer;
    1710                 : 
    1711                 :     oTransformer.hSrcImageTransformer = 
    1712               3 :         GDALCreateGenImgProjTransformer2( hSrcDS, NULL, papszTO );
    1713                 : 
    1714               3 :     CSLDestroy( papszTO );
    1715                 : 
    1716               3 :     if( oTransformer.hSrcImageTransformer == NULL )
    1717               0 :         exit( 1 );
    1718                 : 
    1719                 :     OGR_G_Transform( hMultiPolygon, 
    1720               3 :                      (OGRCoordinateTransformationH) &oTransformer );
    1721                 : 
    1722               3 :     GDALDestroyGenImgProjTransformer( oTransformer.hSrcImageTransformer );
    1723                 : 
    1724                 : /* -------------------------------------------------------------------- */
    1725                 : /*      Convert aggregate geometry into WKT.                            */
    1726                 : /* -------------------------------------------------------------------- */
    1727               3 :     char *pszWKT = NULL;
    1728                 : 
    1729               3 :     OGR_G_ExportToWkt( hMultiPolygon, &pszWKT );
    1730               3 :     OGR_G_DestroyGeometry( hMultiPolygon );
    1731                 : 
    1732                 :     *ppapszWarpOptions = CSLSetNameValue( *ppapszWarpOptions, 
    1733               3 :                                           "CUTLINE", pszWKT );
    1734               3 :     CPLFree( pszWKT );
    1735                 : #endif
    1736               3 : }

Generated by: LCOV version 1.7