LCOV - code coverage report
Current view: directory - apps - gdal_translate.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 599 451 75.3 %
Date: 2011-12-18 Functions: 6 5 83.3 %

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

Generated by: LCOV version 1.7