~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to apps/gdal_translate.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
 
 * $Id: gdal_translate.cpp 18576 2010-01-17 22:32:24Z rouault $
 
2
 * $Id: gdal_translate.cpp 22783 2011-07-23 19:28:16Z rouault $
3
3
 *
4
4
 * Project:  GDAL Utilities
5
5
 * Purpose:  GDAL Image Translator Program
33
33
#include "gdal_priv.h"
34
34
#include "ogr_spatialref.h"
35
35
#include "vrt/vrtdataset.h"
 
36
#include "commonutils.h"
36
37
 
37
 
CPL_CVSID("$Id: gdal_translate.cpp 18576 2010-01-17 22:32:24Z rouault $");
 
38
CPL_CVSID("$Id: gdal_translate.cpp 22783 2011-07-23 19:28:16Z rouault $");
38
39
 
39
40
static int ArgIsNumeric( const char * );
40
41
static void AttachMetadata( GDALDatasetH, char ** );
 
42
static void CopyBandInfo( GDALRasterBand * poSrcBand, GDALRasterBand * poDstBand,
 
43
                            int bCanCopyStatsMetadata, int bCopyScale, int bCopyNoData );
41
44
static int bSubCall = FALSE;
42
45
 
43
46
/*  ******************************************************************* */
52
55
    printf( "Usage: gdal_translate [--help-general]\n"
53
56
            "       [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
54
57
            "             CInt16/CInt32/CFloat32/CFloat64}] [-strict]\n"
55
 
            "       [-of format] [-b band] [-expand {gray|rgb|rgba}]\n"
 
58
            "       [-of format] [-b band] [-mask band] [-expand {gray|rgb|rgba}]\n"
56
59
            "       [-outsize xsize[%%] ysize[%%]]\n"
57
60
            "       [-unscale] [-scale [src_min src_max [dst_min dst_max]]]\n"
58
61
            "       [-srcwin xoff yoff xsize ysize] [-projwin ulx uly lrx lry]\n"
59
62
            "       [-a_srs srs_def] [-a_ullr ulx uly lrx lry] [-a_nodata value]\n"
60
63
            "       [-gcp pixel line easting northing [elevation]]*\n" 
61
64
            "       [-mo \"META-TAG=VALUE\"]* [-q] [-sds]\n"
62
 
            "       [-co \"NAME=VALUE\"]*\n"
 
65
            "       [-co \"NAME=VALUE\"]* [-stats]\n"
63
66
            "       src_dataset dst_dataset\n\n" );
64
67
 
65
68
    printf( "%s\n\n", GDALVersionInfo( "--version" ) );
83
86
/*                             ProxyMain()                              */
84
87
/************************************************************************/
85
88
 
 
89
enum
 
90
{
 
91
    MASK_DISABLED,
 
92
    MASK_AUTO,
 
93
    MASK_USER
 
94
};
 
95
 
86
96
static int ProxyMain( int argc, char ** argv )
87
97
 
88
98
{
90
100
    int                 i;
91
101
    int                 nRasterXSize, nRasterYSize;
92
102
    const char          *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
 
103
    int bFormatExplicitelySet = FALSE;
93
104
    GDALDriverH         hDriver;
94
 
    int                 *panBandList = NULL, nBandCount = 0, bDefBands = TRUE;
 
105
    int                 *panBandList = NULL; /* negative value of panBandList[i] means mask band of ABS(panBandList[i]) */
 
106
    int         nBandCount = 0, bDefBands = TRUE;
95
107
    double              adfGeoTransform[6];
96
108
    GDALDataType        eOutputType = GDT_Unknown;
97
109
    int                 nOXSize = 0, nOYSize = 0;
113
125
    int                 bCopySubDatasets = FALSE;
114
126
    double              adfULLR[4] = { 0,0,0,0 };
115
127
    int                 bSetNoData = FALSE;
 
128
    int                 bUnsetNoData = FALSE;
116
129
    double              dfNoDataReal = 0.0;
117
130
    int                 nRGBExpand = 0;
 
131
    int                 bParsedMaskArgument = FALSE;
 
132
    int                 eMaskMode = MASK_AUTO;
 
133
    int                 nMaskBand = 0; /* negative value means mask band of ABS(nMaskBand) */
 
134
    int                 bStats = FALSE, bApproxStats = FALSE;
118
135
 
119
136
 
120
137
    anSrcWin[0] = 0;
162
179
            return 0;
163
180
        }
