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: 2012-04-28 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             258 : static int ProxyMain( int argc, char ** argv )
      97                 : 
      98                 : {
      99                 :     GDALDatasetH  hDataset, hOutDS;
     100                 :     int     i;
     101                 :     int     nRasterXSize, nRasterYSize;
     102             258 :     const char    *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
     103             258 :     int bFormatExplicitelySet = FALSE;
     104                 :     GDALDriverH   hDriver;
     105             258 :     int     *panBandList = NULL; /* negative value of panBandList[i] means mask band of ABS(panBandList[i]) */
     106             258 :     int         nBandCount = 0, bDefBands = TRUE;
     107                 :     double    adfGeoTransform[6];
     108             258 :     GDALDataType  eOutputType = GDT_Unknown;
     109             258 :     int     nOXSize = 0, nOYSize = 0;
     110             258 :     char    *pszOXSize=NULL, *pszOYSize=NULL;
     111             258 :     char                **papszCreateOptions = NULL;
     112             258 :     int                 anSrcWin[4], bStrict = FALSE;
     113                 :     const char          *pszProjection;
     114             258 :     int                 bScale = FALSE, bHaveScaleSrc = FALSE, bUnscale=FALSE;
     115             258 :     double          dfScaleSrcMin=0.0, dfScaleSrcMax=255.0;
     116             258 :     double              dfScaleDstMin=0.0, dfScaleDstMax=255.0;
     117                 :     double              dfULX, dfULY, dfLRX, dfLRY;
     118             258 :     char                **papszMetadataOptions = NULL;
     119             258 :     char                *pszOutputSRS = NULL;
     120             258 :     int                 bQuiet = FALSE, bGotBounds = FALSE;
     121             258 :     GDALProgressFunc    pfnProgress = GDALTermProgress;
     122             258 :     int                 nGCPCount = 0;
     123             258 :     GDAL_GCP            *pasGCPs = NULL;
     124             258 :     int                 iSrcFileArg = -1, iDstFileArg = -1;
     125             258 :     int                 bCopySubDatasets = FALSE;
     126             258 :     double              adfULLR[4] = { 0,0,0,0 };
     127             258 :     int                 bSetNoData = FALSE;
     128             258 :     int                 bUnsetNoData = FALSE;
     129             258 :     double    dfNoDataReal = 0.0;
     130             258 :     int                 nRGBExpand = 0;
     131             258 :     int                 bParsedMaskArgument = FALSE;
     132             258 :     int                 eMaskMode = MASK_AUTO;
     133             258 :     int                 nMaskBand = 0; /* negative value means mask band of ABS(nMaskBand) */
     134             258 :     int                 bStats = FALSE, bApproxStats = FALSE;
     135                 : 
     136                 : 
     137             258 :     anSrcWin[0] = 0;
     138             258 :     anSrcWin[1] = 0;
     139             258 :     anSrcWin[2] = 0;
     140             258 :     anSrcWin[3] = 0;
     141                 : 
     142             258 :     dfULX = dfULY = dfLRX = dfLRY = 0.0;
     143                 :     
     144                 :     /* Check strict compilation and runtime library version as we use C++ API */
     145             258 :     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            1522 :     for( i = 1; i < argc; i++ )
     152                 :     {
     153            1264 :         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             258 :     GDALAllRegister();
     166             258 :     argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
     167             258 :     if( argc < 1 )
     168               0 :         exit( -argc );
     169                 : 
     170                 : /* -------------------------------------------------------------------- */
     171                 : /*      Handle command line arguments.                                  */
     172                 : /* -------------------------------------------------------------------- */
     173            1088 :     for( i = 1; i < argc; i++ )
     174                 :     {
     175             832 :         if( EQUAL(argv[i], "--utility_version") )
     176                 :         {
     177                 :             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
     178               2 :                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
     179               2 :             return 0;
     180                 :         }
     181             986 :         else if( EQUAL(argv[i],"-of") && i < argc-1 )
     182                 :         {
     183             156 :             pszFormat = argv[++i];
     184             156 :             bFormatExplicitelySet = TRUE;
     185                 :         }
     186                 : 
     187             674 :         else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
     188                 :         {
     189               0 :             bQuiet = TRUE;
     190               0 :             pfnProgress = GDALDummyProgress;
     191                 :         }
     192                 : 
     193             722 :         else if( EQUAL(argv[i],"-ot") && i < argc-1 )
     194                 :         {
     195                 :             int iType;
     196                 :             
     197             576 :             for( iType = 1; iType < GDT_TypeCount; iType++ )
     198                 :             {
     199            1056 :                 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
     200             528 :                     && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
     201                 :                              argv[i+1]) )
     202                 :                 {
     203              48 :                     eOutputType = (GDALDataType) iType;
     204                 :                 }
     205                 :             }
     206                 : 
     207              48 :             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              48 :             i++;
     215                 :         }
     216             658 :         else if( EQUAL(argv[i],"-b") && i < argc-1 )
     217                 :         {
     218              32 :             const char* pszBand = argv[i+1];
     219              32 :             int bMask = FALSE;
     220              32 :             if (EQUAL(pszBand, "mask"))
     221               2 :                 pszBand = "mask,1";
     222              32 :             if (EQUALN(pszBand, "mask,", 5))
     223                 :             {
     224               2 :                 bMask = TRUE;
     225               2 :                 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               2 :                 if( !bParsedMaskArgument )
     229               2 :                     eMaskMode = MASK_DISABLED;
     230                 :             }
     231              32 :             int nBand = atoi(pszBand);
     232              32 :             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              32 :             i++;
     240                 : 
     241              32 :             nBandCount++;
     242                 :             panBandList = (int *) 
     243              32 :                 CPLRealloc(panBandList, sizeof(int) * nBandCount);
     244              32 :             panBandList[nBandCount-1] = nBand;
     245              32 :             if (bMask)
     246               2 :                 panBandList[nBandCount-1] *= -1;
     247                 : 
     248              32 :             if( panBandList[nBandCount-1] != nBandCount )
     249               6 :                 bDefBands = FALSE;
     250                 :         }
     251             600 :         else if( EQUAL(argv[i],"-mask") && i < argc-1 )
     252                 :         {
     253               6 :             bParsedMaskArgument = TRUE;
     254               6 :             const char* pszBand = argv[i+1];
     255               6 :             if (EQUAL(pszBand, "none"))
     256                 :             {
     257               2 :                 eMaskMode = MASK_DISABLED;
     258                 :             }
     259               4 :             else if (EQUAL(pszBand, "auto"))
     260                 :             {
     261               0 :                 eMaskMode = MASK_AUTO;
     262                 :             }
     263                 :             else
     264                 :             {
     265               4 :                 int bMask = FALSE;
     266               4 :                 if (EQUAL(pszBand, "mask"))
     267               0 :                     pszBand = "mask,1";
     268               4 :                 if (EQUALN(pszBand, "mask,", 5))
     269                 :                 {
     270               2 :                     bMask = TRUE;
     271               2 :                     pszBand += 5;
     272                 :                 }
     273               4 :                 int nBand = atoi(pszBand);
     274               4 :                 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               4 :                 eMaskMode = MASK_USER;
     283               4 :                 nMaskBand = nBand;
     284               4 :                 if (bMask)
     285               2 :                     nMaskBand *= -1;
     286                 :             }
     287               6 :             i ++;
     288                 :         }
     289             588 :         else if( EQUAL(argv[i],"-not_strict")  )
     290               0 :             bStrict = FALSE;
     291                 :             
     292             588 :         else if( EQUAL(argv[i],"-strict")  )
     293               0 :             bStrict = TRUE;
     294                 :             
     295             588 :         else if( EQUAL(argv[i],"-sds")  )
     296               4 :             bCopySubDatasets = TRUE;
     297                 :             
     298             608 :         else if( EQUAL(argv[i],"-gcp") && i < argc - 4 )
     299                 :         {
     300              24 :             char* endptr = NULL;
     301                 :             /* -gcp pixel line easting northing [elev] */
     302                 : 
     303              24 :             nGCPCount++;
     304                 :             pasGCPs = (GDAL_GCP *) 
     305              24 :                 CPLRealloc( pasGCPs, sizeof(GDAL_GCP) * nGCPCount );
     306              24 :             GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 );
     307                 : 
     308              24 :             pasGCPs[nGCPCount-1].dfGCPPixel = CPLAtofM(argv[++i]);
     309              24 :             pasGCPs[nGCPCount-1].dfGCPLine = CPLAtofM(argv[++i]);
     310              24 :             pasGCPs[nGCPCount-1].dfGCPX = CPLAtofM(argv[++i]);
     311              24 :             pasGCPs[nGCPCount-1].dfGCPY = CPLAtofM(argv[++i]);
     312              68 :             if( argv[i+1] != NULL 
     313              44 :                 && (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               4 :                 if (endptr && *endptr == 0)
     318               4 :                     pasGCPs[nGCPCount-1].dfGCPZ = CPLAtofM(argv[++i]);
     319                 :             }
     320                 : 
     321                 :             /* should set id and info? */
     322                 :         }   
     323                 : 
     324             566 :         else if( EQUAL(argv[i],"-a_nodata") && i < argc - 1 )
     325                 :         {
     326               6 :             if (EQUAL(argv[i+1], "none"))
     327                 :             {
     328               2 :                 bUnsetNoData = TRUE;
     329                 :             }
     330                 :             else
     331                 :             {
     332               4 :                 bSetNoData = TRUE;
     333               4 :                 dfNoDataReal = CPLAtofM(argv[i+1]);
     334                 :             }
     335               6 :             i += 1;
     336                 :         }   
     337                 : 
     338             556 :         else if( EQUAL(argv[i],"-a_ullr") && i < argc - 4 )
     339                 :         {
     340               2 :             adfULLR[0] = CPLAtofM(argv[i+1]);
     341               2 :             adfULLR[1] = CPLAtofM(argv[i+2]);
     342               2 :             adfULLR[2] = CPLAtofM(argv[i+3]);
     343               2 :             adfULLR[3] = CPLAtofM(argv[i+4]);
     344                 : 
     345               2 :             bGotBounds = TRUE;
     346                 :             
     347               2 :             i += 4;
     348                 :         }   
     349                 : 
     350             556 :         else if( EQUAL(argv[i],"-co") && i < argc-1 )
     351                 :         {
     352               4 :             papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
     353                 :         }   
     354                 : 
     355             548 :         else if( EQUAL(argv[i],"-scale") )
     356                 :         {
     357               2 :             bScale = TRUE;
     358               2 :             if( i < argc-2 && ArgIsNumeric(argv[i+1]) )
     359                 :             {
     360               2 :                 bHaveScaleSrc = TRUE;
     361               2 :                 dfScaleSrcMin = CPLAtofM(argv[i+1]);
     362               2 :                 dfScaleSrcMax = CPLAtofM(argv[i+2]);
     363               2 :                 i += 2;
     364                 :             }
     365               2 :             if( i < argc-2 && bHaveScaleSrc && ArgIsNumeric(argv[i+1]) )
     366                 :             {
     367               2 :                 dfScaleDstMin = CPLAtofM(argv[i+1]);
     368               2 :                 dfScaleDstMax = CPLAtofM(argv[i+2]);
     369               2 :                 i += 2;
     370                 :             }
     371                 :             else
     372                 :             {
     373               0 :                 dfScaleDstMin = 0.0;
     374               0 :                 dfScaleDstMax = 255.999;
     375                 :             }
     376                 :         }   
     377                 : 
     378             546 :         else if( EQUAL(argv[i], "-unscale") )
     379                 :         {
     380               0 :             bUnscale = TRUE;
     381                 :         }
     382                 : 
     383             548 :         else if( EQUAL(argv[i],"-mo") && i < argc-1 )
     384                 :         {
     385                 :             papszMetadataOptions = CSLAddString( papszMetadataOptions,
     386               2 :                                                  argv[++i] );
     387                 :         }
     388                 : 
     389             552 :         else if( EQUAL(argv[i],"-outsize") && i < argc-2 )
     390                 :         {
     391               8 :             pszOXSize = argv[++i];
     392               8 :             pszOYSize = argv[++i];
     393                 :         }   
     394                 : 
     395             542 :         else if( EQUAL(argv[i],"-srcwin") && i < argc-4 )
     396                 :         {
     397               6 :             anSrcWin[0] = atoi(argv[++i]);
     398               6 :             anSrcWin[1] = atoi(argv[++i]);
     399               6 :             anSrcWin[2] = atoi(argv[++i]);
     400               6 :             anSrcWin[3] = atoi(argv[++i]);
     401                 :         }   
     402                 : 
     403             532 :         else if( EQUAL(argv[i],"-projwin") && i < argc-4 )
     404                 :         {
     405               2 :             dfULX = CPLAtofM(argv[++i]);
     406               2 :             dfULY = CPLAtofM(argv[++i]);
     407               2 :             dfLRX = CPLAtofM(argv[++i]);
     408               2 :             dfLRY = CPLAtofM(argv[++i]);
     409                 :         }   
     410                 : 
     411             532 :         else if( EQUAL(argv[i],"-a_srs") && i < argc-1 )
     412                 :         {
     413               4 :             OGRSpatialReference oOutputSRS;
     414                 : 
     415               4 :             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               4 :             oOutputSRS.exportToWkt( &pszOutputSRS );
     424               4 :             i++;
     425                 :         }   
     426                 : 
     427             534 :         else if( EQUAL(argv[i],"-expand") && i < argc-1 )
     428                 :         {
     429              10 :             if (EQUAL(argv[i+1], "gray"))
     430               2 :                 nRGBExpand = 1;
     431               8 :             else if (EQUAL(argv[i+1], "rgb"))
     432               4 :                 nRGBExpand = 3;
     433               4 :             else if (EQUAL(argv[i+1], "rgba"))
     434               4 :                 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              10 :             i++;
     444                 :         }
     445                 : 
     446             514 :         else if( EQUAL(argv[i], "-stats") )
     447                 :         {
     448               2 :             bStats = TRUE;
     449               2 :             bApproxStats = FALSE;
     450                 :         }
     451             512 :         else if( EQUAL(argv[i], "-approx_stats") )
     452                 :         {
     453               0 :             bStats = TRUE;
     454               0 :             bApproxStats = TRUE;
     455                 :         }
     456                 : 
     457             512 :         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             512 :         else if( pszSource == NULL )
     466                 :         {
     467             256 :             iSrcFileArg = i;
     468             256 :             pszSource = argv[i];
     469                 :         }
     470             256 :         else if( pszDest == NULL )
     471                 :         {
     472             256 :             pszDest = argv[i];
     473             256 :             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             256 :     if( pszDest == NULL )
     486                 :     {
     487               0 :         Usage();
     488               0 :         GDALDestroyDriverManager();
     489               0 :         exit( 10 );
     490                 :     }
     491                 : 
     492             256 :     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             256 :     if( strcmp(pszDest, "/vsistdout/") == 0)
     500                 :     {
     501               0 :         bQuiet = TRUE;
     502               0 :         pfnProgress = GDALDummyProgress;
     503                 :     }
     504                 : 
     505             256 :     if (!bQuiet && !bFormatExplicitelySet)
     506             102 :         CheckExtensionConsistency(pszDest, pszFormat);
     507                 : 
     508                 : /* -------------------------------------------------------------------- */
     509                 : /*      Attempt to open source file.                                    */
     510                 : /* -------------------------------------------------------------------- */
     511                 : 
     512             256 :     hDataset = GDALOpenShared( pszSource, GA_ReadOnly );
     513                 :     
     514             256 :     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             256 :     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             256 :     if( CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0 
     538                 :         && bCopySubDatasets )
     539                 :     {
     540               2 :         char **papszSubdatasets = GDALGetMetadata(hDataset,"SUBDATASETS");
     541               2 :         char *pszSubDest = (char *) CPLMalloc(strlen(pszDest)+32);
     542                 :         int i;
     543               2 :         int bOldSubCall = bSubCall;
     544               2 :         char** papszDupArgv = CSLDuplicate(argv);
     545               2 :         int nRet = 0;
     546                 : 
     547               2 :         CPLFree(papszDupArgv[iDstFileArg]);
     548               2 :         papszDupArgv[iDstFileArg] = pszSubDest;
     549               2 :         bSubCall = TRUE;
     550               4 :         for( i = 0; papszSubdatasets[i] != NULL; i += 2 )
     551                 :         {
     552               2 :             CPLFree(papszDupArgv[iSrcFileArg]);
     553               2 :             papszDupArgv[iSrcFileArg] = CPLStrdup(strstr(papszSubdatasets[i],"=")+1);
     554               2 :             sprintf( pszSubDest, "%s%d", pszDest, i/2 + 1 );
     555               2 :             nRet = ProxyMain( argc, papszDupArgv );
     556               2 :             if (nRet != 0)
     557               0 :                 break;
     558                 :         }
     559               2 :         CSLDestroy(papszDupArgv);
     560                 :         
     561               2 :         bSubCall = bOldSubCall;
     562               2 :         CSLDestroy(argv);
     563                 : 
     564               2 :         GDALClose( hDataset );
     565                 : 
     566               2 :         if( !bSubCall )
     567                 :         {
     568               2 :             GDALDumpOpenDatasets( stderr );
     569               2 :             GDALDestroyDriverManager();
     570                 :         }
     571               2 :         return nRet;
     572                 :     }
     573                 : 
     574                 : /* -------------------------------------------------------------------- */
     575                 : /*      Collect some information from the source file.                  */
     576                 : /* -------------------------------------------------------------------- */
     577             254 :     nRasterXSize = GDALGetRasterXSize( hDataset );
     578             254 :     nRasterYSize = GDALGetRasterYSize( hDataset );
     579                 : 
     580             254 :     if( !bQuiet )
     581             254 :         printf( "Input file size is %d, %d\n", nRasterXSize, nRasterYSize );
     582                 : 
     583             254 :     if( anSrcWin[2] == 0 && anSrcWin[3] == 0 )
     584                 :     {
     585             248 :         anSrcWin[2] = nRasterXSize;
     586             248 :         anSrcWin[3] = nRasterYSize;
     587                 :     }
     588                 : 
     589                 : /* -------------------------------------------------------------------- */
     590                 : /*  Build band list to translate          */
     591                 : /* -------------------------------------------------------------------- */
     592             254 :     if( nBandCount == 0 )
     593                 :     {
     594             244 :         nBandCount = GDALGetRasterCount( hDataset );
     595             244 :         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             244 :         panBandList = (int *) CPLMalloc(sizeof(int)*nBandCount);
     603             518 :         for( i = 0; i < nBandCount; i++ )
     604             274 :             panBandList[i] = i+1;
     605                 :     }
     606                 :     else
     607                 :     {
     608              42 :         for( i = 0; i < nBandCount; i++ )
     609                 :         {
     610              32 :             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              10 :         if( nBandCount != GDALGetRasterCount( hDataset ) )
     621               6 :             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             254 :     if( dfULX != 0.0 || dfULY != 0.0 
     632                 :         || dfLRX != 0.0 || dfLRY != 0.0 )
     633                 :     {
     634                 :         double  adfGeoTransform[6];
     635                 : 
     636               2 :         GDALGetGeoTransform( hDataset, adfGeoTransform );
     637                 : 
     638               2 :         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               2 :             ((dfULX - adfGeoTransform[0]) / adfGeoTransform[1] + 0.001);
     651                 :         anSrcWin[1] = (int) 
     652               2 :             ((dfULY - adfGeoTransform[3]) / adfGeoTransform[5] + 0.001);
     653                 : 
     654               2 :         anSrcWin[2] = (int) ((dfLRX - dfULX) / adfGeoTransform[1] + 0.5);
     655               2 :         anSrcWin[3] = (int) ((dfLRY - dfULY) / adfGeoTransform[5] + 0.5);
     656                 : 
     657               2 :         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               2 :                      anSrcWin[3] );
     664                 :         
     665               6 :         if( anSrcWin[0] < 0 || anSrcWin[1] < 0 
     666               2 :             || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hDataset) 
     667               2 :             || 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            1270 :     if( anSrcWin[0] < 0 || anSrcWin[1] < 0 
     681             508 :         || anSrcWin[2] <= 0 || anSrcWin[3] <= 0
     682             254 :         || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hDataset) 
     683             254 :         || 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             254 :     hDriver = GDALGetDriverByName( pszFormat );
     701             254 :     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             506 :            anSrcWin[0] == 0 && anSrcWin[1] == 0
     741             252 :         && anSrcWin[2] == GDALGetRasterXSize(hDataset)
     742             248 :         && anSrcWin[3] == GDALGetRasterYSize(hDataset)
     743            1006 :         && pszOXSize == NULL && pszOYSize == NULL );
     744                 : 
     745             254 :     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             150 :                                  pfnProgress, NULL );
     758                 : 
     759             150 :         if( hOutDS != NULL )
     760              20 :             GDALClose( hOutDS );
     761                 :         
     762             150 :         GDALClose( hDataset );
     763                 : 
     764             150 :         CPLFree( panBandList );
     765                 : 
     766             150 :         if( !bSubCall )
     767                 :         {
     768             148 :             GDALDumpOpenDatasets( stderr );
     769             148 :             GDALDestroyDriverManager();
     770                 :         }
     771                 : 
     772             150 :         CSLDestroy( argv );
     773             150 :         CSLDestroy( papszCreateOptions );
     774                 : 
     775             150 :         return hOutDS == NULL;
     776                 :     }
     777                 : 
     778                 : /* -------------------------------------------------------------------- */
     779                 : /*      Establish some parameters.                                      */
     780                 : /* -------------------------------------------------------------------- */
     781             104 :     if( pszOXSize == NULL )
     782                 :     {
     783              96 :         nOXSize = anSrcWin[2];
     784              96 :         nOYSize = anSrcWin[3];
     785                 :     }
     786                 :     else
     787                 :     {
     788               8 :         nOXSize = (int) ((pszOXSize[strlen(pszOXSize)-1]=='%' 
     789              16 :                           ? CPLAtofM(pszOXSize)/100*anSrcWin[2] : atoi(pszOXSize)));
     790               8 :         nOYSize = (int) ((pszOYSize[strlen(pszOYSize)-1]=='%' 
     791              16 :                           ? 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             104 :     poVDS = (VRTDataset *) VRTCreate( nOXSize, nOYSize );
     803                 : 
     804             104 :     if( nGCPCount == 0 )
     805                 :     {
     806              98 :         if( pszOutputSRS != NULL )
     807                 :         {
     808               0 :             poVDS->SetProjection( pszOutputSRS );
     809                 :         }
     810                 :         else
     811                 :         {
     812              98 :             pszProjection = GDALGetProjectionRef( hDataset );
     813              98 :             if( pszProjection != NULL && strlen(pszProjection) > 0 )
     814              86 :                 poVDS->SetProjection( pszProjection );
     815                 :         }
     816                 :     }
     817                 : 
     818             104 :     if( bGotBounds )
     819                 :     {
     820               2 :         adfGeoTransform[0] = adfULLR[0];
     821               2 :         adfGeoTransform[1] = (adfULLR[2] - adfULLR[0]) / nOXSize;
     822               2 :         adfGeoTransform[2] = 0.0;
     823               2 :         adfGeoTransform[3] = adfULLR[1];
     824               2 :         adfGeoTransform[4] = 0.0;
     825               2 :         adfGeoTransform[5] = (adfULLR[3] - adfULLR[1]) / nOYSize;
     826                 : 
     827               2 :         poVDS->SetGeoTransform( adfGeoTransform );
     828                 :     }
     829                 : 
     830             102 :     else if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None 
     831                 :         && nGCPCount == 0 )
     832                 :     {
     833             172 :         adfGeoTransform[0] += anSrcWin[0] * adfGeoTransform[1]
     834             258 :             + anSrcWin[1] * adfGeoTransform[2];
     835             172 :         adfGeoTransform[3] += anSrcWin[0] * adfGeoTransform[4]
     836             258 :             + anSrcWin[1] * adfGeoTransform[5];
     837                 :         
     838              86 :         adfGeoTransform[1] *= anSrcWin[2] / (double) nOXSize;
     839              86 :         adfGeoTransform[2] *= anSrcWin[3] / (double) nOYSize;
     840              86 :         adfGeoTransform[4] *= anSrcWin[2] / (double) nOXSize;
     841              86 :         adfGeoTransform[5] *= anSrcWin[3] / (double) nOYSize;
     842                 :         
     843              86 :         poVDS->SetGeoTransform( adfGeoTransform );
     844                 :     }
     845                 : 
     846             104 :     if( nGCPCount != 0 )
     847                 :     {
     848               6 :         const char *pszGCPProjection = pszOutputSRS;
     849                 : 
     850               6 :         if( pszGCPProjection == NULL )
     851               2 :             pszGCPProjection = GDALGetGCPProjection( hDataset );
     852               6 :         if( pszGCPProjection == NULL )
     853               0 :             pszGCPProjection = "";
     854                 : 
     855               6 :         poVDS->SetGCPs( nGCPCount, pasGCPs, pszGCPProjection );
     856                 : 
     857               6 :         GDALDeinitGCPs( nGCPCount, pasGCPs );
     858               6 :         CPLFree( pasGCPs );
     859                 :     }
     860                 : 
     861              98 :     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             104 :     char** papszMetadata = CSLDuplicate(((GDALDataset*)hDataset)->GetMetadata());
     887             104 :     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              50 :         char** papszIter = papszMetadata;
     892             192 :         while(papszIter && *papszIter)
     893                 :         {
     894              92 :             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              92 :                 papszIter++;
     902                 :         }
     903                 :     }
     904             104 :     poVDS->SetMetadata( papszMetadata );
     905             104 :     CSLDestroy( papszMetadata );
     906             104 :     AttachMetadata( (GDALDatasetH) poVDS, papszMetadataOptions );
     907                 : 
     908             104 :     const char* pszInterleave = GDALGetMetadataItem(hDataset, "INTERLEAVE", "IMAGE_STRUCTURE");
     909             104 :     if (pszInterleave)
     910              94 :         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             104 :     if( bSpatialArrangementPreserved )
     917                 :     {
     918                 :         char **papszMD;
     919                 : 
     920              90 :         papszMD = ((GDALDataset*)hDataset)->GetMetadata("RPC");
     921              90 :         if( papszMD != NULL )
     922               0 :             poVDS->SetMetadata( papszMD, "RPC" );
     923                 : 
     924              90 :         papszMD = ((GDALDataset*)hDataset)->GetMetadata("GEOLOCATION");
     925              90 :         if( papszMD != NULL )
     926               0 :             poVDS->SetMetadata( papszMD, "GEOLOCATION" );
     927                 :     }
     928                 : 
     929             104 :     int nSrcBandCount = nBandCount;
     930                 : 
     931             104 :     if (nRGBExpand != 0)
     932                 :     {
     933                 :         GDALRasterBand  *poSrcBand;
     934                 :         poSrcBand = ((GDALDataset *) 
     935              10 :                      hDataset)->GetRasterBand(ABS(panBandList[0]));
     936              10 :         if (panBandList[0] < 0)
     937               0 :             poSrcBand = poSrcBand->GetMaskBand();
     938              10 :         GDALColorTable* poColorTable = poSrcBand->GetColorTable();
     939              10 :         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              10 :         if (nRGBExpand == 1)
     953                 :         {
     954               2 :             int nColorCount = poColorTable->GetColorEntryCount();
     955                 :             int nColor;
     956               6 :             for( nColor = 0; nColor < nColorCount; nColor++ )
     957                 :             {
     958               4 :                 const GDALColorEntry* poEntry = poColorTable->GetColorEntry(nColor);
     959               4 :                 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              10 :         if (nBandCount == 1)
     968               8 :             nBandCount = nRGBExpand;
     969               4 :         else if (nBandCount == 2 && (nRGBExpand == 3 || nRGBExpand == 4))
     970               2 :             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             104 :         (bScale || bUnscale || !bSpatialArrangementPreserved || nRGBExpand != 0);
     980                 : 
     981                 : /* ==================================================================== */
     982                 : /*      Process all bands.                                              */
     983                 : /* ==================================================================== */
     984             262 :     for( i = 0; i < nBandCount; i++ )
     985                 :     {
     986                 :         VRTSourcedRasterBand   *poVRTBand;
     987                 :         GDALRasterBand  *poSrcBand;
     988                 :         GDALDataType    eBandType;
     989             158 :         int             nComponent = 0;
     990                 : 
     991                 :         int nSrcBand;
     992             158 :         if (nRGBExpand != 0)
     993                 :         {
     994              32 :             if (nSrcBandCount == 2 && nRGBExpand == 4 && i == 3)
     995               2 :                 nSrcBand = panBandList[1];
     996                 :             else
     997                 :             {
     998              28 :                 nSrcBand = panBandList[0];
     999              28 :                 nComponent = i + 1;
    1000                 :             }
    1001                 :         }
    1002                 :         else
    1003             128 :             nSrcBand = panBandList[i];
    1004                 : 
    1005             158 :         poSrcBand = ((GDALDataset *) hDataset)->GetRasterBand(ABS(nSrcBand));
    1006                 : 
    1007                 : /* -------------------------------------------------------------------- */
    1008                 : /*      Select output data type to match source.                        */
    1009                 : /* -------------------------------------------------------------------- */
    1010             158 :         if( eOutputType == GDT_Unknown )
    1011             110 :             eBandType = poSrcBand->GetRasterDataType();
    1012                 :         else
    1013              48 :             eBandType = eOutputType;
    1014                 : 
    1015                 : /* -------------------------------------------------------------------- */
    1016                 : /*      Create this band.                                               */
    1017                 : /* -------------------------------------------------------------------- */
    1018             158 :         poVDS->AddBand( eBandType, NULL );
    1019             158 :         poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand( i+1 );
    1020             158 :         if (nSrcBand < 0)
    1021                 :         {
    1022               2 :             poVRTBand->AddMaskBandSource(poSrcBand);
    1023               2 :             continue;
    1024                 :         }
    1025                 : 
    1026                 : /* -------------------------------------------------------------------- */
    1027                 : /*      Do we need to collect scaling information?                      */
    1028                 : /* -------------------------------------------------------------------- */
    1029             156 :         double dfScale=1.0, dfOffset=0.0;
    1030                 : 
    1031             156 :         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             156 :         if( bScale )
    1040                 :         {
    1041               2 :             if( dfScaleSrcMax == dfScaleSrcMin )
    1042               0 :                 dfScaleSrcMax += 0.1;
    1043               2 :             if( dfScaleDstMax == dfScaleDstMin )
    1044               0 :                 dfScaleDstMax += 0.1;
    1045                 : 
    1046                 :             dfScale = (dfScaleDstMax - dfScaleDstMin) 
    1047               2 :                 / (dfScaleSrcMax - dfScaleSrcMin);
    1048               2 :             dfOffset = -1 * dfScaleSrcMin * dfScale + dfScaleDstMin;
    1049                 :         }
    1050                 : 
    1051             156 :         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             188 :         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              32 :                                          nComponent );
    1070                 :         }
    1071                 :         else
    1072                 :             poVRTBand->AddSimpleSource( poSrcBand,
    1073                 :                                         anSrcWin[0], anSrcWin[1], 
    1074                 :                                         anSrcWin[2], anSrcWin[3], 
    1075             124 :                                         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             156 :         if (nRGBExpand == 1)
    1083                 :         {
    1084               2 :             poVRTBand->SetColorInterpretation( GCI_GrayIndex );
    1085                 :         }
    1086             182 :         else if (nRGBExpand != 0 && i < nRGBExpand)
    1087                 :         {
    1088              28 :             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             126 :                           !bSetNoData && !bUnsetNoData );
    1100                 :         }
    1101                 : 
    1102                 : /* -------------------------------------------------------------------- */
    1103                 : /*      Set a forcable nodata value?                                    */
    1104                 : /* -------------------------------------------------------------------- */
    1105             156 :         if( bSetNoData )
    1106                 :         {
    1107               4 :             double dfVal = dfNoDataReal;
    1108               4 :             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               4 :             switch(eBandType)
    1117                 :             {
    1118                 :                 case GDT_Byte:
    1119               4 :                     CLAMP(dfVal, GByte, 0.0, 255.0);
    1120               4 :                     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               4 :             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               4 :             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               4 :             poVRTBand->SetNoDataValue( dfVal );
    1152                 :         }
    1153                 : 
    1154             276 :         if (eMaskMode == MASK_AUTO &&
    1155                 :             (GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) & GMF_PER_DATASET) == 0 &&
    1156             120 :             (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             104 :     if (eMaskMode == MASK_USER)
    1171                 :     {
    1172                 :         GDALRasterBand *poSrcBand =
    1173               4 :             (GDALRasterBand*)GDALGetRasterBand(hDataset, ABS(nMaskBand));
    1174               4 :         if (poSrcBand && poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
    1175                 :         {
    1176                 :             VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
    1177               4 :                 GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
    1178               4 :             if (nMaskBand > 0)
    1179                 :                 hMaskVRTBand->AddSimpleSource(poSrcBand,
    1180                 :                                         anSrcWin[0], anSrcWin[1],
    1181                 :                                         anSrcWin[2], anSrcWin[3],
    1182               2 :                                         0, 0, nOXSize, nOYSize );
    1183                 :             else
    1184                 :                 hMaskVRTBand->AddMaskBandSource(poSrcBand,
    1185                 :                                         anSrcWin[0], anSrcWin[1],
    1186                 :                                         anSrcWin[2], anSrcWin[3],
    1187               2 :                                         0, 0, nOXSize, nOYSize );
    1188                 :         }
    1189                 :     }
    1190                 :     else
    1191             100 :     if (eMaskMode == MASK_AUTO && nSrcBandCount > 0 &&
    1192                 :         GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) == GMF_PER_DATASET)
    1193                 :     {
    1194               2 :         if (poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
    1195                 :         {
    1196                 :             VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
    1197               2 :                 GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
    1198                 :             hMaskVRTBand->AddMaskBandSource((GDALRasterBand*)GDALGetRasterBand(hDataset, 1),
    1199                 :                                         anSrcWin[0], anSrcWin[1],
    1200                 :                                         anSrcWin[2], anSrcWin[3],
    1201               2 :                                         0, 0, nOXSize, nOYSize );
    1202                 :         }
    1203                 :     }
    1204                 : 
    1205                 : /* -------------------------------------------------------------------- */
    1206                 : /*      Compute stats if required.                                      */
    1207                 : /* -------------------------------------------------------------------- */
    1208             104 :     if (bStats)
    1209                 :     {
    1210               4 :         for( i = 0; i < poVDS->GetRasterCount(); i++ )
    1211                 :         {
    1212                 :             double dfMin, dfMax, dfMean, dfStdDev;
    1213                 :             poVDS->GetRasterBand(i+1)->ComputeStatistics( bApproxStats,
    1214               2 :                     &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             104 :                              pfnProgress, NULL );
    1224             104 :     if( hOutDS != NULL )
    1225                 :     {
    1226             104 :         int bHasGotErr = FALSE;
    1227             104 :         CPLErrorReset();
    1228             104 :         GDALFlushCache( hOutDS );
    1229             104 :         if (CPLGetLastErrorType() != CE_None)
    1230               0 :             bHasGotErr = TRUE;
    1231             104 :         GDALClose( hOutDS );
    1232             104 :         if (bHasGotErr)
    1233               0 :             hOutDS = NULL;
    1234                 :     }
    1235                 :     
    1236             104 :     GDALClose( (GDALDatasetH) poVDS );
    1237                 :         
    1238             104 :     GDALClose( hDataset );
    1239                 : 
    1240             104 :     CPLFree( panBandList );
    1241                 :     
    1242             104 :     CPLFree( pszOutputSRS );
    1243                 : 
    1244             104 :     if( !bSubCall )
    1245                 :     {
    1246             104 :         GDALDumpOpenDatasets( stderr );
    1247             104 :         GDALDestroyDriverManager();
    1248                 :     }
    1249                 : 
    1250             104 :     CSLDestroy( argv );
    1251             104 :     CSLDestroy( papszCreateOptions );
    1252                 :     
    1253             104 :     return hOutDS == NULL;
    1254                 : }
    1255                 : 
    1256                 : 
    1257                 : /************************************************************************/
    1258                 : /*                            ArgIsNumeric()                            */
    1259                 : /************************************************************************/
    1260                 : 
    1261               4 : int ArgIsNumeric( const char *pszArg )
    1262                 : 
    1263                 : {
    1264               4 :     if( pszArg[0] == '-' )
    1265               0 :         pszArg++;
    1266                 : 
    1267               4 :     if( *pszArg == '\0' )
    1268               0 :         return FALSE;
    1269                 : 
    1270              12 :     while( *pszArg != '\0' )
    1271                 :     {
    1272               4 :         if( (*pszArg < '0' || *pszArg > '9') && *pszArg != '.' )
    1273               0 :             return FALSE;
    1274               4 :         pszArg++;
    1275                 :     }
    1276                 :         
    1277               4 :     return TRUE;
    1278                 : }
    1279                 : 
    1280                 : /************************************************************************/
    1281                 : /*                           AttachMetadata()                           */
    1282                 : /************************************************************************/
    1283                 : 
    1284             104 : static void AttachMetadata( GDALDatasetH hDS, char **papszMetadataOptions )
    1285                 : 
    1286                 : {
    1287             104 :     int nCount = CSLCount(papszMetadataOptions);
    1288                 :     int i;
    1289                 : 
    1290             106 :     for( i = 0; i < nCount; i++ )
    1291                 :     {
    1292               2 :         char    *pszKey = NULL;
    1293                 :         const char *pszValue;
    1294                 :         
    1295               2 :         pszValue = CPLParseNameValue( papszMetadataOptions[i], &pszKey );
    1296               2 :         GDALSetMetadataItem(hDS,pszKey,pszValue,NULL);
    1297               2 :         CPLFree( pszKey );
    1298                 :     }
    1299                 : 
    1300             104 :     CSLDestroy( papszMetadataOptions );
    1301             104 : }
    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             126 : static void CopyBandInfo( GDALRasterBand * poSrcBand, GDALRasterBand * poDstBand,
    1311                 :                           int bCanCopyStatsMetadata, int bCopyScale, int bCopyNoData )
    1312                 : 
    1313                 : {
    1314                 :     int bSuccess;
    1315                 :     double dfNoData;
    1316                 : 
    1317             126 :     if (bCanCopyStatsMetadata)
    1318                 :     {
    1319             100 :         poDstBand->SetMetadata( poSrcBand->GetMetadata() );
    1320                 :     }
    1321                 :     else
    1322                 :     {
    1323              26 :         char** papszMetadata = poSrcBand->GetMetadata();
    1324              26 :         char** papszMetadataNew = NULL;
    1325              54 :         for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
    1326                 :         {
    1327              28 :             if (strncmp(papszMetadata[i], "STATISTICS_", 11) != 0)
    1328               2 :                 papszMetadataNew = CSLAddString(papszMetadataNew, papszMetadata[i]);
    1329                 :         }
    1330              26 :         poDstBand->SetMetadata( papszMetadataNew );
    1331              26 :         CSLDestroy(papszMetadataNew);
    1332                 :     }
    1333                 : 
    1334             126 :     poDstBand->SetColorTable( poSrcBand->GetColorTable() );
    1335             126 :     poDstBand->SetColorInterpretation(poSrcBand->GetColorInterpretation());
    1336             126 :     if( strlen(poSrcBand->GetDescription()) > 0 )
    1337               2 :         poDstBand->SetDescription( poSrcBand->GetDescription() );
    1338                 : 
    1339             126 :     if (bCopyNoData)
    1340                 :     {
    1341             120 :         dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
    1342             120 :         if( bSuccess )
    1343               2 :             poDstBand->SetNoDataValue( dfNoData );
    1344                 :     }
    1345                 : 
    1346             126 :     if (bCopyScale)
    1347                 :     {
    1348             126 :         poDstBand->SetOffset( poSrcBand->GetOffset() );
    1349             126 :         poDstBand->SetScale( poSrcBand->GetScale() );
    1350                 :     }
    1351                 : 
    1352             126 :     poDstBand->SetCategoryNames( poSrcBand->GetCategoryNames() );
    1353             126 :     if( !EQUAL(poSrcBand->GetUnitType(),"") )
    1354               2 :         poDstBand->SetUnitType( poSrcBand->GetUnitType() );
    1355             126 : }
    1356                 : 
    1357                 : /************************************************************************/
    1358                 : /*                                main()                                */
    1359                 : /************************************************************************/
    1360                 : 
    1361             256 : int main( int argc, char ** argv )
    1362                 : 
    1363                 : {
    1364             256 :     return ProxyMain( argc, argv );
    1365                 : }
    1366                 : 
    1367                 : 

Generated by: LCOV version 1.7