33
33
#include "gdal_priv.h"
34
34
#include "ogr_spatialref.h"
35
35
#include "vrt/vrtdataset.h"
36
#include "commonutils.h"
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 $");
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;
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" );
65
68
printf( "%s\n\n", GDALVersionInfo( "--version" ) );
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;
196
216
else if( EQUAL(argv[i],"-b") && i < argc-1 )
198
if( atoi(argv[i+1]) < 1 )
218
const char* pszBand = argv[i+1];
220
if (EQUAL(pszBand, "mask"))
222
if (EQUALN(pszBand, "mask,", 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;
231
int nBand = atoi(pszBand);
200
234
printf( "Unrecognizable band number (%s).\n", argv[i+1] );
202
236
GDALDestroyDriverManager();
207
242
panBandList = (int *)
208
243
CPLRealloc(panBandList, sizeof(int) * nBandCount);
209
panBandList[nBandCount-1] = atoi(argv[++i]);
244
panBandList[nBandCount-1] = nBand;
246
panBandList[nBandCount-1] *= -1;
211
248
if( panBandList[nBandCount-1] != nBandCount )
212
249
bDefBands = FALSE;
251
else if( EQUAL(argv[i],"-mask") && i < argc-1 )
253
bParsedMaskArgument = TRUE;
254
const char* pszBand = argv[i+1];
255
if (EQUAL(pszBand, "none"))
257
eMaskMode = MASK_DISABLED;
259
else if (EQUAL(pszBand, "auto"))
261
eMaskMode = MASK_AUTO;
266
if (EQUAL(pszBand, "mask"))
268
if (EQUALN(pszBand, "mask,", 5))
273
int nBand = atoi(pszBand);
276
printf( "Unrecognizable band number (%s).\n", argv[i+1] );
278
GDALDestroyDriverManager();
282
eMaskMode = MASK_USER;
214
289
else if( EQUAL(argv[i],"-not_strict") )
230
305
CPLRealloc( pasGCPs, sizeof(GDAL_GCP) * nGCPCount );
231
306
GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 );
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') )
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]);
246
321
/* should set id and info? */
249
324
else if( EQUAL(argv[i],"-a_nodata") && i < argc - 1 )
252
dfNoDataReal = atof(argv[i+1]);
326
if (EQUAL(argv[i+1], "none"))
333
dfNoDataReal = CPLAtofM(argv[i+1]);
256
338
else if( EQUAL(argv[i],"-a_ullr") && i < argc - 4 )
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]);
263
345
bGotBounds = TRUE;
276
358
if( i < argc-2 && ArgIsNumeric(argv[i+1]) )
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]);
283
365
if( i < argc-2 && bHaveScaleSrc && ArgIsNumeric(argv[i+1]) )
285
dfScaleDstMin = atof(argv[i+1]);
286
dfScaleDstMax = atof(argv[i+2]);
367
dfScaleDstMin = CPLAtofM(argv[i+1]);
368
dfScaleDstMax = CPLAtofM(argv[i+2]);
439
541
char *pszSubDest = (char *) CPLMalloc(strlen(pszDest)+32);
441
543
int bOldSubCall = bSubCall;
443
argv[iDstFileArg] = pszSubDest;
544
char** papszDupArgv = CSLDuplicate(argv);
547
CPLFree(papszDupArgv[iDstFileArg]);
548
papszDupArgv[iDstFileArg] = pszSubDest;
445
550
for( i = 0; papszSubdatasets[i] != NULL; i += 2 )
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 );
559
CSLDestroy(papszDupArgv);
453
561
bSubCall = bOldSubCall;
454
CPLFree( pszSubDest );
456
564
GDALClose( hDataset );
626
734
/* this entire program to use virtual datasets to construct a */
627
735
/* virtual input source to copy from. */
628
736
/* -------------------------------------------------------------------- */
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 );
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
751
&& pszOutputSRS == NULL && !bSetNoData && !bUnsetNoData
752
&& nRGBExpand == 0 && !bStats )
641
755
hOutDS = GDALCreateCopy( hDriver, pszDest, hDataset,
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 )
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)
894
if (EQUALN(*papszIter, "TIFFTAG_MINSAMPLEVALUE=", 23) ||
895
EQUALN(*papszIter, "TIFFTAG_MAXSAMPLEVALUE=", 23))
898
memmove(papszIter, papszIter+1, sizeof(char*) * (CSLCount(papszIter+1)+1));
904
poVDS->SetMetadata( papszMetadata );
905
CSLDestroy( papszMetadata );
773
906
AttachMetadata( (GDALDatasetH) poVDS, papszMetadataOptions );
908
const char* pszInterleave = GDALGetMetadataItem(hDataset, "INTERLEAVE", "IMAGE_STRUCTURE");
910
poVDS->SetMetadataItem("INTERLEAVE", pszInterleave, "IMAGE_STRUCTURE");
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 )
786
920
papszMD = ((GDALDataset*)hDataset)->GetMetadata("RPC");
787
921
if( papszMD != NULL )
788
922
poVDS->SetMetadata( papszMD, "RPC" );
924
papszMD = ((GDALDataset*)hDataset)->GetMetadata("GEOLOCATION");
925
if( papszMD != NULL )
926
poVDS->SetMetadata( papszMD, "GEOLOCATION" );
929
int nSrcBandCount = nBandCount;
791
931
if (nRGBExpand != 0)
792
nBandCount += nRGBExpand - 1;
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)
941
fprintf(stderr, "Error : band %d has no color table\n", ABS(panBandList[0]));
942
GDALClose( hDataset );
943
CPLFree( panBandList );
944
GDALDestroyDriverManager();
946
CSLDestroy( papszCreateOptions );
950
/* Check that the color table only contains gray levels */
951
/* when using -expand gray */
954
int nColorCount = poColorTable->GetColorEntryCount();
956
for( nColor = 0; nColor < nColorCount; nColor++ )
958
const GDALColorEntry* poEntry = poColorTable->GetColorEntry(nColor);
959
if (poEntry->c1 != poEntry->c2 || poEntry->c1 != poEntry->c2)
961
fprintf(stderr, "Warning : color table contains non gray levels colors\n");
968
nBandCount = nRGBExpand;
969
else if (nBandCount == 2 && (nRGBExpand == 3 || nRGBExpand == 4))
970
nBandCount = nRGBExpand;
973
fprintf(stderr, "Error : invalid use of -expand option.\n");
978
int bFilterOutStatsMetadata =
979
(bScale || bUnscale || !bSpatialArrangementPreserved || nRGBExpand != 0);
794
981
/* ==================================================================== */
795
982
/* Process all bands. */
799
986
VRTSourcedRasterBand *poVRTBand;
800
987
GDALRasterBand *poSrcBand;
801
988
GDALDataType eBandType;
803
if (nRGBExpand != 0 && i < nRGBExpand)
805
poSrcBand = ((GDALDataset *)
806
hDataset)->GetRasterBand(panBandList[0]);
807
GDALColorTable* poColorTable = poSrcBand->GetColorTable();
808
if (poColorTable == NULL)
810
fprintf(stderr, "Error : band %d has no color table\n", panBandList[0]);
811
GDALClose( hDataset );
812
CPLFree( panBandList );
813
GDALDestroyDriverManager();
815
CSLDestroy( papszCreateOptions );
819
/* Check that the color table only contains gray levels */
820
/* when using -expand gray */
823
int nColorCount = poColorTable->GetColorEntryCount();
825
for( nColor = 0; nColor < nColorCount; nColor++ )
827
const GDALColorEntry* poEntry = poColorTable->GetColorEntry(nColor);
828
if (poEntry->c1 != poEntry->c2 || poEntry->c1 != poEntry->c2)
830
fprintf(stderr, "Warning : color table contains non gray levels colors\n");
994
if (nSrcBandCount == 2 && nRGBExpand == 4 && i == 3)
995
nSrcBand = panBandList[1];
998
nSrcBand = panBandList[0];
837
poSrcBand = ((GDALDataset *)
838
hDataset)->GetRasterBand(panBandList[i]);
1003
nSrcBand = panBandList[i];
1005
poSrcBand = ((GDALDataset *) hDataset)->GetRasterBand(ABS(nSrcBand));
840
1007
/* -------------------------------------------------------------------- */
841
1008
/* Select output data type to match source. */
982
1151
poVRTBand->SetNoDataValue( dfVal );
1154
if (eMaskMode == MASK_AUTO &&
1155
(GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) & GMF_PER_DATASET) == 0 &&
1156
(poSrcBand->GetMaskFlags() & (GMF_ALL_VALID | GMF_NODATA)) == 0)
1158
if (poVRTBand->CreateMaskBand(poSrcBand->GetMaskFlags()) == CE_None)
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 );
1170
if (eMaskMode == MASK_USER)
1172
GDALRasterBand *poSrcBand =
1173
(GDALRasterBand*)GDALGetRasterBand(hDataset, ABS(nMaskBand));
1174
if (poSrcBand && poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
1176
VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
1177
GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
1179
hMaskVRTBand->AddSimpleSource(poSrcBand,
1180
anSrcWin[0], anSrcWin[1],
1181
anSrcWin[2], anSrcWin[3],
1182
0, 0, nOXSize, nOYSize );
1184
hMaskVRTBand->AddMaskBandSource(poSrcBand,
1185
anSrcWin[0], anSrcWin[1],
1186
anSrcWin[2], anSrcWin[3],
1187
0, 0, nOXSize, nOYSize );
1191
if (eMaskMode == MASK_AUTO && nSrcBandCount > 0 &&
1192
GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) == GMF_PER_DATASET)
1194
if (poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
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 );
1205
/* -------------------------------------------------------------------- */
1206
/* Compute stats if required. */
1207
/* -------------------------------------------------------------------- */
1210
for( i = 0; i < poVDS->GetRasterCount(); i++ )
1212
double dfMin, dfMax, dfMean, dfStdDev;
1213
poVDS->GetRasterBand(i+1)->ComputeStatistics( bApproxStats,
1214
&dfMin, &dfMax, &dfMean, &dfStdDev, GDALDummyProgress, NULL );
986
1218
/* -------------------------------------------------------------------- */
1064
1303
/************************************************************************/
1304
/* CopyBandInfo() */
1305
/************************************************************************/
1307
/* A bit of a clone of VRTRasterBand::CopyCommonInfoFrom(), but we need */
1308
/* more and more custom behaviour in the context of gdal_translate ... */
1310
static void CopyBandInfo( GDALRasterBand * poSrcBand, GDALRasterBand * poDstBand,
1311
int bCanCopyStatsMetadata, int bCopyScale, int bCopyNoData )
1317
if (bCanCopyStatsMetadata)
1319
poDstBand->SetMetadata( poSrcBand->GetMetadata() );
1323
char** papszMetadata = poSrcBand->GetMetadata();
1324
char** papszMetadataNew = NULL;
1325
for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
1327
if (strncmp(papszMetadata[i], "STATISTICS_", 11) != 0)
1328
papszMetadataNew = CSLAddString(papszMetadataNew, papszMetadata[i]);
1330
poDstBand->SetMetadata( papszMetadataNew );
1331
CSLDestroy(papszMetadataNew);
1334
poDstBand->SetColorTable( poSrcBand->GetColorTable() );
1335
poDstBand->SetColorInterpretation(poSrcBand->GetColorInterpretation());
1336
if( strlen(poSrcBand->GetDescription()) > 0 )
1337
poDstBand->SetDescription( poSrcBand->GetDescription() );
1341
dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
1343
poDstBand->SetNoDataValue( dfNoData );
1348
poDstBand->SetOffset( poSrcBand->GetOffset() );
1349
poDstBand->SetScale( poSrcBand->GetScale() );
1352
poDstBand->SetCategoryNames( poSrcBand->GetCategoryNames() );
1353
if( !EQUAL(poSrcBand->GetUnitType(),"") )
1354
poDstBand->SetUnitType( poSrcBand->GetUnitType() );
1357
/************************************************************************/
1066
1359
/************************************************************************/