164
181
        else if( EQUAL(argv[i],"-of") && i < argc-1 )
 
182
        {
165
183
            pszFormat = argv[++i];
 
184
            bFormatExplicitelySet = TRUE;
 
185
        }
166
186
 
167
187
        else if( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
168
188
        {
195
215
        }
196
216
        else if( EQUAL(argv[i],"-b") && i < argc-1 )
197
217
        {
198
 
            if( atoi(argv[i+1]) < 1 )
 
218
            const char* pszBand = argv[i+1];
 
219
            int bMask = FALSE;
 
220
            if (EQUAL(pszBand, "mask"))
 
221
                pszBand = "mask,1";
 
222
            if (EQUALN(pszBand, "mask,", 5))
 
223
            {
 
224
                bMask = TRUE;
 
225
                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
                if( !bParsedMaskArgument )
 
229
                    eMaskMode = MASK_DISABLED;
 
230
            }
 
231
            int nBand = atoi(pszBand);
 
232
            if( nBand < 1 )
199
233
            {
200
234
                printf( "Unrecognizable band number (%s).\n", argv[i+1] );
201
235
                Usage();
202
236
                GDALDestroyDriverManager();
203
237
                exit( 2 );
204
238
            }
 
239
            i++;
205
240
 
206
241
            nBandCount++;
207
242
            panBandList = (int *) 
208
243
                CPLRealloc(panBandList, sizeof(int) * nBandCount);
209
 
            panBandList[nBandCount-1] = atoi(argv[++i]);
 
244
            panBandList[nBandCount-1] = nBand;
 
245
            if (bMask)
 
246
                panBandList[nBandCount-1] *= -1;
210
247
 
211
248
            if( panBandList[nBandCount-1] != nBandCount )
212
249
                bDefBands = FALSE;
213
250
        }
 
251
        else if( EQUAL(argv[i],"-mask") && i < argc-1 )
 
252
        {
 
253
            bParsedMaskArgument = TRUE;
 
254
            const char* pszBand = argv[i+1];
 
255
            if (EQUAL(pszBand, "none"))
 
256
            {
 
257
                eMaskMode = MASK_DISABLED;
 
258
            }
 
259
            else if (EQUAL(pszBand, "auto"))
 
260
            {
 
261
                eMaskMode = MASK_AUTO;
 
262
            }
 
263
            else
 
264
            {
 
265
                int bMask = FALSE;
 
266
                if (EQUAL(pszBand, "mask"))
 
267
                    pszBand = "mask,1";
 
268
                if (EQUALN(pszBand, "mask,", 5))
 
269
                {
 
270
                    bMask = TRUE;
 
271
                    pszBand += 5;
 
272
                }
 
273
                int nBand = atoi(pszBand);
 
274
                if( nBand < 1 )
 
275
                {
 
276
                    printf( "Unrecognizable band number (%s).\n", argv[i+1] );
 
277
                    Usage();
 
278
                    GDALDestroyDriverManager();
 
279
                    exit( 2 );
 
280
                }
 
281
                
 
282
                eMaskMode = MASK_USER;
 
283
                nMaskBand = nBand;
 
284
                if (bMask)
 
285
                    nMaskBand *= -1;
 
286
            }
 
287
            i ++;
 
288
        }
214
289
        else if( EQUAL(argv[i],"-not_strict")  )
215
290
            bStrict = FALSE;
216
291
            
230
305
                CPLRealloc( pasGCPs, sizeof(GDAL_GCP) * nGCPCount );
231
306
            GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 );
232
307
 
233
 
            pasGCPs[nGCPCount-1].dfGCPPixel = atof(argv[++i]);
234
 
            pasGCPs[nGCPCount-1].dfGCPLine = atof(argv[++i]);
235
 
            pasGCPs[nGCPCount-1].dfGCPX = atof(argv[++i]);
236
 
            pasGCPs[nGCPCount-1].dfGCPY = atof(argv[++i]);
 
308
            pasGCPs[nGCPCount-1].dfGCPPixel = CPLAtofM(argv[++i]);
 
309
            pasGCPs[nGCPCount-1].dfGCPLine = CPLAtofM(argv[++i]);
 
310
            pasGCPs[nGCPCount-1].dfGCPX = CPLAtofM(argv[++i]);
 
311
            pasGCPs[nGCPCount-1].dfGCPY = CPLAtofM(argv[++i]);
