LCOV - code coverage report
Current view: directory - apps - gdal_translate.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 672 522 77.7 %
Date: 2012-12-26 Functions: 8 7 87.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdal_translate.cpp 24663 2012-07-07 13:11:43Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL Utilities
       5                 :  * Purpose:  GDAL Image Translator Program
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1998, 2002, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "cpl_vsi.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : #include "gdal_priv.h"
      34                 : #include "ogr_spatialref.h"
      35                 : #include "vrt/vrtdataset.h"
      36                 : #include "commonutils.h"
      37                 : 
      38                 : CPL_CVSID("$Id: gdal_translate.cpp 24663 2012-07-07 13:11:43Z rouault $");
      39                 : 
      40                 : static int ArgIsNumeric( const char * );
      41                 : static void AttachMetadata( GDALDatasetH, char ** );
      42                 : static void CopyBandInfo( GDALRasterBand * poSrcBand, GDALRasterBand * poDstBand,
      43                 :                             int bCanCopyStatsMetadata, int bCopyScale, int bCopyNoData );
      44                 : static int bSubCall = FALSE;
      45                 : 
      46                 : /*  ******************************************************************* */
      47                 : /*                               Usage()                                */
      48                 : /* ******************************************************************** */
      49                 : 
      50               0 : static void Usage()
      51                 : 
      52                 : {
      53                 :     int iDr;
      54                 :         
      55                 :     printf( "Usage: gdal_translate [--help-general]\n"
      56                 :             "       [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
      57                 :             "             CInt16/CInt32/CFloat32/CFloat64}] [-strict]\n"
      58                 :             "       [-of format] [-b band] [-mask band] [-expand {gray|rgb|rgba}]\n"
      59                 :             "       [-outsize xsize[%%] ysize[%%]]\n"
      60                 :             "       [-unscale] [-scale [src_min src_max [dst_min dst_max]]]\n"
      61                 :             "       [-srcwin xoff yoff xsize ysize] [-projwin ulx uly lrx lry] [-epo] [-eco]\n"
      62                 :             "       [-a_srs srs_def] [-a_ullr ulx uly lrx lry] [-a_nodata value]\n"
      63                 :             "       [-gcp pixel line easting northing [elevation]]*\n" 
      64                 :             "       [-mo \"META-TAG=VALUE\"]* [-q] [-sds]\n"
      65                 :             "       [-co \"NAME=VALUE\"]* [-stats]\n"
      66               0 :             "       src_dataset dst_dataset\n\n" );
      67                 : 
      68               0 :     printf( "%s\n\n", GDALVersionInfo( "--version" ) );
      69               0 :     printf( "The following format drivers are configured and support output:\n" );
      70               0 :     for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
      71                 :     {
      72               0 :         GDALDriverH hDriver = GDALGetDriver(iDr);
      73                 :         
      74               0 :         if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
      75                 :             || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY,
      76                 :                                     NULL ) != NULL )
      77                 :         {
      78                 :             printf( "  %s: %s\n",
      79                 :                     GDALGetDriverShortName( hDriver ),
      80               0 :                     GDALGetDriverLongName( hDriver ) );
      81                 :         }
      82                 :     }
      83               0 : }
      84                 : 
      85                 : /************************************************************************/
      86                 : /*                              SrcToDst()                              */
      87                 : /************************************************************************/
      88                 : 
      89               2 : static void SrcToDst( double dfX, double dfY,
      90                 :                       int nSrcXOff, int nSrcYOff,
      91                 :                       int nSrcXSize, int nSrcYSize,
      92                 :                       int nDstXOff, int nDstYOff,
      93                 :                       int nDstXSize, int nDstYSize,
      94                 :                       double &dfXOut, double &dfYOut )
      95                 : 
      96                 : {
      97               2 :     dfXOut = ((dfX - nSrcXOff) / nSrcXSize) * nDstXSize + nDstXOff;
      98               2 :     dfYOut = ((dfY - nSrcYOff) / nSrcYSize) * nDstYSize + nDstYOff;
      99               2 : }
     100                 : 
     101                 : /************************************************************************/
     102                 : /*                          GetSrcDstWindow()                           */
     103                 : /************************************************************************/
     104                 : 
     105              53 : static int FixSrcDstWindow( int* panSrcWin, int* panDstWin,
     106                 :                             int nSrcRasterXSize,
     107                 :                             int nSrcRasterYSize )
     108                 : 
     109                 : {
     110              53 :     const int nSrcXOff = panSrcWin[0];
     111              53 :     const int nSrcYOff = panSrcWin[1];
     112              53 :     const int nSrcXSize = panSrcWin[2];
     113              53 :     const int nSrcYSize = panSrcWin[3];
     114                 : 
     115              53 :     const int nDstXOff = panDstWin[0];
     116              53 :     const int nDstYOff = panDstWin[1];
     117              53 :     const int nDstXSize = panDstWin[2];
     118              53 :     const int nDstYSize = panDstWin[3];
     119                 : 
     120              53 :     int bModifiedX = FALSE, bModifiedY = FALSE;
     121                 : 
     122              53 :     int nModifiedSrcXOff = nSrcXOff;
     123              53 :     int nModifiedSrcYOff = nSrcYOff;
     124                 : 
     125              53 :     int nModifiedSrcXSize = nSrcXSize;
     126              53 :     int nModifiedSrcYSize = nSrcYSize;
     127                 : 
     128                 : /* -------------------------------------------------------------------- */
     129                 : /*      Clamp within the bounds of the available source data.           */
     130                 : /* -------------------------------------------------------------------- */
     131              53 :     if( nModifiedSrcXOff < 0 )
     132                 :     {
     133               1 :         nModifiedSrcXSize += nModifiedSrcXOff;
     134               1 :         nModifiedSrcXOff = 0;
     135                 : 
     136               1 :         bModifiedX = TRUE;
     137                 :     }
     138                 : 
     139              53 :     if( nModifiedSrcYOff < 0 )
     140                 :     {
     141               1 :         nModifiedSrcYSize += nModifiedSrcYOff;
     142               1 :         nModifiedSrcYOff = 0;
     143               1 :         bModifiedY = TRUE;
     144                 :     }
     145                 : 
     146              53 :     if( nModifiedSrcXOff + nModifiedSrcXSize > nSrcRasterXSize )
     147                 :     {
     148               1 :         nModifiedSrcXSize = nSrcRasterXSize - nModifiedSrcXOff;
     149               1 :         bModifiedX = TRUE;
     150                 :     }
     151                 : 
     152              53 :     if( nModifiedSrcYOff + nModifiedSrcYSize > nSrcRasterYSize )
     153                 :     {
     154               1 :         nModifiedSrcYSize = nSrcRasterYSize - nModifiedSrcYOff;
     155               1 :         bModifiedY = TRUE;
     156                 :     }
     157                 : 
     158                 : /* -------------------------------------------------------------------- */
     159                 : /*      Don't do anything if the requesting region is completely off    */
     160                 : /*      the source image.                                               */
     161                 : /* -------------------------------------------------------------------- */
     162              53 :     if( nModifiedSrcXOff >= nSrcRasterXSize
     163                 :         || nModifiedSrcYOff >= nSrcRasterYSize
     164                 :         || nModifiedSrcXSize <= 0 || nModifiedSrcYSize <= 0 )
     165                 :     {
     166               0 :         return FALSE;
     167                 :     }
     168                 : 
     169              53 :     panSrcWin[0] = nModifiedSrcXOff;
     170              53 :     panSrcWin[1] = nModifiedSrcYOff;
     171              53 :     panSrcWin[2] = nModifiedSrcXSize;
     172              53 :     panSrcWin[3] = nModifiedSrcYSize;
     173                 : 
     174                 : /* -------------------------------------------------------------------- */
     175                 : /*      If we haven't had to modify the source rectangle, then the      */
     176                 : /*      destination rectangle must be the whole region.                 */
     177                 : /* -------------------------------------------------------------------- */
     178              53 :     if( !bModifiedX && !bModifiedY )
     179              52 :         return TRUE;
     180                 : 
     181                 : /* -------------------------------------------------------------------- */
     182                 : /*      Now transform this possibly reduced request back into the       */
     183                 : /*      destination buffer coordinates in case the output region is     */
     184                 : /*      less than the whole buffer.                                     */
     185                 : /* -------------------------------------------------------------------- */
     186                 :     double dfDstULX, dfDstULY, dfDstLRX, dfDstLRY;
     187                 : 
     188                 :     SrcToDst( nModifiedSrcXOff, nModifiedSrcYOff,
     189                 :               nSrcXOff, nSrcYOff,
     190                 :               nSrcXSize, nSrcYSize,
     191                 :               nDstXOff, nDstYOff,
     192                 :               nDstXSize, nDstYSize,
     193               1 :               dfDstULX, dfDstULY );
     194                 :     SrcToDst( nModifiedSrcXOff + nModifiedSrcXSize, nModifiedSrcYOff + nModifiedSrcYSize,
     195                 :               nSrcXOff, nSrcYOff,
     196                 :               nSrcXSize, nSrcYSize,
     197                 :               nDstXOff, nDstYOff,
     198                 :               nDstXSize, nDstYSize,
     199               1 :               dfDstLRX, dfDstLRY );
     200                 : 
     201               1 :     int nModifiedDstXOff = nDstXOff;
     202               1 :     int nModifiedDstYOff = nDstYOff;
     203               1 :     int nModifiedDstXSize = nDstXSize;
     204               1 :     int nModifiedDstYSize = nDstYSize;
     205                 : 
     206               1 :     if( bModifiedX )
     207                 :     {
     208               1 :         nModifiedDstXOff = (int) ((dfDstULX - nDstXOff)+0.001);
     209                 :         nModifiedDstXSize = (int) ((dfDstLRX - nDstXOff)+0.001)
     210               1 :             - nModifiedDstXOff;
     211                 : 
     212               1 :         nModifiedDstXOff = MAX(0,nModifiedDstXOff);
     213               1 :         if( nModifiedDstXOff + nModifiedDstXSize > nDstXSize )
     214               0 :             nModifiedDstXSize = nDstXSize - nModifiedDstXOff;
     215                 :     }
     216                 : 
     217               1 :     if( bModifiedY )
     218                 :     {
     219               1 :         nModifiedDstYOff = (int) ((dfDstULY - nDstYOff)+0.001);
     220                 :         nModifiedDstYSize = (int) ((dfDstLRY - nDstYOff)+0.001)
     221               1 :             - nModifiedDstYOff;
     222                 : 
     223               1 :         nModifiedDstYOff = MAX(0,nModifiedDstYOff);
     224               1 :         if( nModifiedDstYOff + nModifiedDstYSize > nDstYSize )
     225               0 :             nModifiedDstYSize = nDstYSize - nModifiedDstYOff;
     226                 :     }
     227                 : 
     228               1 :     if( nModifiedDstXSize < 1 || nModifiedDstYSize < 1 )
     229               0 :         return FALSE;
     230                 :     else
     231                 :     {
     232               1 :         panDstWin[0] = nModifiedDstXOff;
     233               1 :         panDstWin[1] = nModifiedDstYOff;
     234               1 :         panDstWin[2] = nModifiedDstXSize;
     235               1 :         panDstWin[3] = nModifiedDstYSize;
     236                 : 
     237               1 :         return TRUE;
     238                 :     }
     239                 : }
     240                 : 
     241                 : /************************************************************************/
     242                 : /*                             ProxyMain()                              */
     243                 : /************************************************************************/
     244                 : 
     245                 : enum
     246                 : {
     247                 :     MASK_DISABLED,
     248                 :     MASK_AUTO,
     249                 :     MASK_USER
     250                 : };
     251                 : 
     252             133 : static int ProxyMain( int argc, char ** argv )
     253                 : 
     254                 : {
     255                 :     GDALDatasetH  hDataset, hOutDS;
     256                 :     int     i;
     257                 :     int     nRasterXSize, nRasterYSize;
     258             133 :     const char    *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
     259             133 :     int bFormatExplicitelySet = FALSE;
     260                 :     GDALDriverH   hDriver;
     261             133 :     int     *panBandList = NULL; /* negative value of panBandList[i] means mask band of ABS(panBandList[i]) */
     262             133 :     int         nBandCount = 0, bDefBands = TRUE;
     263                 :     double    adfGeoTransform[6];
     264             133 :     GDALDataType  eOutputType = GDT_Unknown;
     265             133 :     int     nOXSize = 0, nOYSize = 0;
     266             133 :     char    *pszOXSize=NULL, *pszOYSize=NULL;
     267             133 :     char                **papszCreateOptions = NULL;
     268             133 :     int                 anSrcWin[4], bStrict = FALSE;
     269                 :     const char          *pszProjection;
     270             133 :     int                 bScale = FALSE, bHaveScaleSrc = FALSE, bUnscale=FALSE;
     271             133 :     double          dfScaleSrcMin=0.0, dfScaleSrcMax=255.0;
     272             133 :     double              dfScaleDstMin=0.0, dfScaleDstMax=255.0;
     273                 :     double              dfULX, dfULY, dfLRX, dfLRY;
     274             133 :     char                **papszMetadataOptions = NULL;
     275             133 :     char                *pszOutputSRS = NULL;
     276             133 :     int                 bQuiet = FALSE, bGotBounds = FALSE;
     277             133 :     GDALProgressFunc    pfnProgress = GDALTermProgress;
     278             133 :     int                 nGCPCount = 0;
     279             133 :     GDAL_GCP            *pasGCPs = NULL;
     280             133 :     int                 iSrcFileArg = -1, iDstFileArg = -1;
     281             133 :     int                 bCopySubDatasets = FALSE;
     282             133 :     double              adfULLR[4] = { 0,0,0,0 };
     283             133 :     int                 bSetNoData = FALSE;
     284             133 :     int                 bUnsetNoData = FALSE;
     285             133 :     double    dfNoDataReal = 0.0;
     286             133 :     int                 nRGBExpand = 0;
     287             133 :     int                 bParsedMaskArgument = FALSE;
     288             133 :     int                 eMaskMode = MASK_AUTO;
     289             133 :     int                 nMaskBand = 0; /* negative value means mask band of ABS(nMaskBand) */
     290             133 :     int                 bStats = FALSE, bApproxStats = FALSE;
     291             133 :     int                 bErrorOnPartiallyOutside = FALSE;
     292             133 :     int                 bErrorOnCompletelyOutside = FALSE;
     293                 : 
     294                 : 
     295             133 :     anSrcWin[0] = 0;
     296             133 :     anSrcWin[1] = 0;
     297             133 :     anSrcWin[2] = 0;
     298             133 :     anSrcWin[3] = 0;
     299                 : 
     300             133 :     dfULX = dfULY = dfLRX = dfLRY = 0.0;
     301                 :     
     302                 :     /* Check strict compilation and runtime library version as we use C++ API */
     303             133 :     if (! GDAL_CHECK_VERSION(argv[0]))
     304               0 :         exit(1);
     305                 : 
     306                 :     /* Must process GDAL_SKIP before GDALAllRegister(), but we can't call */
     307                 :     /* GDALGeneralCmdLineProcessor before it needs the drivers to be registered */
     308                 :     /* for the --format or --formats options */
     309             783 :     for( i = 1; i < argc; i++ )
     310                 :     {
     311             650 :         if( EQUAL(argv[i],"--config") && i + 2 < argc && EQUAL(argv[i + 1], "GDAL_SKIP") )
     312                 :         {
     313               0 :             CPLSetConfigOption( argv[i+1], argv[i+2] );
     314                 : 
     315               0 :             i += 2;
     316                 :         }
     317                 :     }
     318                 : 
     319                 : /* -------------------------------------------------------------------- */
     320                 : /*      Register standard GDAL drivers, and process generic GDAL        */
     321                 : /*      command options.                                                */
     322                 : /* -------------------------------------------------------------------- */
     323             133 :     GDALAllRegister();
     324             133 :     argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
     325             133 :     if( argc < 1 )
     326               0 :         exit( -argc );
     327                 : 
     328                 : /* -------------------------------------------------------------------- */
     329                 : /*      Handle command line arguments.                                  */
     330                 : /* -------------------------------------------------------------------- */
     331             561 :     for( i = 1; i < argc; i++ )
     332                 :     {
     333             429 :         if( EQUAL(argv[i], "--utility_version") )
     334                 :         {
     335                 :             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
     336               1 :                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
     337               1 :             return 0;
     338                 :         }
     339             507 :         else if( EQUAL(argv[i],"-of") && i < argc-1 )
     340                 :         {
     341              79 :             pszFormat = argv[++i];
     342              79 :             bFormatExplicitelySet = TRUE;
     343                 :         }
     344                 : 
     345             352 :         else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
     346                 :         {
     347               3 :             bQuiet = TRUE;
     348               3 :             pfnProgress = GDALDummyProgress;
     349                 :         }
     350                 : 
     351             370 :         else if( EQUAL(argv[i],"-ot") && i < argc-1 )
     352                 :         {
     353                 :             int iType;
     354                 :             
     355             288 :             for( iType = 1; iType < GDT_TypeCount; iType++ )
     356                 :             {
     357             528 :                 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
     358             264 :                     && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
     359                 :                              argv[i+1]) )
     360                 :                 {
     361              24 :                     eOutputType = (GDALDataType) iType;
     362                 :                 }
     363                 :             }
     364                 : 
     365              24 :             if( eOutputType == GDT_Unknown )
     366                 :             {
     367               0 :                 printf( "Unknown output pixel type: %s\n", argv[i+1] );
     368               0 :                 Usage();
     369               0 :                 GDALDestroyDriverManager();
     370               0 :                 exit( 2 );
     371                 :             }
     372              24 :             i++;
     373                 :         }
     374             338 :         else if( EQUAL(argv[i],"-b") && i < argc-1 )
     375                 :         {
     376              16 :             const char* pszBand = argv[i+1];
     377              16 :             int bMask = FALSE;
     378              16 :             if (EQUAL(pszBand, "mask"))
     379               1 :                 pszBand = "mask,1";
     380              16 :             if (EQUALN(pszBand, "mask,", 5))
     381                 :             {
     382               1 :                 bMask = TRUE;
     383               1 :                 pszBand += 5;
     384                 :                 /* If we use tha source mask band as a regular band */
     385                 :                 /* don't create a target mask band by default */
     386               1 :                 if( !bParsedMaskArgument )
     387               1 :                     eMaskMode = MASK_DISABLED;
     388                 :             }
     389              16 :             int nBand = atoi(pszBand);
     390              16 :             if( nBand < 1 )
     391                 :             {
     392               0 :                 printf( "Unrecognizable band number (%s).\n", argv[i+1] );
     393               0 :                 Usage();
     394               0 :                 GDALDestroyDriverManager();
     395               0 :                 exit( 2 );
     396                 :             }
     397              16 :             i++;
     398                 : 
     399              16 :             nBandCount++;
     400                 :             panBandList = (int *) 
     401              16 :                 CPLRealloc(panBandList, sizeof(int) * nBandCount);
     402              16 :             panBandList[nBandCount-1] = nBand;
     403              16 :             if (bMask)
     404               1 :                 panBandList[nBandCount-1] *= -1;
     405                 : 
     406              16 :             if( panBandList[nBandCount-1] != nBandCount )
     407               3 :                 bDefBands = FALSE;
     408                 :         }
     409             309 :         else if( EQUAL(argv[i],"-mask") && i < argc-1 )
     410                 :         {
     411               3 :             bParsedMaskArgument = TRUE;
     412               3 :             const char* pszBand = argv[i+1];
     413               3 :             if (EQUAL(pszBand, "none"))
     414                 :             {
     415               1 :                 eMaskMode = MASK_DISABLED;
     416                 :             }
     417               2 :             else if (EQUAL(pszBand, "auto"))
     418                 :             {
     419               0 :                 eMaskMode = MASK_AUTO;
     420                 :             }
     421                 :             else
     422                 :             {
     423               2 :                 int bMask = FALSE;
     424               2 :                 if (EQUAL(pszBand, "mask"))
     425               0 :                     pszBand = "mask,1";
     426               2 :                 if (EQUALN(pszBand, "mask,", 5))
     427                 :                 {
     428               1 :                     bMask = TRUE;
     429               1 :                     pszBand += 5;
     430                 :                 }
     431               2 :                 int nBand = atoi(pszBand);
     432               2 :                 if( nBand < 1 )
     433                 :                 {
     434               0 :                     printf( "Unrecognizable band number (%s).\n", argv[i+1] );
     435               0 :                     Usage();
     436               0 :                     GDALDestroyDriverManager();
     437               0 :                     exit( 2 );
     438                 :                 }
     439                 :                 
     440               2 :                 eMaskMode = MASK_USER;
     441               2 :                 nMaskBand = nBand;
     442               2 :                 if (bMask)
     443               1 :                     nMaskBand *= -1;
     444                 :             }
     445               3 :             i ++;
     446                 :         }
     447             303 :         else if( EQUAL(argv[i],"-not_strict")  )
     448               0 :             bStrict = FALSE;
     449                 :             
     450             303 :         else if( EQUAL(argv[i],"-strict")  )
     451               0 :             bStrict = TRUE;
     452                 :             
     453             303 :         else if( EQUAL(argv[i],"-sds")  )
     454               2 :             bCopySubDatasets = TRUE;
     455                 :             
     456             313 :         else if( EQUAL(argv[i],"-gcp") && i < argc - 4 )
     457                 :         {
     458              12 :             char* endptr = NULL;
     459                 :             /* -gcp pixel line easting northing [elev] */
     460                 : 
     461              12 :             nGCPCount++;
     462                 :             pasGCPs = (GDAL_GCP *) 
     463              12 :                 CPLRealloc( pasGCPs, sizeof(GDAL_GCP) * nGCPCount );
     464              12 :             GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 );
     465                 : 
     466              12 :             pasGCPs[nGCPCount-1].dfGCPPixel = CPLAtofM(argv[++i]);
     467              12 :             pasGCPs[nGCPCount-1].dfGCPLine = CPLAtofM(argv[++i]);
     468              12 :             pasGCPs[nGCPCount-1].dfGCPX = CPLAtofM(argv[++i]);
     469              12 :             pasGCPs[nGCPCount-1].dfGCPY = CPLAtofM(argv[++i]);
     470              34 :             if( argv[i+1] != NULL 
     471              22 :                 && (CPLStrtod(argv[i+1], &endptr) != 0.0 || argv[i+1][0] == '0') )
     472                 :             {
     473                 :                 /* Check that last argument is really a number and not a filename */
     474                 :                 /* looking like a number (see ticket #863) */
     475               2 :                 if (endptr && *endptr == 0)
     476               2 :                     pasGCPs[nGCPCount-1].dfGCPZ = CPLAtofM(argv[++i]);
     477                 :             }
     478                 : 
     479                 :             /* should set id and info? */
     480                 :         }   
     481                 : 
     482             292 :         else if( EQUAL(argv[i],"-a_nodata") && i < argc - 1 )
     483                 :         {
     484               3 :             if (EQUAL(argv[i+1], "none"))
     485                 :             {
     486               1 :                 bUnsetNoData = TRUE;
     487                 :             }
     488                 :             else
     489                 :             {
     490               2 :                 bSetNoData = TRUE;
     491               2 :                 dfNoDataReal = CPLAtofM(argv[i+1]);
     492                 :             }
     493               3 :             i += 1;
     494                 :         }   
     495                 : 
     496             287 :         else if( EQUAL(argv[i],"-a_ullr") && i < argc - 4 )
     497                 :         {
     498               1 :             adfULLR[0] = CPLAtofM(argv[i+1]);
     499               1 :             adfULLR[1] = CPLAtofM(argv[i+2]);
     500               1 :             adfULLR[2] = CPLAtofM(argv[i+3]);
     501               1 :             adfULLR[3] = CPLAtofM(argv[i+4]);
     502                 : 
     503               1 :             bGotBounds = TRUE;
     504                 :             
     505               1 :             i += 4;
     506                 :         }   
     507                 : 
     508             287 :         else if( EQUAL(argv[i],"-co") && i < argc-1 )
     509                 :         {
     510               2 :             papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
     511                 :         }   
     512                 : 
     513             283 :         else if( EQUAL(argv[i],"-scale") )
     514                 :         {
     515               1 :             bScale = TRUE;
     516               1 :             if( i < argc-2 && ArgIsNumeric(argv[i+1]) )
     517                 :             {
     518               1 :                 bHaveScaleSrc = TRUE;
     519               1 :                 dfScaleSrcMin = CPLAtofM(argv[i+1]);
     520               1 :                 dfScaleSrcMax = CPLAtofM(argv[i+2]);
     521               1 :                 i += 2;
     522                 :             }
     523               1 :             if( i < argc-2 && bHaveScaleSrc && ArgIsNumeric(argv[i+1]) )
     524                 :             {
     525               1 :                 dfScaleDstMin = CPLAtofM(argv[i+1]);
     526               1 :                 dfScaleDstMax = CPLAtofM(argv[i+2]);
     527               1 :                 i += 2;
     528                 :             }
     529                 :             else
     530                 :             {
     531               0 :                 dfScaleDstMin = 0.0;
     532               0 :                 dfScaleDstMax = 255.999;
     533                 :             }
     534                 :         }   
     535                 : 
     536             282 :         else if( EQUAL(argv[i], "-unscale") )
     537                 :         {
     538               0 :             bUnscale = TRUE;
     539                 :         }
     540                 : 
     541             283 :         else if( EQUAL(argv[i],"-mo") && i < argc-1 )
     542                 :         {
     543                 :             papszMetadataOptions = CSLAddString( papszMetadataOptions,
     544               1 :                                                  argv[++i] );
     545                 :         }
     546                 : 
     547             285 :         else if( EQUAL(argv[i],"-outsize") && i < argc-2 )
     548                 :         {
     549               4 :             pszOXSize = argv[++i];
     550               4 :             pszOYSize = argv[++i];
     551                 :         }   
     552                 : 
     553             281 :         else if( EQUAL(argv[i],"-srcwin") && i < argc-4 )
     554                 :         {
     555               4 :             anSrcWin[0] = atoi(argv[++i]);
     556               4 :             anSrcWin[1] = atoi(argv[++i]);
     557               4 :             anSrcWin[2] = atoi(argv[++i]);
     558               4 :             anSrcWin[3] = atoi(argv[++i]);
     559                 :         }   
     560                 : 
     561             274 :         else if( EQUAL(argv[i],"-projwin") && i < argc-4 )
     562                 :         {
     563               1 :             dfULX = CPLAtofM(argv[++i]);
     564               1 :             dfULY = CPLAtofM(argv[++i]);
     565               1 :             dfLRX = CPLAtofM(argv[++i]);
     566               1 :             dfLRY = CPLAtofM(argv[++i]);
     567                 :         }   
     568                 : 
     569             272 :         else if( EQUAL(argv[i],"-epo") )
     570                 :         {
     571               0 :             bErrorOnPartiallyOutside = TRUE;
     572               0 :             bErrorOnCompletelyOutside = TRUE;
     573                 :         }
     574                 : 
     575             272 :         else  if( EQUAL(argv[i],"-eco") )
     576                 :         {
     577               0 :             bErrorOnCompletelyOutside = TRUE;
     578                 :         }
     579                 :     
     580             274 :         else if( EQUAL(argv[i],"-a_srs") && i < argc-1 )
     581                 :         {
     582               2 :             OGRSpatialReference oOutputSRS;
     583                 : 
     584               2 :             if( oOutputSRS.SetFromUserInput( argv[i+1] ) != OGRERR_NONE )
     585                 :             {
     586                 :                 fprintf( stderr, "Failed to process SRS definition: %s\n", 
     587               0 :                          argv[i+1] );
     588               0 :                 GDALDestroyDriverManager();
     589               0 :                 exit( 1 );
     590                 :             }
     591                 : 
     592               2 :             oOutputSRS.exportToWkt( &pszOutputSRS );
     593               2 :             i++;
     594                 :         }   
     595                 : 
     596             275 :         else if( EQUAL(argv[i],"-expand") && i < argc-1 )
     597                 :         {
     598               5 :             if (EQUAL(argv[i+1], "gray"))
     599               1 :                 nRGBExpand = 1;
     600               4 :             else if (EQUAL(argv[i+1], "rgb"))
     601               2 :                 nRGBExpand = 3;
     602               2 :             else if (EQUAL(argv[i+1], "rgba"))
     603               2 :                 nRGBExpand = 4;
     604                 :             else
     605                 :             {
     606                 :                 printf( "Value %s unsupported. Only gray, rgb or rgba are supported.\n\n", 
     607               0 :                     argv[i] );
     608               0 :                 Usage();
     609               0 :                 GDALDestroyDriverManager();
     610               0 :                 exit( 2 );
     611                 :             }
     612               5 :             i++;
     613                 :         }
     614                 : 
     615             265 :         else if( EQUAL(argv[i], "-stats") )
     616                 :         {
     617               1 :             bStats = TRUE;
     618               1 :             bApproxStats = FALSE;
     619                 :         }
     620             264 :         else if( EQUAL(argv[i], "-approx_stats") )
     621                 :         {
     622               0 :             bStats = TRUE;
     623               0 :             bApproxStats = TRUE;
     624                 :         }
     625                 : 
     626             264 :         else if( argv[i][0] == '-' )
     627                 :         {
     628                 :             printf( "Option %s incomplete, or not recognised.\n\n", 
     629               0 :                     argv[i] );
     630               0 :             Usage();
     631               0 :             GDALDestroyDriverManager();
     632               0 :             exit( 2 );
     633                 :         }
     634             264 :         else if( pszSource == NULL )
     635                 :         {
     636             132 :             iSrcFileArg = i;
     637             132 :             pszSource = argv[i];
     638                 :         }
     639             132 :         else if( pszDest == NULL )
     640                 :         {
     641             132 :             pszDest = argv[i];
     642             132 :             iDstFileArg = i;
     643                 :         }
     644                 : 
     645                 :         else
     646                 :         {
     647               0 :             printf( "Too many command options.\n\n" );
     648               0 :             Usage();
     649               0 :             GDALDestroyDriverManager();
     650               0 :             exit( 2 );
     651                 :         }
     652                 :     }
     653                 : 
     654             132 :     if( pszDest == NULL )
     655                 :     {
     656               0 :         Usage();
     657               0 :         GDALDestroyDriverManager();
     658               0 :         exit( 10 );
     659                 :     }
     660                 : 
     661             132 :     if ( strcmp(pszSource, pszDest) == 0)
     662                 :     {
     663               0 :         fprintf(stderr, "Source and destination datasets must be different.\n");
     664               0 :         GDALDestroyDriverManager();
     665               0 :         exit( 1 );
     666                 :     }
     667                 : 
     668             132 :     if( strcmp(pszDest, "/vsistdout/") == 0)
     669                 :     {
     670               0 :         bQuiet = TRUE;
     671               0 :         pfnProgress = GDALDummyProgress;
     672                 :     }
     673                 : 
     674             132 :     if (!bQuiet && !bFormatExplicitelySet)
     675              51 :         CheckExtensionConsistency(pszDest, pszFormat);
     676                 : 
     677                 : /* -------------------------------------------------------------------- */
     678                 : /*      Attempt to open source file.                                    */
     679                 : /* -------------------------------------------------------------------- */
     680                 : 
     681             132 :     hDataset = GDALOpenShared( pszSource, GA_ReadOnly );
     682                 :     
     683             132 :     if( hDataset == NULL )
     684                 :     {
     685                 :         fprintf( stderr,
     686                 :                  "GDALOpen failed - %d\n%s\n",
     687               0 :                  CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
     688               0 :         GDALDestroyDriverManager();
     689               0 :         exit( 1 );
     690                 :     }
     691                 : 
     692                 : /* -------------------------------------------------------------------- */
     693                 : /*      Handle subdatasets.                                             */
     694                 : /* -------------------------------------------------------------------- */
     695             132 :     if( !bCopySubDatasets 
     696                 :         && CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0 
     697                 :         && GDALGetRasterCount(hDataset) == 0 )
     698                 :     {
     699                 :         fprintf( stderr,
     700               0 :                  "Input file contains subdatasets. Please, select one of them for reading.\n" );
     701               0 :         GDALClose( hDataset );
     702               0 :         GDALDestroyDriverManager();
     703               0 :         exit( 1 );
     704                 :     }
     705                 : 
     706             132 :     if( CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0 
     707                 :         && bCopySubDatasets )
     708                 :     {
     709               1 :         char **papszSubdatasets = GDALGetMetadata(hDataset,"SUBDATASETS");
     710               1 :         char *pszSubDest = (char *) CPLMalloc(strlen(pszDest)+32);
     711                 :         int i;
     712               1 :         int bOldSubCall = bSubCall;
     713               1 :         char** papszDupArgv = CSLDuplicate(argv);
     714               1 :         int nRet = 0;
     715                 : 
     716               1 :         CPLFree(papszDupArgv[iDstFileArg]);
     717               1 :         papszDupArgv[iDstFileArg] = pszSubDest;
     718               1 :         bSubCall = TRUE;
     719               2 :         for( i = 0; papszSubdatasets[i] != NULL; i += 2 )
     720                 :         {
     721               1 :             CPLFree(papszDupArgv[iSrcFileArg]);
     722               1 :             papszDupArgv[iSrcFileArg] = CPLStrdup(strstr(papszSubdatasets[i],"=")+1);
     723               1 :             sprintf( pszSubDest, "%s%d", pszDest, i/2 + 1 );
     724               1 :             nRet = ProxyMain( argc, papszDupArgv );
     725               1 :             if (nRet != 0)
     726               0 :                 break;
     727                 :         }
     728               1 :         CSLDestroy(papszDupArgv);
     729                 :         
     730               1 :         bSubCall = bOldSubCall;
     731               1 :         CSLDestroy(argv);
     732                 : 
     733               1 :         GDALClose( hDataset );
     734                 : 
     735               1 :         if( !bSubCall )
     736                 :         {
     737               1 :             GDALDumpOpenDatasets( stderr );
     738               1 :             GDALDestroyDriverManager();
     739                 :         }
     740               1 :         return nRet;
     741                 :     }
     742                 : 
     743                 : /* -------------------------------------------------------------------- */
     744                 : /*      Collect some information from the source file.                  */
     745                 : /* -------------------------------------------------------------------- */
     746             131 :     nRasterXSize = GDALGetRasterXSize( hDataset );
     747             131 :     nRasterYSize = GDALGetRasterYSize( hDataset );
     748                 : 
     749             131 :     if( !bQuiet )
     750             128 :         printf( "Input file size is %d, %d\n", nRasterXSize, nRasterYSize );
     751                 : 
     752             131 :     if( anSrcWin[2] == 0 && anSrcWin[3] == 0 )
     753                 :     {
     754             127 :         anSrcWin[2] = nRasterXSize;
     755             127 :         anSrcWin[3] = nRasterYSize;
     756                 :     }
     757                 : 
     758                 : /* -------------------------------------------------------------------- */
     759                 : /*  Build band list to translate          */
     760                 : /* -------------------------------------------------------------------- */
     761             131 :     if( nBandCount == 0 )
     762                 :     {
     763             126 :         nBandCount = GDALGetRasterCount( hDataset );
     764             126 :         if( nBandCount == 0 )
     765                 :         {
     766               0 :             fprintf( stderr, "Input file has no bands, and so cannot be translated.\n" );
     767               0 :             GDALDestroyDriverManager();
     768               0 :             exit(1 );
     769                 :         }
     770                 : 
     771             126 :         panBandList = (int *) CPLMalloc(sizeof(int)*nBandCount);
     772             267 :         for( i = 0; i < nBandCount; i++ )
     773             141 :             panBandList[i] = i+1;
     774                 :     }
     775                 :     else
     776                 :     {
     777              21 :         for( i = 0; i < nBandCount; i++ )
     778                 :         {
     779              16 :             if( ABS(panBandList[i]) > GDALGetRasterCount(hDataset) )
     780                 :             {
     781                 :                 fprintf( stderr, 
     782                 :                          "Band %d requested, but only bands 1 to %d available.\n",
     783               0 :                          ABS(panBandList[i]), GDALGetRasterCount(hDataset) );
     784               0 :                 GDALDestroyDriverManager();
     785               0 :                 exit( 2 );
     786                 :             }
     787                 :         }
     788                 : 
     789               5 :         if( nBandCount != GDALGetRasterCount( hDataset ) )
     790               3 :             bDefBands = FALSE;
     791                 :     }
     792                 : 
     793                 : /* -------------------------------------------------------------------- */
     794                 : /*      Compute the source window from the projected source window      */
     795                 : /*      if the projected coordinates were provided.  Note that the      */
     796                 : /*      projected coordinates are in ulx, uly, lrx, lry format,         */
     797                 : /*      while the anSrcWin is xoff, yoff, xsize, ysize with the         */
     798                 : /*      xoff,yoff being the ulx, uly in pixel/line.                     */
     799                 : /* -------------------------------------------------------------------- */
     800             131 :     if( dfULX != 0.0 || dfULY != 0.0 
     801                 :         || dfLRX != 0.0 || dfLRY != 0.0 )
     802                 :     {
     803                 :         double  adfGeoTransform[6];
     804                 : 
     805               1 :         GDALGetGeoTransform( hDataset, adfGeoTransform );
     806                 : 
     807               1 :         if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 )
     808                 :         {
     809                 :             fprintf( stderr, 
     810                 :                      "The -projwin option was used, but the geotransform is\n"
     811               0 :                      "rotated.  This configuration is not supported.\n" );
     812               0 :             GDALClose( hDataset );
     813               0 :             CPLFree( panBandList );
     814               0 :             GDALDestroyDriverManager();
     815               0 :             exit( 1 );
     816                 :         }
     817                 : 
     818                 :         anSrcWin[0] = (int) 
     819               1 :             ((dfULX - adfGeoTransform[0]) / adfGeoTransform[1] + 0.001);
     820                 :         anSrcWin[1] = (int) 
     821               1 :             ((dfULY - adfGeoTransform[3]) / adfGeoTransform[5] + 0.001);
     822                 : 
     823               1 :         anSrcWin[2] = (int) ((dfLRX - dfULX) / adfGeoTransform[1] + 0.5);
     824               1 :         anSrcWin[3] = (int) ((dfLRY - dfULY) / adfGeoTransform[5] + 0.5);
     825                 : 
     826               1 :         if( !bQuiet )
     827                 :             fprintf( stdout, 
     828                 :                      "Computed -srcwin %d %d %d %d from projected window.\n",
     829                 :                      anSrcWin[0], 
     830                 :                      anSrcWin[1], 
     831                 :                      anSrcWin[2], 
     832               1 :                      anSrcWin[3] );
     833                 :     }
     834                 : 
     835                 : /* -------------------------------------------------------------------- */
     836                 : /*      Verify source window dimensions.                                */
     837                 : /* -------------------------------------------------------------------- */
     838             131 :     if( anSrcWin[2] <= 0 || anSrcWin[3] <= 0 )
     839                 :     {
     840                 :         fprintf( stderr,
     841                 :                  "Error: %s-srcwin %d %d %d %d has negative width and/or height.\n",
     842                 :                  ( dfULX != 0.0 || dfULY != 0.0 || dfLRX != 0.0 || dfLRY != 0.0 ) ? "Computed " : "",
     843                 :                  anSrcWin[0],
     844                 :                  anSrcWin[1],
     845                 :                  anSrcWin[2],
     846               0 :                  anSrcWin[3] );
     847               0 :         exit( 1 );
     848                 :     }
     849                 : 
     850                 : /* -------------------------------------------------------------------- */
     851                 : /*      Verify source window dimensions.                                */
     852                 : /* -------------------------------------------------------------------- */
     853             391 :     else if( anSrcWin[0] < 0 || anSrcWin[1] < 0 
     854             130 :         || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hDataset)
     855             130 :         || anSrcWin[1] + anSrcWin[3] > GDALGetRasterYSize(hDataset) )
     856                 :     {
     857               1 :         int bCompletelyOutside = anSrcWin[0] + anSrcWin[2] <= 0 ||
     858               1 :                                     anSrcWin[1] + anSrcWin[3] <= 0 ||
     859               1 :                                     anSrcWin[0] >= GDALGetRasterXSize(hDataset) ||
     860               3 :                                     anSrcWin[1] >= GDALGetRasterYSize(hDataset);
     861               1 :         int bIsError = bErrorOnPartiallyOutside || (bCompletelyOutside && bErrorOnCompletelyOutside);
     862               1 :         if( !bQuiet || bIsError )
     863                 :         {
     864                 :             fprintf( stderr,
     865                 :                  "%s: %s-srcwin %d %d %d %d falls %s outside raster extent.%s\n",
     866                 :                  (bIsError) ? "Error" : "Warning",
     867                 :                  ( dfULX != 0.0 || dfULY != 0.0 || dfLRX != 0.0 || dfLRY != 0.0 ) ? "Computed " : "",
     868                 :                  anSrcWin[0],
     869                 :                  anSrcWin[1],
     870                 :                  anSrcWin[2],
     871                 :                  anSrcWin[3],
     872                 :                  (bCompletelyOutside) ? "completely" : "partially",
     873               0 :                  (bIsError) ? "" : " Going on however." );
     874                 :         }
     875               1 :         if( bIsError )
     876               0 :             exit(1);
     877                 :     }
     878                 : 
     879                 : /* -------------------------------------------------------------------- */
     880                 : /*      Find the output driver.                                         */
     881                 : /* -------------------------------------------------------------------- */
     882             131 :     hDriver = GDALGetDriverByName( pszFormat );
     883             131 :     if( hDriver == NULL )
     884                 :     {
     885                 :         int iDr;
     886                 :         
     887               0 :         printf( "Output driver `%s' not recognised.\n", pszFormat );
     888               0 :         printf( "The following format drivers are configured and support output:\n" );
     889               0 :         for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
     890                 :         {
     891               0 :             GDALDriverH hDriver = GDALGetDriver(iDr);
     892                 : 
     893               0 :             if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
     894                 :                 || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY,
     895                 :                                         NULL ) != NULL )
     896                 :             {
     897                 :                 printf( "  %s: %s\n",
     898                 :                         GDALGetDriverShortName( hDriver  ),
     899               0 :                         GDALGetDriverLongName( hDriver ) );
     900                 :             }
     901                 :         }
     902               0 :         printf( "\n" );
     903               0 :         Usage();
     904                 :         
     905               0 :         GDALClose( hDataset );
     906               0 :         CPLFree( panBandList );
     907               0 :         GDALDestroyDriverManager();
     908               0 :         CSLDestroy( argv );
     909               0 :         CSLDestroy( papszCreateOptions );
     910               0 :         exit( 1 );
     911                 :     }
     912                 : 
     913                 : /* -------------------------------------------------------------------- */
     914                 : /*      The short form is to CreateCopy().  We use this if the input    */
     915                 : /*      matches the whole dataset.  Eventually we should rewrite        */
     916                 : /*      this entire program to use virtual datasets to construct a      */
     917                 : /*      virtual input source to copy from.                              */
     918                 : /* -------------------------------------------------------------------- */
     919                 : 
     920                 : 
     921                 :     int bSpatialArrangementPreserved = (
     922             260 :            anSrcWin[0] == 0 && anSrcWin[1] == 0
     923             129 :         && anSrcWin[2] == GDALGetRasterXSize(hDataset)
     924             127 :         && anSrcWin[3] == GDALGetRasterYSize(hDataset)
     925             516 :         && pszOXSize == NULL && pszOYSize == NULL );
     926                 : 
     927             131 :     if( eOutputType == GDT_Unknown 
     928                 :         && !bScale && !bUnscale
     929                 :         && CSLCount(papszMetadataOptions) == 0 && bDefBands 
     930                 :         && eMaskMode == MASK_AUTO
     931                 :         && bSpatialArrangementPreserved
     932                 :         && nGCPCount == 0 && !bGotBounds
     933                 :         && pszOutputSRS == NULL && !bSetNoData && !bUnsetNoData
     934                 :         && nRGBExpand == 0 && !bStats )
     935                 :     {
     936                 :         
     937                 :         hOutDS = GDALCreateCopy( hDriver, pszDest, hDataset, 
     938                 :                                  bStrict, papszCreateOptions, 
     939              78 :                                  pfnProgress, NULL );
     940                 : 
     941              78 :         if( hOutDS != NULL )
     942              12 :             GDALClose( hOutDS );
     943                 :         
     944              78 :         GDALClose( hDataset );
     945                 : 
     946              78 :         CPLFree( panBandList );
     947                 : 
     948              78 :         if( !bSubCall )
     949                 :         {
     950              77 :             GDALDumpOpenDatasets( stderr );
     951              77 :             GDALDestroyDriverManager();
     952                 :         }
     953                 : 
     954              78 :         CSLDestroy( argv );
     955              78 :         CSLDestroy( papszCreateOptions );
     956                 : 
     957              78 :         return hOutDS == NULL;
     958                 :     }
     959                 : 
     960                 : /* -------------------------------------------------------------------- */
     961                 : /*      Establish some parameters.                                      */
     962                 : /* -------------------------------------------------------------------- */
     963              53 :     if( pszOXSize == NULL )
     964                 :     {
     965              49 :         nOXSize = anSrcWin[2];
     966              49 :         nOYSize = anSrcWin[3];
     967                 :     }
     968                 :     else
     969                 :     {
     970               4 :         nOXSize = (int) ((pszOXSize[strlen(pszOXSize)-1]=='%' 
     971               8 :                           ? CPLAtofM(pszOXSize)/100*anSrcWin[2] : atoi(pszOXSize)));
     972               4 :         nOYSize = (int) ((pszOYSize[strlen(pszOYSize)-1]=='%' 
     973               8 :                           ? CPLAtofM(pszOYSize)/100*anSrcWin[3] : atoi(pszOYSize)));
     974                 :     }
     975                 : 
     976                 : /* ==================================================================== */
     977                 : /*      Create a virtual dataset.                                       */
     978                 : /* ==================================================================== */
     979                 :     VRTDataset *poVDS;
     980                 :         
     981                 : /* -------------------------------------------------------------------- */
     982                 : /*      Make a virtual clone.                                           */
     983                 : /* -------------------------------------------------------------------- */
     984              53 :     poVDS = (VRTDataset *) VRTCreate( nOXSize, nOYSize );
     985                 : 
     986              53 :     if( nGCPCount == 0 )
     987                 :     {
     988              50 :         if( pszOutputSRS != NULL )
     989                 :         {
     990               0 :             poVDS->SetProjection( pszOutputSRS );
     991                 :         }
     992                 :         else
     993                 :         {
     994              50 :             pszProjection = GDALGetProjectionRef( hDataset );
     995              50 :             if( pszProjection != NULL && strlen(pszProjection) > 0 )
     996              44 :                 poVDS->SetProjection( pszProjection );
     997                 :         }
     998                 :     }
     999                 : 
    1000              53 :     if( bGotBounds )
    1001                 :     {
    1002               1 :         adfGeoTransform[0] = adfULLR[0];
    1003               1 :         adfGeoTransform[1] = (adfULLR[2] - adfULLR[0]) / nOXSize;
    1004               1 :         adfGeoTransform[2] = 0.0;
    1005               1 :         adfGeoTransform[3] = adfULLR[1];
    1006               1 :         adfGeoTransform[4] = 0.0;
    1007               1 :         adfGeoTransform[5] = (adfULLR[3] - adfULLR[1]) / nOYSize;
    1008                 : 
    1009               1 :         poVDS->SetGeoTransform( adfGeoTransform );
    1010                 :     }
    1011                 : 
    1012              52 :     else if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None 
    1013                 :         && nGCPCount == 0 )
    1014                 :     {
    1015              88 :         adfGeoTransform[0] += anSrcWin[0] * adfGeoTransform[1]
    1016             132 :             + anSrcWin[1] * adfGeoTransform[2];
    1017              88 :         adfGeoTransform[3] += anSrcWin[0] * adfGeoTransform[4]
    1018             132 :             + anSrcWin[1] * adfGeoTransform[5];
    1019                 :         
    1020              44 :         adfGeoTransform[1] *= anSrcWin[2] / (double) nOXSize;
    1021              44 :         adfGeoTransform[2] *= anSrcWin[3] / (double) nOYSize;
    1022              44 :         adfGeoTransform[4] *= anSrcWin[2] / (double) nOXSize;
    1023              44 :         adfGeoTransform[5] *= anSrcWin[3] / (double) nOYSize;
    1024                 :         
    1025              44 :         poVDS->SetGeoTransform( adfGeoTransform );
    1026                 :     }
    1027                 : 
    1028              53 :     if( nGCPCount != 0 )
    1029                 :     {
    1030               3 :         const char *pszGCPProjection = pszOutputSRS;
    1031                 : 
    1032               3 :         if( pszGCPProjection == NULL )
    1033               1 :             pszGCPProjection = GDALGetGCPProjection( hDataset );
    1034               3 :         if( pszGCPProjection == NULL )
    1035               0 :             pszGCPProjection = "";
    1036                 : 
    1037               3 :         poVDS->SetGCPs( nGCPCount, pasGCPs, pszGCPProjection );
    1038                 : 
    1039               3 :         GDALDeinitGCPs( nGCPCount, pasGCPs );
    1040               3 :         CPLFree( pasGCPs );
    1041                 :     }
    1042                 : 
    1043              50 :     else if( GDALGetGCPCount( hDataset ) > 0 )
    1044                 :     {
    1045                 :         GDAL_GCP *pasGCPs;
    1046               0 :         int       nGCPs = GDALGetGCPCount( hDataset );
    1047                 : 
    1048               0 :         pasGCPs = GDALDuplicateGCPs( nGCPs, GDALGetGCPs( hDataset ) );
    1049                 : 
    1050               0 :         for( i = 0; i < nGCPs; i++ )
    1051                 :         {
    1052               0 :             pasGCPs[i].dfGCPPixel -= anSrcWin[0];
    1053               0 :             pasGCPs[i].dfGCPLine  -= anSrcWin[1];
    1054               0 :             pasGCPs[i].dfGCPPixel *= (nOXSize / (double) anSrcWin[2] );
    1055               0 :             pasGCPs[i].dfGCPLine  *= (nOYSize / (double) anSrcWin[3] );
    1056                 :         }
    1057                 :             
    1058                 :         poVDS->SetGCPs( nGCPs, pasGCPs,
    1059               0 :                         GDALGetGCPProjection( hDataset ) );
    1060                 : 
    1061               0 :         GDALDeinitGCPs( nGCPs, pasGCPs );
    1062               0 :         CPLFree( pasGCPs );
    1063                 :     }
    1064                 : 
    1065                 : /* -------------------------------------------------------------------- */
    1066                 : /*      To make the VRT to look less awkward (but this is optional      */
    1067                 : /*      in fact), avoid negative values.                                */
    1068                 : /* -------------------------------------------------------------------- */
    1069                 :     int anDstWin[4];
    1070              53 :     anDstWin[0] = 0;
    1071              53 :     anDstWin[1] = 0;
    1072              53 :     anDstWin[2] = nOXSize;
    1073              53 :     anDstWin[3] = nOYSize;
    1074                 : 
    1075                 :     FixSrcDstWindow( anSrcWin, anDstWin,
    1076                 :                      GDALGetRasterXSize(hDataset),
    1077              53 :                      GDALGetRasterYSize(hDataset) );
    1078                 : 
    1079                 : /* -------------------------------------------------------------------- */
    1080                 : /*      Transfer generally applicable metadata.                         */
    1081                 : /* -------------------------------------------------------------------- */
    1082              53 :     char** papszMetadata = CSLDuplicate(((GDALDataset*)hDataset)->GetMetadata());
    1083              53 :     if ( bScale || bUnscale || eOutputType != GDT_Unknown )
    1084                 :     {
    1085                 :         /* Remove TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE */
    1086                 :         /* if the data range may change because of options */
    1087              25 :         char** papszIter = papszMetadata;
    1088              97 :         while(papszIter && *papszIter)
    1089                 :         {
    1090              47 :             if (EQUALN(*papszIter, "TIFFTAG_MINSAMPLEVALUE=", 23) ||
    1091                 :                 EQUALN(*papszIter, "TIFFTAG_MAXSAMPLEVALUE=", 23))
    1092                 :             {
    1093               0 :                 CPLFree(*papszIter);
    1094               0 :                 memmove(papszIter, papszIter+1, sizeof(char*) * (CSLCount(papszIter+1)+1));
    1095                 :             }
    1096                 :             else
    1097              47 :                 papszIter++;
    1098                 :         }
    1099                 :     }
    1100              53 :     poVDS->SetMetadata( papszMetadata );
    1101              53 :     CSLDestroy( papszMetadata );
    1102              53 :     AttachMetadata( (GDALDatasetH) poVDS, papszMetadataOptions );
    1103                 : 
    1104              53 :     const char* pszInterleave = GDALGetMetadataItem(hDataset, "INTERLEAVE", "IMAGE_STRUCTURE");
    1105              53 :     if (pszInterleave)
    1106              48 :         poVDS->SetMetadataItem("INTERLEAVE", pszInterleave, "IMAGE_STRUCTURE");
    1107                 : 
    1108                 : /* -------------------------------------------------------------------- */
    1109                 : /*      Transfer metadata that remains valid if the spatial             */
    1110                 : /*      arrangement of the data is unaltered.                           */
    1111                 : /* -------------------------------------------------------------------- */
    1112              53 :     if( bSpatialArrangementPreserved )
    1113                 :     {
    1114                 :         char **papszMD;
    1115                 : 
    1116              45 :         papszMD = ((GDALDataset*)hDataset)->GetMetadata("RPC");
    1117              45 :         if( papszMD != NULL )
    1118               0 :             poVDS->SetMetadata( papszMD, "RPC" );
    1119                 : 
    1120              45 :         papszMD = ((GDALDataset*)hDataset)->GetMetadata("GEOLOCATION");
    1121              45 :         if( papszMD != NULL )
    1122               0 :             poVDS->SetMetadata( papszMD, "GEOLOCATION" );
    1123                 :     }
    1124                 : 
    1125              53 :     int nSrcBandCount = nBandCount;
    1126                 : 
    1127              53 :     if (nRGBExpand != 0)
    1128                 :     {
    1129                 :         GDALRasterBand  *poSrcBand;
    1130                 :         poSrcBand = ((GDALDataset *) 
    1131               5 :                      hDataset)->GetRasterBand(ABS(panBandList[0]));
    1132               5 :         if (panBandList[0] < 0)
    1133               0 :             poSrcBand = poSrcBand->GetMaskBand();
    1134               5 :         GDALColorTable* poColorTable = poSrcBand->GetColorTable();
    1135               5 :         if (poColorTable == NULL)
    1136                 :         {
    1137               0 :             fprintf(stderr, "Error : band %d has no color table\n", ABS(panBandList[0]));
    1138               0 :             GDALClose( hDataset );
    1139               0 :             CPLFree( panBandList );
    1140               0 :             GDALDestroyDriverManager();
    1141               0 :             CSLDestroy( argv );
    1142               0 :             CSLDestroy( papszCreateOptions );
    1143               0 :             exit( 1 );
    1144                 :         }
    1145                 :         
    1146                 :         /* Check that the color table only contains gray levels */
    1147                 :         /* when using -expand gray */
    1148               5 :         if (nRGBExpand == 1)
    1149                 :         {
    1150               1 :             int nColorCount = poColorTable->GetColorEntryCount();
    1151                 :             int nColor;
    1152               3 :             for( nColor = 0; nColor < nColorCount; nColor++ )
    1153                 :             {
    1154               2 :                 const GDALColorEntry* poEntry = poColorTable->GetColorEntry(nColor);
    1155               2 :                 if (poEntry->c1 != poEntry->c2 || poEntry->c1 != poEntry->c2)
    1156                 :                 {
    1157               0 :                     fprintf(stderr, "Warning : color table contains non gray levels colors\n");
    1158               0 :                     break;
    1159                 :                 }
    1160                 :             }
    1161                 :         }
    1162                 : 
    1163               5 :         if (nBandCount == 1)
    1164               4 :             nBandCount = nRGBExpand;
    1165               2 :         else if (nBandCount == 2 && (nRGBExpand == 3 || nRGBExpand == 4))
    1166               1 :             nBandCount = nRGBExpand;
    1167                 :         else
    1168                 :         {
    1169               0 :             fprintf(stderr, "Error : invalid use of -expand option.\n");
    1170               0 :             exit( 1 );
    1171                 :         }
    1172                 :     }
    1173                 : 
    1174                 :     int bFilterOutStatsMetadata =
    1175              53 :         (bScale || bUnscale || !bSpatialArrangementPreserved || nRGBExpand != 0);
    1176                 : 
    1177                 : /* ==================================================================== */
    1178                 : /*      Process all bands.                                              */
    1179                 : /* ==================================================================== */
    1180             133 :     for( i = 0; i < nBandCount; i++ )
    1181                 :     {
    1182                 :         VRTSourcedRasterBand   *poVRTBand;
    1183                 :         GDALRasterBand  *poSrcBand;
    1184                 :         GDALDataType    eBandType;
    1185              80 :         int             nComponent = 0;
    1186                 : 
    1187                 :         int nSrcBand;
    1188              80 :         if (nRGBExpand != 0)
    1189                 :         {
    1190              16 :             if (nSrcBandCount == 2 && nRGBExpand == 4 && i == 3)
    1191               1 :                 nSrcBand = panBandList[1];
    1192                 :             else
    1193                 :             {
    1194              14 :                 nSrcBand = panBandList[0];
    1195              14 :                 nComponent = i + 1;
    1196                 :             }
    1197                 :         }
    1198                 :         else
    1199              65 :             nSrcBand = panBandList[i];
    1200                 : 
    1201              80 :         poSrcBand = ((GDALDataset *) hDataset)->GetRasterBand(ABS(nSrcBand));
    1202                 : 
    1203                 : /* -------------------------------------------------------------------- */
    1204                 : /*      Select output data type to match source.                        */
    1205                 : /* -------------------------------------------------------------------- */
    1206              80 :         if( eOutputType == GDT_Unknown )
    1207              56 :             eBandType = poSrcBand->GetRasterDataType();
    1208                 :         else
    1209              24 :             eBandType = eOutputType;
    1210                 : 
    1211                 : /* -------------------------------------------------------------------- */
    1212                 : /*      Create this band.                                               */
    1213                 : /* -------------------------------------------------------------------- */
    1214              80 :         poVDS->AddBand( eBandType, NULL );
    1215              80 :         poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand( i+1 );
    1216              80 :         if (nSrcBand < 0)
    1217                 :         {
    1218               1 :             poVRTBand->AddMaskBandSource(poSrcBand);
    1219               1 :             continue;
    1220                 :         }
    1221                 : 
    1222                 : /* -------------------------------------------------------------------- */
    1223                 : /*      Do we need to collect scaling information?                      */
    1224                 : /* -------------------------------------------------------------------- */
    1225              79 :         double dfScale=1.0, dfOffset=0.0;
    1226                 : 
    1227              79 :         if( bScale && !bHaveScaleSrc )
    1228                 :         {
    1229                 :             double  adfCMinMax[2];
    1230               0 :             GDALComputeRasterMinMax( poSrcBand, TRUE, adfCMinMax );
    1231               0 :             dfScaleSrcMin = adfCMinMax[0];
    1232               0 :             dfScaleSrcMax = adfCMinMax[1];
    1233                 :         }
    1234                 : 
    1235              79 :         if( bScale )
    1236                 :         {
    1237               1 :             if( dfScaleSrcMax == dfScaleSrcMin )
    1238               0 :                 dfScaleSrcMax += 0.1;
    1239               1 :             if( dfScaleDstMax == dfScaleDstMin )
    1240               0 :                 dfScaleDstMax += 0.1;
    1241                 : 
    1242                 :             dfScale = (dfScaleDstMax - dfScaleDstMin) 
    1243               1 :                 / (dfScaleSrcMax - dfScaleSrcMin);
    1244               1 :             dfOffset = -1 * dfScaleSrcMin * dfScale + dfScaleDstMin;
    1245                 :         }
    1246                 : 
    1247              79 :         if( bUnscale )
    1248                 :         {
    1249               0 :             dfScale = poSrcBand->GetScale();
    1250               0 :             dfOffset = poSrcBand->GetOffset();
    1251                 :         }
    1252                 : 
    1253                 : /* -------------------------------------------------------------------- */
    1254                 : /*      Create a simple or complex data source depending on the         */
    1255                 : /*      translation type required.                                      */
    1256                 : /* -------------------------------------------------------------------- */
    1257              95 :         if( bUnscale || bScale || (nRGBExpand != 0 && i < nRGBExpand) )
    1258                 :         {
    1259                 :             poVRTBand->AddComplexSource( poSrcBand,
    1260                 :                                          anSrcWin[0], anSrcWin[1],
    1261                 :                                          anSrcWin[2], anSrcWin[3],
    1262                 :                                          anDstWin[0], anDstWin[1],
    1263                 :                                          anDstWin[2], anDstWin[3],
    1264                 :                                          dfOffset, dfScale,
    1265                 :                                          VRT_NODATA_UNSET,
    1266              16 :                                          nComponent );
    1267                 :         }
    1268                 :         else
    1269                 :             poVRTBand->AddSimpleSource( poSrcBand,
    1270                 :                                         anSrcWin[0], anSrcWin[1],
    1271                 :                                         anSrcWin[2], anSrcWin[3],
    1272                 :                                         anDstWin[0], anDstWin[1],
    1273              63 :                                         anDstWin[2], anDstWin[3] );
    1274                 : 
    1275                 : /* -------------------------------------------------------------------- */
    1276                 : /*      In case of color table translate, we only set the color         */
    1277                 : /*      interpretation other info copied by CopyBandInfo are            */
    1278                 : /*      not relevant in RGB expansion.                                  */
    1279                 : /* -------------------------------------------------------------------- */
    1280              79 :         if (nRGBExpand == 1)
    1281                 :         {
    1282               1 :             poVRTBand->SetColorInterpretation( GCI_GrayIndex );
    1283                 :         }
    1284              92 :         else if (nRGBExpand != 0 && i < nRGBExpand)
    1285                 :         {
    1286              14 :             poVRTBand->SetColorInterpretation( (GDALColorInterp) (GCI_RedBand + i) );
    1287                 :         }
    1288                 : 
    1289                 : /* -------------------------------------------------------------------- */
    1290                 : /*      copy over some other information of interest.                   */
    1291                 : /* -------------------------------------------------------------------- */
    1292                 :         else
    1293                 :         {
    1294                 :             CopyBandInfo( poSrcBand, poVRTBand,
    1295                 :                           !bStats && !bFilterOutStatsMetadata,
    1296                 :                           !bUnscale,
    1297              64 :                           !bSetNoData && !bUnsetNoData );
    1298                 :         }
    1299                 : 
    1300                 : /* -------------------------------------------------------------------- */
    1301                 : /*      Set a forcable nodata value?                                    */
    1302                 : /* -------------------------------------------------------------------- */
    1303              79 :         if( bSetNoData )
    1304                 :         {
    1305               2 :             double dfVal = dfNoDataReal;
    1306               2 :             int bClamped = FALSE, bRounded = FALSE;
    1307                 : 
    1308                 : #define CLAMP(val,type,minval,maxval) \
    1309                 :     do { if (val < minval) { bClamped = TRUE; val = minval; } \
    1310                 :     else if (val > maxval) { bClamped = TRUE; val = maxval; } \
    1311                 :     else if (val != (type)val) { bRounded = TRUE; val = (type)(val + 0.5); } } \
    1312                 :     while(0)
    1313                 : 
    1314               2 :             switch(eBandType)
    1315                 :             {
    1316                 :                 case GDT_Byte:
    1317               2 :                     CLAMP(dfVal, GByte, 0.0, 255.0);
    1318               2 :                     break;
    1319                 :                 case GDT_Int16:
    1320               0 :                     CLAMP(dfVal, GInt16, -32768.0, 32767.0);
    1321               0 :                     break;
    1322                 :                 case GDT_UInt16:
    1323               0 :                     CLAMP(dfVal, GUInt16, 0.0, 65535.0);
    1324               0 :                     break;
    1325                 :                 case GDT_Int32:
    1326               0 :                     CLAMP(dfVal, GInt32, -2147483648.0, 2147483647.0);
    1327               0 :                     break;
    1328                 :                 case GDT_UInt32:
    1329               0 :                     CLAMP(dfVal, GUInt32, 0.0, 4294967295.0);
    1330                 :                     break;
    1331                 :                 default:
    1332                 :                     break;
    1333                 :             }
    1334                 :                 
    1335               2 :             if (bClamped)
    1336                 :             {
    1337                 :                 printf( "for band %d, nodata value has been clamped "
    1338                 :                        "to %.0f, the original value being out of range.\n",
    1339               0 :                        i + 1, dfVal);
    1340                 :             }
    1341               2 :             else if(bRounded)
    1342                 :             {
    1343                 :                 printf("for band %d, nodata value has been rounded "
    1344                 :                        "to %.0f, %s being an integer datatype.\n",
    1345                 :                        i + 1, dfVal,
    1346               0 :                        GDALGetDataTypeName(eBandType));
    1347                 :             }
    1348                 :             
    1349               2 :             poVRTBand->SetNoDataValue( dfVal );
    1350                 :         }
    1351                 : 
    1352             140 :         if (eMaskMode == MASK_AUTO &&
    1353                 :             (GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) & GMF_PER_DATASET) == 0 &&
    1354              61 :             (poSrcBand->GetMaskFlags() & (GMF_ALL_VALID | GMF_NODATA)) == 0)
    1355                 :         {
    1356               0 :             if (poVRTBand->CreateMaskBand(poSrcBand->GetMaskFlags()) == CE_None)
    1357                 :             {
    1358                 :                 VRTSourcedRasterBand* hMaskVRTBand =
    1359               0 :                     (VRTSourcedRasterBand*)poVRTBand->GetMaskBand();
    1360                 :                 hMaskVRTBand->AddMaskBandSource(poSrcBand,
    1361                 :                                         anSrcWin[0], anSrcWin[1],
    1362                 :                                         anSrcWin[2], anSrcWin[3],
    1363                 :                                         anDstWin[0], anDstWin[1],
    1364               0 :                                         anDstWin[2], anDstWin[3] );
    1365                 :             }
    1366                 :         }
    1367                 :     }
    1368                 : 
    1369              53 :     if (eMaskMode == MASK_USER)
    1370                 :     {
    1371                 :         GDALRasterBand *poSrcBand =
    1372               2 :             (GDALRasterBand*)GDALGetRasterBand(hDataset, ABS(nMaskBand));
    1373               2 :         if (poSrcBand && poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
    1374                 :         {
    1375                 :             VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
    1376               2 :                 GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
    1377               2 :             if (nMaskBand > 0)
    1378                 :                 hMaskVRTBand->AddSimpleSource(poSrcBand,
    1379                 :                                         anSrcWin[0], anSrcWin[1],
    1380                 :                                         anSrcWin[2], anSrcWin[3],
    1381                 :                                         anDstWin[0], anDstWin[1],
    1382               1 :                                         anDstWin[2], anDstWin[3] );
    1383                 :             else
    1384                 :                 hMaskVRTBand->AddMaskBandSource(poSrcBand,
    1385                 :                                         anSrcWin[0], anSrcWin[1],
    1386                 :                                         anSrcWin[2], anSrcWin[3],
    1387                 :                                         anDstWin[0], anDstWin[1],
    1388               1 :                                         anDstWin[2], anDstWin[3] );
    1389                 :         }
    1390                 :     }
    1391                 :     else
    1392              51 :     if (eMaskMode == MASK_AUTO && nSrcBandCount > 0 &&
    1393                 :         GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) == GMF_PER_DATASET)
    1394                 :     {
    1395               1 :         if (poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
    1396                 :         {
    1397                 :             VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
    1398               1 :                 GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
    1399                 :             hMaskVRTBand->AddMaskBandSource((GDALRasterBand*)GDALGetRasterBand(hDataset, 1),
    1400                 :                                         anSrcWin[0], anSrcWin[1],
    1401                 :                                         anSrcWin[2], anSrcWin[3],
    1402                 :                                         anDstWin[0], anDstWin[1],
    1403               1 :                                         anDstWin[2], anDstWin[3] );
    1404                 :         }
    1405                 :     }
    1406                 : 
    1407                 : /* -------------------------------------------------------------------- */
    1408                 : /*      Compute stats if required.                                      */
    1409                 : /* -------------------------------------------------------------------- */
    1410              53 :     if (bStats)
    1411                 :     {
    1412               2 :         for( i = 0; i < poVDS->GetRasterCount(); i++ )
    1413                 :         {
    1414                 :             double dfMin, dfMax, dfMean, dfStdDev;
    1415                 :             poVDS->GetRasterBand(i+1)->ComputeStatistics( bApproxStats,
    1416               1 :                     &dfMin, &dfMax, &dfMean, &dfStdDev, GDALDummyProgress, NULL );
    1417                 :         }
    1418                 :     }
    1419                 : 
    1420                 : /* -------------------------------------------------------------------- */
    1421                 : /*      Write to the output file using CopyCreate().                    */
    1422                 : /* -------------------------------------------------------------------- */
    1423                 :     hOutDS = GDALCreateCopy( hDriver, pszDest, (GDALDatasetH) poVDS,
    1424                 :                              bStrict, papszCreateOptions, 
    1425              53 :                              pfnProgress, NULL );
    1426              53 :     if( hOutDS != NULL )
    1427                 :     {
    1428              53 :         int bHasGotErr = FALSE;
    1429              53 :         CPLErrorReset();
    1430              53 :         GDALFlushCache( hOutDS );
    1431              53 :         if (CPLGetLastErrorType() != CE_None)
    1432               0 :             bHasGotErr = TRUE;
    1433              53 :         GDALClose( hOutDS );
    1434              53 :         if (bHasGotErr)
    1435               0 :             hOutDS = NULL;
    1436                 :     }
    1437                 :     
    1438              53 :     GDALClose( (GDALDatasetH) poVDS );
    1439                 :         
    1440              53 :     GDALClose( hDataset );
    1441                 : 
    1442              53 :     CPLFree( panBandList );
    1443                 :     
    1444              53 :     CPLFree( pszOutputSRS );
    1445                 : 
    1446              53 :     if( !bSubCall )
    1447                 :     {
    1448              53 :         GDALDumpOpenDatasets( stderr );
    1449              53 :         GDALDestroyDriverManager();
    1450                 :     }
    1451                 : 
    1452              53 :     CSLDestroy( argv );
    1453              53 :     CSLDestroy( papszCreateOptions );
    1454                 :     
    1455              53 :     return hOutDS == NULL;
    1456                 : }
    1457                 : 
    1458                 : 
    1459                 : /************************************************************************/
    1460                 : /*                            ArgIsNumeric()                            */
    1461                 : /************************************************************************/
    1462                 : 
    1463               2 : int ArgIsNumeric( const char *pszArg )
    1464                 : 
    1465                 : {
    1466               2 :     return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
    1467                 : }
    1468                 : 
    1469                 : /************************************************************************/
    1470                 : /*                           AttachMetadata()                           */
    1471                 : /************************************************************************/
    1472                 : 
    1473              53 : static void AttachMetadata( GDALDatasetH hDS, char **papszMetadataOptions )
    1474                 : 
    1475                 : {
    1476              53 :     int nCount = CSLCount(papszMetadataOptions);
    1477                 :     int i;
    1478                 : 
    1479              54 :     for( i = 0; i < nCount; i++ )
    1480                 :     {
    1481               1 :         char    *pszKey = NULL;
    1482                 :         const char *pszValue;
    1483                 :         
    1484               1 :         pszValue = CPLParseNameValue( papszMetadataOptions[i], &pszKey );
    1485               1 :         GDALSetMetadataItem(hDS,pszKey,pszValue,NULL);
    1486               1 :         CPLFree( pszKey );
    1487                 :     }
    1488                 : 
    1489              53 :     CSLDestroy( papszMetadataOptions );
    1490              53 : }
    1491                 : 
    1492                 : /************************************************************************/
    1493                 : /*                           CopyBandInfo()                            */
    1494                 : /************************************************************************/
    1495                 : 
    1496                 : /* A bit of a clone of VRTRasterBand::CopyCommonInfoFrom(), but we need */
    1497                 : /* more and more custom behaviour in the context of gdal_translate ... */
    1498                 : 
    1499              64 : static void CopyBandInfo( GDALRasterBand * poSrcBand, GDALRasterBand * poDstBand,
    1500                 :                           int bCanCopyStatsMetadata, int bCopyScale, int bCopyNoData )
    1501                 : 
    1502                 : {
    1503                 :     int bSuccess;
    1504                 :     double dfNoData;
    1505                 : 
    1506              64 :     if (bCanCopyStatsMetadata)
    1507                 :     {
    1508              50 :         poDstBand->SetMetadata( poSrcBand->GetMetadata() );
    1509                 :     }
    1510                 :     else
    1511                 :     {
    1512              14 :         char** papszMetadata = poSrcBand->GetMetadata();
    1513              14 :         char** papszMetadataNew = NULL;
    1514              32 :         for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
    1515                 :         {
    1516              18 :             if (strncmp(papszMetadata[i], "STATISTICS_", 11) != 0)
    1517               1 :                 papszMetadataNew = CSLAddString(papszMetadataNew, papszMetadata[i]);
    1518                 :         }
    1519              14 :         poDstBand->SetMetadata( papszMetadataNew );
    1520              14 :         CSLDestroy(papszMetadataNew);
    1521                 :     }
    1522                 : 
    1523              64 :     poDstBand->SetColorTable( poSrcBand->GetColorTable() );
    1524              64 :     poDstBand->SetColorInterpretation(poSrcBand->GetColorInterpretation());
    1525              64 :     if( strlen(poSrcBand->GetDescription()) > 0 )
    1526               1 :         poDstBand->SetDescription( poSrcBand->GetDescription() );
    1527                 : 
    1528              64 :     if (bCopyNoData)
    1529                 :     {
    1530              61 :         dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
    1531              61 :         if( bSuccess )
    1532               1 :             poDstBand->SetNoDataValue( dfNoData );
    1533                 :     }
    1534                 : 
    1535              64 :     if (bCopyScale)
    1536                 :     {
    1537              64 :         poDstBand->SetOffset( poSrcBand->GetOffset() );
    1538              64 :         poDstBand->SetScale( poSrcBand->GetScale() );
    1539                 :     }
    1540                 : 
    1541              64 :     poDstBand->SetCategoryNames( poSrcBand->GetCategoryNames() );
    1542              64 :     if( !EQUAL(poSrcBand->GetUnitType(),"") )
    1543               1 :         poDstBand->SetUnitType( poSrcBand->GetUnitType() );
    1544              64 : }
    1545                 : 
    1546                 : /************************************************************************/
    1547                 : /*                                main()                                */
    1548                 : /************************************************************************/
    1549                 : 
    1550             132 : int main( int argc, char ** argv )
    1551                 : 
    1552                 : {
    1553             132 :     return ProxyMain( argc, argv );
    1554                 : }
    1555                 : 
    1556                 : 

Generated by: LCOV version 1.7