237
312
            if( argv[i+1] != NULL 
238
313
                && (CPLStrtod(argv[i+1], &endptr) != 0.0 || argv[i+1][0] == '0') )
239
314
            {
240
315
                /* Check that last argument is really a number and not a filename */
241
316
                /* looking like a number (see ticket #863) */
242
317
                if (endptr && *endptr == 0)
243
 
                    pasGCPs[nGCPCount-1].dfGCPZ = atof(argv[++i]);
 
318
                    pasGCPs[nGCPCount-1].dfGCPZ = CPLAtofM(argv[++i]);
244
319
            }
245
320
 
246
321
            /* should set id and info? */
248
323
 
249
324
        else if( EQUAL(argv[i],"-a_nodata") && i < argc - 1 )
250
325
        {
251
 
            bSetNoData = TRUE;
252
 
            dfNoDataReal = atof(argv[i+1]);
 
326
            if (EQUAL(argv[i+1], "none"))
 
327
            {
 
328
                bUnsetNoData = TRUE;
 
329
            }
 
330
            else
 
331
            {
 
332
                bSetNoData = TRUE;
 
333
                dfNoDataReal = CPLAtofM(argv[i+1]);
 
334
            }
253
335
            i += 1;
254
336
        }   
255
337
 
256
338
        else if( EQUAL(argv[i],"-a_ullr") && i < argc - 4 )
257
339
        {
258
 
            adfULLR[0] = atof(argv[i+1]);
259
 
            adfULLR[1] = atof(argv[i+2]);
260
 
            adfULLR[2] = atof(argv[i+3]);
261
 
            adfULLR[3] = atof(argv[i+4]);
 
340
            adfULLR[0] = CPLAtofM(argv[i+1]);
 
341
            adfULLR[1] = CPLAtofM(argv[i+2]);
 
342
            adfULLR[2] = CPLAtofM(argv[i+3]);
 
343
            adfULLR[3] = CPLAtofM(argv[i+4]);
262
344
 
263
345
            bGotBounds = TRUE;
264
346
            
276
358
            if( i < argc-2 && ArgIsNumeric(argv[i+1]) )
277
359
            {
278
360
                bHaveScaleSrc = TRUE;
279
 
                dfScaleSrcMin = atof(argv[i+1]);
280
 
                dfScaleSrcMax = atof(argv[i+2]);
 
361
                dfScaleSrcMin = CPLAtofM(argv[i+1]);
 
362
                dfScaleSrcMax = CPLAtofM(argv[i+2]);
281
363
                i += 2;
282
364
            }
283
365
            if( i < argc-2 && bHaveScaleSrc && ArgIsNumeric(argv[i+1]) )
284
366
            {
285
 
                dfScaleDstMin = atof(argv[i+1]);
286
 
                dfScaleDstMax = atof(argv[i+2]);
 
367
                dfScaleDstMin = CPLAtofM(argv[i+1]);
 
368
                dfScaleDstMax = CPLAtofM(argv[i+2]);
287
369
                i += 2;
288
370
            }
289
371
            else
320
402
 
321
403
        else if( EQUAL(argv[i],"-projwin") && i < argc-4 )
322
404
        {
323
 
            dfULX = atof(argv[++i]);
324
 
            dfULY = atof(argv[++i]);
325
 
            dfLRX = atof(argv[++i]);
326
 
            dfLRY = atof(argv[++i]);
 
405
            dfULX = CPLAtofM(argv[++i]);
 
406
            dfULY = CPLAtofM(argv[++i]);
 
407
            dfLRX = CPLAtofM(argv[++i]);
 
408
            dfLRY = CPLAtofM(argv[++i]);
327
409
        }   
328
410
 
329
411
        else if( EQUAL(argv[i],"-a_srs") && i < argc-1 )
361
443
            i++;
362
444
        }
363
445
 
 
446
        else if( EQUAL(argv[i], "-stats") )
 
447
        {
 
448
            bStats = TRUE;
 
449
            bApproxStats = FALSE;
 
450
        }
 
451
        else if( EQUAL(argv[i], "-approx_stats") )
 
452
        {
 
453
            bStats = TRUE;
 
454
            bApproxStats = TRUE;
 
455
        }
 
456
 
364
457
        else if( argv[i][0] == '-' )
365
458
        {
366
459
            printf( "Option %s incomplete, or not recognised.\n\n", 
403
496
        exit( 1 );
404
497
    }
405
498
 
 
499
    if( strcmp(pszDest, "/vsistdout/") == 0)
 
500
    {
 
501
        bQuiet = TRUE;
 
502
        pfnProgress = GDALDummyProgress;
 
503
    }
 
504
 
 
505
    if (!bQuiet && !bFormatExplicitelySet)
 
506
        CheckExtensionConsistency(pszDest, pszFormat);
 
507
 
406
508
/* -------------------------------------------------------------------- */
407
509
/*      Attempt to open source file.                                    */
408
510
/* -------------------------------------------------------------------- */
439
541
        char *pszSubDest = (char *) CPLMalloc(strlen(pszDest)+32);
440
542
        int i;
441
543
        int bOldSubCall = bSubCall;
442
 
        
443
 
        argv[iDstFileArg] = pszSubDest;
 
544
        char** papszDupArgv = CSLDuplicate(argv);
 
545
        int nRet = 0;
 
546
 
 
547
        CPLFree(papszDupArgv[iDstFileArg]);
 
548
        papszDupArgv[iDstFileArg] = pszSubDest;
444
549
        bSubCall = TRUE;
445
550
        for( i = 0; papszSubdatasets[i] != NULL; i += 2 )
446
551
        {
447
 
            argv[iSrcFileArg] = strstr(papszSubdatasets[i],"=")+1;
 
552
            CPLFree(papszDupArgv[iSrcFileArg]);
 
553
            papszDupArgv[iSrcFileArg] = CPLStrdup(strstr(papszSubdatasets[i],"=")+1);
448
554
            sprintf( pszSubDest, "%s%d", pszDest, i/2 + 1 );
449
 
            if( ProxyMain( argc, argv ) != 0 )
 
555
            nRet = ProxyMain( argc, papszDupArgv );
 
556
            if (nRet != 0)
450
557
                break;
451
558
        }
 
559
        CSLDestroy(papszDupArgv);
452
560
        
453
561
        bSubCall = bOldSubCall;
454
 
        CPLFree( pszSubDest );
 
562
        CSLDestroy(argv);
455
563
 
456
564
        GDALClose( hDataset );
457
565
 
460
568
            GDALDumpOpenDatasets( stderr );
461
569
            GDALDestroyDriverManager();
462
570
        }
463
 
        return 1;
 
571
        return nRet;
464
572
    }
465
573
 
466
574
/* -------------------------------------------------------------------- */
499
607
    {
500
608
        for( i = 0; i < nBandCount; i++ )
501
609
        {
502
 
            if( panBandList[i] < 1 || panBandList[i] > GDALGetRasterCount(hDataset) )
 
610
            if( ABS(panBandList[i]) > GDALGetRasterCount(hDataset) )
503
611
            {
504
612
                fprintf( stderr, 
505
613
                         "Band %d requested, but only bands 1 to %d available.\n",
506
 
                         panBandList[i], GDALGetRasterCount(hDataset) );
 
614
                         ABS(panBandList[i]), GDALGetRasterCount(hDataset) );
507
615
                GDALDestroyDriverManager();
508
616
                exit( 2 );
509
617
            }
626
734
/*      this entire program to use virtual datasets to construct a      */
627
735
/*      virtual input source to copy from.                              */
628
736
/* -------------------------------------------------------------------- */
 
737
 
 
738
 
 
739
    int bSpatialArrangementPreserved = (
 
740
           anSrcWin[0] == 0 && anSrcWin[1] == 0
 
741
        && anSrcWin[2] == GDALGetRasterXSize(hDataset)
 
742
        && anSrcWin[3] == GDALGetRasterYSize(hDataset)
 
743
        && pszOXSize == NULL && pszOYSize == NULL );
 
744
 
629
745
    if( eOutputType == GDT_Unknown 
630
746
        && !bScale && !bUnscale
631
747
        && CSLCount(papszMetadataOptions) == 0 && bDefBands 
632
 
        && anSrcWin[0] == 0 && anSrcWin[1] == 0 
633
 
        && anSrcWin[2] == GDALGetRasterXSize(hDataset)
634
 
        && anSrcWin[3] == GDALGetRasterYSize(hDataset) 
635
 
        && pszOXSize == NULL && pszOYSize == NULL 
 
748
        && eMaskMode == MASK_AUTO
 
749
        && bSpatialArrangementPreserved
636
750
        && nGCPCount == 0 && !bGotBounds
637
 
        && pszOutputSRS == NULL && !bSetNoData
638
 
        && nRGBExpand == 0)
 
751
        && pszOutputSRS == NULL && !bSetNoData && !bUnsetNoData
 
752
        && nRGBExpand == 0 && !bStats )
639
753
    {
640
754
        
641
755
        hOutDS = GDALCreateCopy( hDriver, pszDest, hDataset, 
672
786
    else
673
787
    {
674
788
        nOXSize = (int) ((pszOXSize[strlen(pszOXSize)-1]=='%' 
675
 
                          ? atof(pszOXSize)/100*anSrcWin[2] : atoi(pszOXSize)));
 
789
                          ? CPLAtofM(pszOXSize)/100*anSrcWin[2] : atoi(pszOXSize)));
676
790
        nOYSize = (int) ((pszOYSize[strlen(pszOYSize)-1]=='%' 
677
 
                          ? atof(pszOYSize)/100*anSrcWin[3] : atoi(pszOYSize)));
 
791
                          ? CPLAtofM(pszOYSize)/100*anSrcWin[3] : atoi(pszOYSize)));
678
792
    }
679
793
    
680
794
/* ==================================================================== */
769
883
/* -------------------------------------------------------------------- */
770
884
/*      Transfer generally applicable metadata.                         */
771
885
/* -------------------------------------------------------------------- */
772
 
    poVDS->SetMetadata( ((GDALDataset*)hDataset)->GetMetadata() );
 
886
    char** papszMetadata = CSLDuplicate(((GDALDataset*)hDataset)->GetMetadata());
 
887
    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
        char** papszIter = papszMetadata;
 
892
        while(papszIter && *papszIter)
 
893
        {
 
894
            if (EQUALN(*papszIter, "TIFFTAG_MINSAMPLEVALUE=", 23) ||
 
895
                EQUALN(*papszIter, "TIFFTAG_MAXSAMPLEVALUE=", 23))
 
896
            {
 
897
                CPLFree(*papszIter);
 
898
                memmove(papszIter, papszIter+1, sizeof(char*) * (CSLCount(papszIter+1)+1));
 
899
            }
 
900
            else
 
901
                papszIter++;
 
902
        }
 
903
    }
 
904
    poVDS->SetMetadata( papszMetadata );
 
905
    CSLDestroy( papszMetadata );
773
906
    AttachMetadata( (GDALDatasetH) poVDS, papszMetadataOptions );
774
907
 
 
908
    const char* pszInterleave = GDALGetMetadataItem(hDataset, "INTERLEAVE", "IMAGE_STRUCTURE");
 
909
    if (pszInterleave)
 
910
        poVDS->SetMetadataItem("INTERLEAVE", pszInterleave, "IMAGE_STRUCTURE");
 
911
 
775
912
/* -------------------------------------------------------------------- */
776
913
/*      Transfer metadata that remains valid if the spatial             */
777
914
/*      arrangement of the data is unaltered.                           */
778
915
/* -------------------------------------------------------------------- */
779
 
    if( anSrcWin[0] == 0 && anSrcWin[1] == 0 
780
 
        && anSrcWin[2] == GDALGetRasterXSize(hDataset)
781
 
        && anSrcWin[3] == GDALGetRasterYSize(hDataset) 
782
 
        && pszOXSize == NULL && pszOYSize == NULL )
 
916
    if( bSpatialArrangementPreserved )
783
917
    {
784
918
        char **papszMD;
785
919
 
786
920
        papszMD = ((GDALDataset*)hDataset)->GetMetadata("RPC");
787
921
        if( papszMD != NULL )
788
922
            poVDS->SetMetadata( papszMD, "RPC" );
 
923
 
 
924
        papszMD = ((GDALDataset*)hDataset)->GetMetadata("GEOLOCATION");
 
925
        if( papszMD != NULL )
 
926
            poVDS->SetMetadata( papszMD, "GEOLOCATION" );
789
927
    }
790
928
 
 
929
    int nSrcBandCount = nBandCount;
 
930
 
791
931
    if (nRGBExpand != 0)
792
 
        nBandCount += nRGBExpand - 1;
 
932
    {
 
933
        GDALRasterBand  *poSrcBand;
 
934
        poSrcBand = ((GDALDataset *) 
 
935
                     hDataset)->GetRasterBand(ABS(panBandList[0]));
 
936
        if (panBandList[0] < 0)
 
937
            poSrcBand = poSrcBand->GetMaskBand();
 
938
        GDALColorTable* poColorTable = poSrcBand->GetColorTable();
 
939
        if (poColorTable == NULL)
 
940
        {
 
941
            fprintf(stderr, "Error : band %d has no color table\n", ABS(panBandList[0]));
 
942
            GDALClose( hDataset );
 
943
            CPLFree( panBandList );
 
944
            GDALDestroyDriverManager();
 
945
            CSLDestroy( argv );
 
946
            CSLDestroy( papszCreateOptions );
 
947
            exit( 1 );
 
948
        }
 
949
        
 
950
        /* Check that the color table only contains gray levels */
 
951
        /* when using -expand gray */
 
952
        if (nRGBExpand == 1)
 
953
        {
 
954
            int nColorCount = poColorTable->GetColorEntryCount();
 
955
            int nColor;
 
956
            for( nColor = 0; nColor < nColorCount; nColor++ )
 
957
            {
 
958
                const GDALColorEntry* poEntry = poColorTable->GetColorEntry(nColor);
 
959
                if (poEntry->c1 != poEntry->c2 || poEntry->c1 != poEntry->c2)
 
960
                {
 
961
                    fprintf(stderr, "Warning : color table contains non gray levels colors\n");
 
962
                    break;
 
963
                }
 
964
            }
 
965
        }
 
966
 
 
967
        if (nBandCount == 1)
 
968
            nBandCount = nRGBExpand;
 
969
        else if (nBandCount == 2 && (nRGBExpand == 3 || nRGBExpand == 4))
 
970
            nBandCount = nRGBExpand;
 
971
        else
 
972
        {
 
973
            fprintf(stderr, "Error : invalid use of -expand option.\n");
 
974
            exit( 1 );
 
975
        }
 
976
    }
 
977
 
 
978
    int bFilterOutStatsMetadata =
 
979
        (bScale || bUnscale || !bSpatialArrangementPreserved || nRGBExpand != 0);
793
980
 
794
981
/* ==================================================================== */
795
982
/*      Process all bands.                                              */
799
986
        VRTSourcedRasterBand   *poVRTBand;
800
987
        GDALRasterBand  *poSrcBand;
801
988
        GDALDataType    eBandType;
 
989
        int             nComponent = 0;
802
990
 
803
 
        if (nRGBExpand != 0 && i < nRGBExpand)
 
991
        int nSrcBand;
 
992
        if (nRGBExpand != 0)
804
993
        {
805
 
            poSrcBand = ((GDALDataset *) 
806
 
                     hDataset)->GetRasterBand(panBandList[0]);
807
 
            GDALColorTable* poColorTable = poSrcBand->GetColorTable();
808
 
            if (poColorTable == NULL)
809
 
            {
810
 
                fprintf(stderr, "Error : band %d has no color table\n", panBandList[0]);
811
 
                GDALClose( hDataset );
812
 
                CPLFree( panBandList );
813
 
                GDALDestroyDriverManager();
814
 
                CSLDestroy( argv );
815
 
                CSLDestroy( papszCreateOptions );
816
 
                exit( 1 );
817
 
            }
818
 
            
819
 
            /* Check that the color table only contains gray levels */
820
 
            /* when using -expand gray */
821
 
            if (nRGBExpand == 1)
822
 
            {
823
 
                int nColorCount = poColorTable->GetColorEntryCount();
824
 
                int nColor;
825
 
                for( nColor = 0; nColor < nColorCount; nColor++ )
826
 
                {
827
 
                    const GDALColorEntry* poEntry = poColorTable->GetColorEntry(nColor);
828
 
                    if (poEntry->c1 != poEntry->c2 || poEntry->c1 != poEntry->c2)
829
 
                    {
830
 
                        fprintf(stderr, "Warning : color table contains non gray levels colors\n");
831
 
                        break;
832
 
                    }
833
 
                }
 
994
            if (nSrcBandCount == 2 && nRGBExpand == 4 && i == 3)
 
995
                nSrcBand = panBandList[1];
 
996
            else
 
997
            {
 
998
                nSrcBand = panBandList[0];
 
999
                nComponent = i + 1;
834
1000
            }
835
1001
        }
836
1002
        else
837
 
            poSrcBand = ((GDALDataset *) 
838
 
                        hDataset)->GetRasterBand(panBandList[i]);
 
1003
            nSrcBand = panBandList[i];
 
1004
 
 
1005
        poSrcBand = ((GDALDataset *) hDataset)->GetRasterBand(ABS(nSrcBand));
839
1006
 
840
1007
/* -------------------------------------------------------------------- */
841
1008
/*      Select output data type to match source.                        */
850
1017
/* -------------------------------------------------------------------- */
851
1018
        poVDS->AddBand( eBandType, NULL );
852
1019
        poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand( i+1 );
853
 
            
 
1020
        if (nSrcBand < 0)
 
1021
        {
 
1022
            poVRTBand->AddMaskBandSource(poSrcBand);
 
1023
            continue;
 
1024
        }
 
1025
 
854
1026
/* -------------------------------------------------------------------- */
855
1027
/*      Do we need to collect scaling information?                      */
856
1028
/* -------------------------------------------------------------------- */
894
1066
                                         0, 0, nOXSize, nOYSize,
895
1067
                                         dfOffset, dfScale,
896
1068
                                         VRT_NODATA_UNSET,
897
 
                                         (nRGBExpand != 0 && i < nRGBExpand) ? i + 1 : 0 );
 
1069
                                         nComponent );
898
1070
        }
899
1071
        else
900
1072
            poVRTBand->AddSimpleSource( poSrcBand,
904
1076
 
905
1077
/* -------------------------------------------------------------------- */
906
1078
/*      In case of color table translate, we only set the color         */
907
 
/*      interpretation other info copied by CopyCommonInfoFrom are      */
 
1079
/*      interpretation other info copied by CopyBandInfo are            */
908
1080
/*      not relevant in RGB expansion.                                  */
909
1081
/* -------------------------------------------------------------------- */
910
1082
        if (nRGBExpand == 1)
921
1093
/* -------------------------------------------------------------------- */
922
1094
        else
923
1095
        {
924
 
            poVRTBand->CopyCommonInfoFrom( poSrcBand );
925
 
 
926
 
            if( bUnscale )
927
 
            {
928
 
                poVRTBand->SetOffset( 0.0 );
929
 
                poVRTBand->SetScale( 1.0 );
930
 
            }
 
1096
            CopyBandInfo( poSrcBand, poVRTBand,
 
1097
                          !bStats && !bFilterOutStatsMetadata,
 
1098
                          !bUnscale,
 
1099
                          !bSetNoData && !bUnsetNoData );
931
1100
        }
932
1101
 
933
1102
/* -------------------------------------------------------------------- */
981
1150
            
982
1151
            poVRTBand->SetNoDataValue( dfVal );
983
1152
        }
 
1153
 
 
1154
        if (eMaskMode == MASK_AUTO &&
 
1155
            (GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) & GMF_PER_DATASET) == 0 &&
 
1156
            (poSrcBand->GetMaskFlags() & (GMF_ALL_VALID | GMF_NODATA)) == 0)
 
1157
        {
 
1158
            if (poVRTBand->CreateMaskBand(poSrcBand->GetMaskFlags()) == CE_None)
 
1159
            {
 
1160
                VRTSourcedRasterBand* hMaskVRTBand =
 
1161
                    (VRTSourcedRasterBand*)poVRTBand->GetMaskBand();
 
1162
                hMaskVRTBand->AddMaskBandSource(poSrcBand,
 
1163
                                        anSrcWin[0], anSrcWin[1],
 
1164
                                        anSrcWin[2], anSrcWin[3],
 
1165
                                        0, 0, nOXSize, nOYSize );
 
1166
            }
 
1167
        }
 
1168
    }
 
1169
 
 
1170
    if (eMaskMode == MASK_USER)
 
1171
    {
 
1172
        GDALRasterBand *poSrcBand =
 
1173
            (GDALRasterBand*)GDALGetRasterBand(hDataset, ABS(nMaskBand));
 
1174
        if (poSrcBand && poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
 
1175
        {
 
1176
            VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
 
1177
                GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
 
1178
            if (nMaskBand > 0)
 
1179
                hMaskVRTBand->AddSimpleSource(poSrcBand,
 
1180
                                        anSrcWin[0], anSrcWin[1],
 
1181
                                        anSrcWin[2], anSrcWin[3],
 
1182
                                        0, 0, nOXSize, nOYSize );
 
1183
            else
 
1184
                hMaskVRTBand->AddMaskBandSource(poSrcBand,
 
1185
                                        anSrcWin[0], anSrcWin[1],
 
1186
                                        anSrcWin[2], anSrcWin[3],
 
1187
                                        0, 0, nOXSize, nOYSize );
 
1188
        }
 
1189
    }
 
1190
    else
 
1191
    if (eMaskMode == MASK_AUTO && nSrcBandCount > 0 &&
 
1192
        GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) == GMF_PER_DATASET)
 
1193
    {
 
1194
        if (poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
 
1195
        {
 
1196
            VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
 
1197
                GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
 
1198
            hMaskVRTBand->AddMaskBandSource((GDALRasterBand*)GDALGetRasterBand(hDataset, 1),
 
1199
                                        anSrcWin[0], anSrcWin[1],
 
1200
                                        anSrcWin[2], anSrcWin[3],
 
1201
                                        0, 0, nOXSize, nOYSize );
 
1202
        }
 
1203
    }
 
1204
 
 
1205
/* -------------------------------------------------------------------- */
 
1206
/*      Compute stats if required.                                      */
 
1207
/* -------------------------------------------------------------------- */
 
1208
    if (bStats)
 
1209
    {
 
1210
        for( i = 0; i < poVDS->GetRasterCount(); i++ )
 
1211
        {
 
1212
            double dfMin, dfMax, dfMean, dfStdDev;
 
1213
            poVDS->GetRasterBand(i+1)->ComputeStatistics( bApproxStats,
 
1214
                    &dfMin, &dfMax, &dfMean, &dfStdDev, GDALDummyProgress, NULL );
 
1215
        }
984
1216
    }
985
1217
 
986
1218
/* -------------------------------------------------------------------- */
991
1223
                             pfnProgress, NULL );
992
1224
    if( hOutDS != NULL )
993
1225
    {
 
1226
        int bHasGotErr = FALSE;
 
1227
        CPLErrorReset();
 
1228
        GDALFlushCache( hOutDS );
 
1229
        if (CPLGetLastErrorType() != CE_None)
 
1230
            bHasGotErr = TRUE;
994
1231
        GDALClose( hOutDS );
 
1232
        if (bHasGotErr)
 
1233
            hOutDS = NULL;
995
1234
    }
996
1235
    
997
1236
    GDALClose( (GDALDatasetH) poVDS );
1062
1301
}
1063
1302
 
1064
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
static void CopyBandInfo( GDALRasterBand * poSrcBand, GDALRasterBand * poDstBand,
 
1311
                          int bCanCopyStatsMetadata, int bCopyScale, int bCopyNoData )
 
1312
 
 
1313
{
 
1314
    int bSuccess;
 
1315
    double dfNoData;
 
1316
 
 
1317
    if (bCanCopyStatsMetadata)
 
1318
    {
 
1319
        poDstBand->SetMetadata( poSrcBand->GetMetadata() );
 
1320
    }
 
1321
    else
 
1322
    {
 
1323
        char** papszMetadata = poSrcBand->GetMetadata();
 
1324
        char** papszMetadataNew = NULL;
 
1325
        for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
 
1326
        {
 
1327
            if (strncmp(papszMetadata[i], "STATISTICS_", 11) != 0)
 
1328
                papszMetadataNew = CSLAddString(papszMetadataNew, papszMetadata[i]);
 
1329
        }
 
1330
        poDstBand->SetMetadata( papszMetadataNew );
 
1331
        CSLDestroy(papszMetadataNew);
 
1332
    }
 
1333
 
 
1334
    poDstBand->SetColorTable( poSrcBand->GetColorTable() );
 
1335
    poDstBand->SetColorInterpretation(poSrcBand->GetColorInterpretation());
 
1336
    if( strlen(poSrcBand->GetDescription()) > 0 )
 
1337
        poDstBand->SetDescription( poSrcBand->GetDescription() );
 
1338
 
 
1339
    if (bCopyNoData)
 
1340
    {
 
1341
        dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
 
1342
        if( bSuccess )
 
1343
            poDstBand->SetNoDataValue( dfNoData );
 
1344
    }
 
1345
 
 
1346
    if (bCopyScale)
 
1347
    {
 
1348
        poDstBand->SetOffset( poSrcBand->GetOffset() );
 
1349
        poDstBand->SetScale( poSrcBand->GetScale() );
 
1350
    }
 
1351
 
 
1352
    poDstBand->SetCategoryNames( poSrcBand->GetCategoryNames() );
 
1353
    if( !EQUAL(poSrcBand->GetUnitType(),"") )
 
1354
        poDstBand->SetUnitType( poSrcBand->GetUnitType() );
 
1355
}
 
1356
 
 
1357
/************************************************************************/
1065
1358
/*                                main()                                */
1066
1359
/************************************************************************/
1067
1360