static void* GDALCreateSimilarTPSTransformer( void *hTransformArg, double dfRatioX, double dfRatioY ) { VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarTPSTransformer", NULL ); TPSTransformInfo *psInfo = (TPSTransformInfo *) hTransformArg; if( dfRatioX == 1.0 && dfRatioY == 1.0 ) { /* We can just use a ref count, since using the source transformation */ /* is thread-safe */ CPLAtomicInc(&(psInfo->nRefCount)); } else { GDAL_GCP *pasGCPList = GDALDuplicateGCPs( psInfo->nGCPCount, psInfo->pasGCPList ); for(int i=0;i<psInfo->nGCPCount;i++) { pasGCPList[i].dfGCPPixel /= dfRatioX; pasGCPList[i].dfGCPLine /= dfRatioY; } psInfo = (TPSTransformInfo *) GDALCreateTPSTransformer( psInfo->nGCPCount, pasGCPList, psInfo->bReversed ); GDALDeinitGCPs( psInfo->nGCPCount, pasGCPList ); CPLFree( pasGCPList ); } return psInfo; }
CPLErr GDALPamDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList, const char *pszGCPProjection ) { PamInitialize(); if( psPam ) { CPLFree( psPam->pszGCPProjection ); if( psPam->nGCPCount > 0 ) { GDALDeinitGCPs( psPam->nGCPCount, psPam->pasGCPList ); CPLFree( psPam->pasGCPList ); } psPam->pszGCPProjection = CPLStrdup(pszGCPProjection); psPam->nGCPCount = nGCPCount; psPam->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList ); MarkPamDirty(); return CE_None; } else { return GDALDataset::SetGCPs( nGCPCount, pasGCPList, pszGCPProjection ); } }
static void* GDALCreateSimilarGCPTransformer( void *hTransformArg, double dfRatioX, double dfRatioY ) { int i = 0; GDAL_GCP *pasGCPList = NULL; GCPTransformInfo *psInfo = (GCPTransformInfo *) hTransformArg; VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarGCPTransformer", NULL ); if( dfRatioX == 1.0 && dfRatioY == 1.0 ) { /* We can just use a ref count, since using the source transformation */ /* is thread-safe */ CPLAtomicInc(&(psInfo->nRefCount)); } else { pasGCPList = GDALDuplicateGCPs( psInfo->nGCPCount, psInfo->pasGCPList ); for(i=0;i<psInfo->nGCPCount;i++) { pasGCPList[i].dfGCPPixel /= dfRatioX; pasGCPList[i].dfGCPLine /= dfRatioY; } /* As remove_outliers modifies the provided GCPs we don't need to reapply it */ psInfo = (GCPTransformInfo *) GDALCreateGCPTransformer( psInfo->nGCPCount, pasGCPList, psInfo->nOrder, psInfo->bReversed ); GDALDeinitGCPs( psInfo->nGCPCount, pasGCPList ); CPLFree( pasGCPList ); } return psInfo; }
void *GDALCreateTPSTransformer( int nGCPCount, const GDAL_GCP *pasGCPList, int bReversed ) { TPSTransformInfo *psInfo; int iGCP; /* -------------------------------------------------------------------- */ /* Allocate transform info. */ /* -------------------------------------------------------------------- */ psInfo = (TPSTransformInfo *) CPLCalloc(sizeof(TPSTransformInfo),1); psInfo->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList ); psInfo->nGCPCount = nGCPCount; psInfo->bReversed = bReversed; psInfo->poForward = new VizGeorefSpline2D( 2 ); psInfo->poReverse = new VizGeorefSpline2D( 2 ); strcpy( psInfo->sTI.szSignature, "GTI" ); psInfo->sTI.pszClassName = "GDALTPSTransformer"; psInfo->sTI.pfnTransform = GDALTPSTransform; psInfo->sTI.pfnCleanup = GDALDestroyTPSTransformer; psInfo->sTI.pfnSerialize = GDALSerializeTPSTransformer; /* -------------------------------------------------------------------- */ /* Attach all the points to the transformation. */ /* -------------------------------------------------------------------- */ for( iGCP = 0; iGCP < nGCPCount; iGCP++ ) { double afPL[2], afXY[2]; afPL[0] = pasGCPList[iGCP].dfGCPPixel; afPL[1] = pasGCPList[iGCP].dfGCPLine; afXY[0] = pasGCPList[iGCP].dfGCPX; afXY[1] = pasGCPList[iGCP].dfGCPY; if( bReversed ) { psInfo->poReverse->add_point( afPL[0], afPL[1], afXY ); psInfo->poForward->add_point( afXY[0], afXY[1], afPL ); } else { psInfo->poForward->add_point( afPL[0], afPL[1], afXY ); psInfo->poReverse->add_point( afXY[0], afXY[1], afPL ); } } psInfo->poForward->solve(); psInfo->poReverse->solve(); return psInfo; }
void GDALJP2Metadata::SetGCPs( int nCount, const GDAL_GCP *pasGCPsIn ) { if( nGCPCount > 0 ) { GDALDeinitGCPs( nGCPCount, pasGCPList ); CPLFree( pasGCPList ); } nGCPCount = nCount; pasGCPList = GDALDuplicateGCPs(nGCPCount, pasGCPsIn); }
CPLErr MEMDataset::SetGCPs( int nNewCount, const GDAL_GCP *pasNewGCPList, const char *pszGCPProjection ) { GDALDeinitGCPs( nGCPCount, pasGCPs ); CPLFree( pasGCPs ); if( pszGCPProjection == NULL ) osGCPProjection = ""; else osGCPProjection = pszGCPProjection; nGCPCount = nNewCount; pasGCPs = GDALDuplicateGCPs( nGCPCount, pasNewGCPList ); return CE_None; }
const GDAL_GCP *GDALOverviewDataset::GetGCPs() { if( pasGCPList != NULL ) return pasGCPList; const GDAL_GCP* pasGCPsMain = poMainDS->GetGCPs(); if( pasGCPsMain == NULL ) return NULL; nGCPCount = poMainDS->GetGCPCount(); pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPsMain ); for(int i = 0; i < nGCPCount; i++) { pasGCPList[i].dfGCPPixel *= (double)nRasterXSize / poMainDS->GetRasterXSize(); pasGCPList[i].dfGCPLine *= (double)nRasterYSize / poMainDS->GetRasterYSize(); } return pasGCPList; }
CPLErr VRTDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList, const char *pszGCPProjection ) { CPLFree( this->pszGCPProjection ); if( this->nGCPCount > 0 ) { GDALDeinitGCPs( this->nGCPCount, this->pasGCPList ); CPLFree( this->pasGCPList ); } this->pszGCPProjection = CPLStrdup(pszGCPProjection); this->nGCPCount = nGCPCount; this->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList ); this->bNeedsFlush = TRUE; return CE_None; }
const GDAL_GCP *GDALProxyPoolDataset::GetGCPs() { GDALDataset* poUnderlyingDataset = RefUnderlyingDataset(); if (poUnderlyingDataset == NULL) return NULL; if (nGCPCount) { GDALDeinitGCPs( nGCPCount, pasGCPList ); CPLFree( pasGCPList ); pasGCPList = NULL; } const GDAL_GCP* pasUnderlyingGCPList = poUnderlyingDataset->GetGCPs(); nGCPCount = poUnderlyingDataset->GetGCPCount(); if (nGCPCount) pasGCPList = GDALDuplicateGCPs(nGCPCount, pasUnderlyingGCPList ); UnrefUnderlyingDataset(poUnderlyingDataset); return pasGCPList; }
void *GDALCreateGCPTransformerEx( int nGCPCount, const GDAL_GCP *pasGCPList, int nReqOrder, int bReversed, int bRefine, double dfTolerance, int nMinimumGcps) { GCPTransformInfo *psInfo; double *padfGeoX, *padfGeoY, *padfRasterX, *padfRasterY; int *panStatus, iGCP; int nCRSresult; struct Control_Points sPoints; if( nReqOrder == 0 ) { if( nGCPCount >= 10 ) nReqOrder = 2; /*for now we avoid 3rd order since it is unstable*/ else if( nGCPCount >= 6 ) nReqOrder = 2; else nReqOrder = 1; } psInfo = (GCPTransformInfo *) CPLCalloc(sizeof(GCPTransformInfo),1); psInfo->bReversed = bReversed; psInfo->nOrder = nReqOrder; psInfo->bRefine = bRefine; psInfo->dfTolerance = dfTolerance; psInfo->nMinimumGcps = nMinimumGcps; psInfo->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList ); psInfo->nGCPCount = nGCPCount; strcpy( psInfo->sTI.szSignature, "GTI" ); psInfo->sTI.pszClassName = "GDALGCPTransformer"; psInfo->sTI.pfnTransform = GDALGCPTransform; psInfo->sTI.pfnCleanup = GDALDestroyGCPTransformer; psInfo->sTI.pfnSerialize = GDALSerializeGCPTransformer; /* -------------------------------------------------------------------- */ /* Compute the forward and reverse polynomials. */ /* -------------------------------------------------------------------- */ if(bRefine) { nCRSresult = remove_outliers(psInfo); } else { /* -------------------------------------------------------------------- */ /* Allocate and initialize the working points list. */ /* -------------------------------------------------------------------- */ padfGeoX = (double *) CPLCalloc(sizeof(double),nGCPCount); padfGeoY = (double *) CPLCalloc(sizeof(double),nGCPCount); padfRasterX = (double *) CPLCalloc(sizeof(double),nGCPCount); padfRasterY = (double *) CPLCalloc(sizeof(double),nGCPCount); panStatus = (int *) CPLCalloc(sizeof(int),nGCPCount); for( iGCP = 0; iGCP < nGCPCount; iGCP++ ) { panStatus[iGCP] = 1; padfGeoX[iGCP] = pasGCPList[iGCP].dfGCPX; padfGeoY[iGCP] = pasGCPList[iGCP].dfGCPY; padfRasterX[iGCP] = pasGCPList[iGCP].dfGCPPixel; padfRasterY[iGCP] = pasGCPList[iGCP].dfGCPLine; } sPoints.count = nGCPCount; sPoints.e1 = padfRasterX; sPoints.n1 = padfRasterY; sPoints.e2 = padfGeoX; sPoints.n2 = padfGeoY; sPoints.status = panStatus; nCRSresult = CRS_compute_georef_equations( &sPoints, psInfo->adfToGeoX, psInfo->adfToGeoY, psInfo->adfFromGeoX, psInfo->adfFromGeoY, nReqOrder ); CPLFree( padfGeoX ); CPLFree( padfGeoY ); CPLFree( padfRasterX ); CPLFree( padfRasterY ); CPLFree( panStatus ); } if (nCRSresult != 1) { CPLError( CE_Failure, CPLE_AppDefined, "%s", CRS_error_message[-nCRSresult]); GDALDestroyGCPTransformer( psInfo ); return NULL; } else { return psInfo; } }
CPLErr GDALPamDataset::TryLoadAux() { /* -------------------------------------------------------------------- */ /* Initialize PAM. */ /* -------------------------------------------------------------------- */ PamInitialize(); if( psPam == NULL ) return CE_None; /* -------------------------------------------------------------------- */ /* What is the name of the physical file we are referencing? */ /* We allow an override via the psPam->pszPhysicalFile item. */ /* -------------------------------------------------------------------- */ const char *pszPhysicalFile = psPam->osPhysicalFilename; if( strlen(pszPhysicalFile) == 0 && GetDescription() != NULL ) pszPhysicalFile = GetDescription(); if( strlen(pszPhysicalFile) == 0 ) return CE_None; /* -------------------------------------------------------------------- */ /* Try to open .aux file. */ /* -------------------------------------------------------------------- */ GDALDataset *poAuxDS = GDALFindAssociatedAuxFile( pszPhysicalFile, GA_ReadOnly, this ); if( poAuxDS == NULL ) return CE_None; /* -------------------------------------------------------------------- */ /* Do we have an SRS on the aux file? */ /* -------------------------------------------------------------------- */ if( strlen(poAuxDS->GetProjectionRef()) > 0 ) GDALPamDataset::SetProjection( poAuxDS->GetProjectionRef() ); /* -------------------------------------------------------------------- */ /* Geotransform. */ /* -------------------------------------------------------------------- */ if( poAuxDS->GetGeoTransform( psPam->adfGeoTransform ) == CE_None ) psPam->bHaveGeoTransform = TRUE; /* -------------------------------------------------------------------- */ /* GCPs */ /* -------------------------------------------------------------------- */ if( poAuxDS->GetGCPCount() > 0 ) { psPam->nGCPCount = poAuxDS->GetGCPCount(); psPam->pasGCPList = GDALDuplicateGCPs( psPam->nGCPCount, poAuxDS->GetGCPs() ); } /* -------------------------------------------------------------------- */ /* Apply metadata. We likely ought to be merging this in rather */ /* than overwriting everything that was there. */ /* -------------------------------------------------------------------- */ char **papszMD = poAuxDS->GetMetadata(); if( CSLCount(papszMD) > 0 ) { char **papszMerged = CSLMerge( CSLDuplicate(GetMetadata()), papszMD ); GDALPamDataset::SetMetadata( papszMerged ); CSLDestroy( papszMerged ); } papszMD = poAuxDS->GetMetadata("XFORMS"); if( CSLCount(papszMD) > 0 ) { char **papszMerged = CSLMerge( CSLDuplicate(GetMetadata("XFORMS")), papszMD ); GDALPamDataset::SetMetadata( papszMerged, "XFORMS" ); CSLDestroy( papszMerged ); } /* ==================================================================== */ /* Process bands. */ /* ==================================================================== */ int iBand; for( iBand = 0; iBand < poAuxDS->GetRasterCount(); iBand++ ) { if( iBand >= GetRasterCount() ) break; GDALRasterBand *poAuxBand = poAuxDS->GetRasterBand( iBand+1 ); GDALRasterBand *poBand = GetRasterBand( iBand+1 ); papszMD = poAuxBand->GetMetadata(); if( CSLCount(papszMD) > 0 ) { char **papszMerged = CSLMerge( CSLDuplicate(poBand->GetMetadata()), papszMD ); poBand->SetMetadata( papszMerged ); CSLDestroy( papszMerged ); } if( poAuxBand->GetCategoryNames() != NULL ) poBand->SetCategoryNames( poAuxBand->GetCategoryNames() ); if( poAuxBand->GetColorTable() != NULL && poBand->GetColorTable() == NULL ) poBand->SetColorTable( poAuxBand->GetColorTable() ); // histograms? double dfMin, dfMax; int nBuckets, *panHistogram=NULL; if( poAuxBand->GetDefaultHistogram( &dfMin, &dfMax, &nBuckets, &panHistogram, FALSE, NULL, NULL ) == CE_None ) { poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogram ); CPLFree( panHistogram ); } // RAT if( poAuxBand->GetDefaultRAT() != NULL ) poBand->SetDefaultRAT( poAuxBand->GetDefaultRAT() ); // NoData int bSuccess = FALSE; double dfNoDataValue = poAuxBand->GetNoDataValue( &bSuccess ); if( bSuccess ) poBand->SetNoDataValue( dfNoDataValue ); } GDALClose( poAuxDS ); /* -------------------------------------------------------------------- */ /* Mark PAM info as clean. */ /* -------------------------------------------------------------------- */ nPamFlags &= ~GPF_DIRTY; return CE_Failure; }
void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList, int bReversed, char** papszOptions ) { TPSTransformInfo *psInfo; int iGCP; /* -------------------------------------------------------------------- */ /* Allocate transform info. */ /* -------------------------------------------------------------------- */ psInfo = (TPSTransformInfo *) CPLCalloc(sizeof(TPSTransformInfo),1); psInfo->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList ); psInfo->nGCPCount = nGCPCount; psInfo->bReversed = bReversed; psInfo->poForward = new VizGeorefSpline2D( 2 ); psInfo->poReverse = new VizGeorefSpline2D( 2 ); strcpy( psInfo->sTI.szSignature, "GTI" ); psInfo->sTI.pszClassName = "GDALTPSTransformer"; psInfo->sTI.pfnTransform = GDALTPSTransform; psInfo->sTI.pfnCleanup = GDALDestroyTPSTransformer; psInfo->sTI.pfnSerialize = GDALSerializeTPSTransformer; /* -------------------------------------------------------------------- */ /* Attach all the points to the transformation. */ /* -------------------------------------------------------------------- */ for( iGCP = 0; iGCP < nGCPCount; iGCP++ ) { double afPL[2], afXY[2]; afPL[0] = pasGCPList[iGCP].dfGCPPixel; afPL[1] = pasGCPList[iGCP].dfGCPLine; afXY[0] = pasGCPList[iGCP].dfGCPX; afXY[1] = pasGCPList[iGCP].dfGCPY; if( bReversed ) { psInfo->poReverse->add_point( afPL[0], afPL[1], afXY ); psInfo->poForward->add_point( afXY[0], afXY[1], afPL ); } else { psInfo->poForward->add_point( afPL[0], afPL[1], afXY ); psInfo->poReverse->add_point( afXY[0], afXY[1], afPL ); } } psInfo->nRefCount = 1; int nThreads = 1; if( nGCPCount > 100 ) { const char* pszWarpThreads = CSLFetchNameValue(papszOptions, "NUM_THREADS"); if (pszWarpThreads == NULL) pszWarpThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "1"); if (EQUAL(pszWarpThreads, "ALL_CPUS")) nThreads = CPLGetNumCPUs(); else nThreads = atoi(pszWarpThreads); } if( nThreads > 1 ) { /* Compute direct and reverse transforms in parallel */ void* hThread = CPLCreateJoinableThread(GDALTPSComputeForwardInThread, psInfo); psInfo->bReverseSolved = psInfo->poReverse->solve() != 0; if( hThread != NULL ) CPLJoinThread(hThread); else psInfo->bForwardSolved = psInfo->poForward->solve() != 0; } else { psInfo->bForwardSolved = psInfo->poForward->solve() != 0; psInfo->bReverseSolved = psInfo->poReverse->solve() != 0; } if( !psInfo->bForwardSolved || !psInfo->bReverseSolved ) { GDALDestroyTPSTransformer(psInfo); return NULL; } return psInfo; }
void GDALJP2AbstractDataset::LoadJP2Metadata(GDALOpenInfo* poOpenInfo, const char* pszOverideFilenameIn) { const char* pszOverideFilename = pszOverideFilenameIn; if( pszOverideFilename == NULL ) pszOverideFilename = poOpenInfo->pszFilename; /* -------------------------------------------------------------------- */ /* Check for georeferencing information. */ /* -------------------------------------------------------------------- */ GDALJP2Metadata oJP2Geo; if( (poOpenInfo->fpL != NULL && pszOverideFilenameIn == NULL && oJP2Geo.ReadAndParse(poOpenInfo->fpL) ) || (!(poOpenInfo->fpL != NULL && pszOverideFilenameIn == NULL) && oJP2Geo.ReadAndParse( pszOverideFilename )) ) { CPLFree(pszProjection); pszProjection = CPLStrdup(oJP2Geo.pszProjection); bGeoTransformValid = oJP2Geo.bHaveGeoTransform; memcpy( adfGeoTransform, oJP2Geo.adfGeoTransform, sizeof(double) * 6 ); nGCPCount = oJP2Geo.nGCPCount; pasGCPList = GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList ); if( oJP2Geo.bPixelIsPoint ) GDALDataset::SetMetadataItem(GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT); if( oJP2Geo.papszRPCMD ) GDALDataset::SetMetadata( oJP2Geo.papszRPCMD, "RPC" ); } /* -------------------------------------------------------------------- */ /* Report XML UUID box in a dedicated metadata domain */ /* -------------------------------------------------------------------- */ if (oJP2Geo.pszXMPMetadata) { char *apszMDList[2]; apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata; apszMDList[1] = NULL; GDALDataset::SetMetadata(apszMDList, "xml:XMP"); } /* -------------------------------------------------------------------- */ /* Do we have any XML boxes we would like to treat as special */ /* domain metadata? (Note: the GDAL multidomain metadata XML box */ /* has been excluded and is dealt a few lines below. */ /* -------------------------------------------------------------------- */ int iBox; for( iBox = 0; oJP2Geo.papszGMLMetadata && oJP2Geo.papszGMLMetadata[iBox] != NULL; iBox++ ) { char *pszName = NULL; const char *pszXML = CPLParseNameValue( oJP2Geo.papszGMLMetadata[iBox], &pszName ); CPLString osDomain; char *apszMDList[2]; osDomain.Printf( "xml:%s", pszName ); apszMDList[0] = (char *) pszXML; apszMDList[1] = NULL; GDALDataset::SetMetadata( apszMDList, osDomain ); CPLFree( pszName ); } /* -------------------------------------------------------------------- */ /* Do we have GDAL metadata? */ /* -------------------------------------------------------------------- */ if( oJP2Geo.pszGDALMultiDomainMetadata != NULL ) { CPLXMLNode* psXMLNode = CPLParseXMLString(oJP2Geo.pszGDALMultiDomainMetadata); if( psXMLNode ) { GDALMultiDomainMetadata oLocalMDMD; oLocalMDMD.XMLInit(psXMLNode, FALSE); char** papszDomainList = oLocalMDMD.GetDomainList(); char** papszIter = papszDomainList; GDALDataset::SetMetadata(oLocalMDMD.GetMetadata()); while( papszIter && *papszIter ) { if( !EQUAL(*papszIter, "") && !EQUAL(*papszIter, "IMAGE_STRUCTURE") ) { if( GDALDataset::GetMetadata(*papszIter) != NULL ) { CPLDebug("GDALJP2", "GDAL metadata overrides metadata in %s domain over metadata read from other boxes", *papszIter); } GDALDataset::SetMetadata(oLocalMDMD.GetMetadata(*papszIter), *papszIter); } papszIter ++; } CPLDestroyXMLNode(psXMLNode); } else CPLErrorReset(); } /* -------------------------------------------------------------------- */ /* Do we have other misc metadata (from resd box for now) ? */ /* -------------------------------------------------------------------- */ if( oJP2Geo.papszMetadata != NULL ) { char **papszMD = CSLDuplicate(GDALDataset::GetMetadata()); papszMD = CSLMerge( papszMD, oJP2Geo.papszMetadata ); GDALDataset::SetMetadata( papszMD ); CSLDestroy( papszMD ); } /* -------------------------------------------------------------------- */ /* Do we have XML IPR ? */ /* -------------------------------------------------------------------- */ if( oJP2Geo.pszXMLIPR != NULL ) { char* apszMD[2] = { NULL, NULL }; apszMD[0] = oJP2Geo.pszXMLIPR; GDALDataset::SetMetadata( apszMD, "xml:IPR" ); } /* -------------------------------------------------------------------- */ /* Check for world file. */ /* -------------------------------------------------------------------- */ if( !bGeoTransformValid ) { bGeoTransformValid |= GDALReadWorldFile2( pszOverideFilename, NULL, adfGeoTransform, poOpenInfo->GetSiblingFiles(), &pszWldFilename ) || GDALReadWorldFile2( pszOverideFilename, ".wld", adfGeoTransform, poOpenInfo->GetSiblingFiles(), &pszWldFilename ); } GDALMDReaderManager mdreadermanager; GDALMDReaderBase* mdreader = mdreadermanager.GetReader(poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles(), MDR_ANY); if(NULL != mdreader) { mdreader->FillMetadata(&(oMDMD)); papszMetadataFiles = mdreader->GetMetadataFiles(); } }
CPLErr ERSDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn, const char *pszGCPProjectionIn ) { /* -------------------------------------------------------------------- */ /* Clean old gcps. */ /* -------------------------------------------------------------------- */ CPLFree( pszGCPProjection ); pszGCPProjection = NULL; if( nGCPCount > 0 ) { GDALDeinitGCPs( nGCPCount, pasGCPList ); CPLFree( pasGCPList ); pasGCPList = NULL; nGCPCount = 0; } /* -------------------------------------------------------------------- */ /* Copy new ones. */ /* -------------------------------------------------------------------- */ nGCPCount = nGCPCountIn; pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPListIn ); pszGCPProjection = CPLStrdup( pszGCPProjectionIn ); /* -------------------------------------------------------------------- */ /* Setup the header contents corresponding to these GCPs. */ /* -------------------------------------------------------------------- */ bHDRDirty = TRUE; poHeader->Set( "RasterInfo.WarpControl.WarpType", "Polynomial" ); if( nGCPCount > 6 ) poHeader->Set( "RasterInfo.WarpControl.WarpOrder", "2" ); else poHeader->Set( "RasterInfo.WarpControl.WarpOrder", "1" ); poHeader->Set( "RasterInfo.WarpControl.WarpSampling", "Nearest" ); /* -------------------------------------------------------------------- */ /* Translate the projection. */ /* -------------------------------------------------------------------- */ OGRSpatialReference oSRS( pszGCPProjection ); char szERSProj[32], szERSDatum[32], szERSUnits[32]; oSRS.exportToERM( szERSProj, szERSDatum, szERSUnits ); poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Datum", CPLString().Printf( "\"%s\"", szERSDatum ) ); poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Projection", CPLString().Printf( "\"%s\"", szERSProj ) ); poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.CoordinateType", CPLString().Printf( "EN" ) ); poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Units", CPLString().Printf( "\"%s\"", szERSUnits ) ); poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Rotation", "0:0:0.0" ); /* -------------------------------------------------------------------- */ /* Translate the GCPs. */ /* -------------------------------------------------------------------- */ CPLString osControlPoints = "{\n"; int iGCP; for( iGCP = 0; iGCP < nGCPCount; iGCP++ ) { CPLString osLine; CPLString osId = pasGCPList[iGCP].pszId; if( strlen(osId) == 0 ) osId.Printf( "%d", iGCP + 1 ); osLine.Printf( "\t\t\t\t\"%s\"\tYes\tYes\t%.6f\t%.6f\t%.15g\t%.15g\t%.15g\n", osId.c_str(), pasGCPList[iGCP].dfGCPPixel, pasGCPList[iGCP].dfGCPLine, pasGCPList[iGCP].dfGCPX, pasGCPList[iGCP].dfGCPY, pasGCPList[iGCP].dfGCPZ ); osControlPoints += osLine; } osControlPoints += "\t\t}"; poHeader->Set( "RasterInfo.WarpControl.ControlPoints", osControlPoints ); return CE_None; }
bool CreateSubRaster( wxGISRasterDatasetSPtr pSrcRasterDataSet, OGREnvelope &Env, const OGRGeometry *pGeom, GDALDriver* pDriver, CPLString &szDstPath, GDALDataType eOutputType, int nBandCount, int *panBandList, double dfOutResX, double dfOutResY, bool bCopyNodata, bool bSkipSourceMetadata, char** papszOptions, ITrackCancel* pTrackCancel ) { GDALDataset* pDset = pSrcRasterDataSet->GetRaster(); if(!pDset) { if(pTrackCancel) pTrackCancel->PutMessage(_("Get raster failed"), -1, enumGISMessageErr); return false; } double adfGeoTransform[6] = { 0, 0, 0, 0, 0, 0 }; CPLErr err = pDset->GetGeoTransform(adfGeoTransform); if(err == CE_Fatal) { if(pTrackCancel) pTrackCancel->PutMessage(_("Get raster failed"), -1, enumGISMessageErr); return false; } if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 ) { if(pTrackCancel) pTrackCancel->PutMessage(_("The geotransform is rotated. This configuration is not supported."), -1, enumGISMessageErr); return false; } int anSrcWin[4] = {0, 0, 0, 0}; anSrcWin[0] = floor ((Env.MinX - adfGeoTransform[0]) / adfGeoTransform[1] + 0.001); anSrcWin[1] = floor ((Env.MaxY - adfGeoTransform[3]) / adfGeoTransform[5] + 0.001); anSrcWin[2] = ceil ((Env.MaxX - Env.MinX) / adfGeoTransform[1]); anSrcWin[3] = ceil ((Env.MinY - Env.MaxY) / adfGeoTransform[5]); if(pTrackCancel) pTrackCancel->PutMessage(wxString::Format(_("Computed source pixel window %d %d %d %d from geographic window."), anSrcWin[0], anSrcWin[1], anSrcWin[2], anSrcWin[3] ), -1, enumGISMessageInfo); if( anSrcWin[0] < 0 || anSrcWin[1] < 0 || anSrcWin[0] + anSrcWin[2] > pSrcRasterDataSet->GetWidth() || anSrcWin[1] + anSrcWin[3] > pSrcRasterDataSet->GetHeight() ) { if(pTrackCancel) pTrackCancel->PutMessage(wxString::Format(_("Computed source pixel window falls outside raster size of %dx%d."), pSrcRasterDataSet->GetWidth(), pSrcRasterDataSet->GetHeight()), -1, enumGISMessageErr); return false; } int nOXSize = 0, nOYSize = 0; if(IsDoubleEquil(dfOutResX, -1) && IsDoubleEquil(dfOutResY, -1)) { nOXSize = anSrcWin[2]; nOYSize = anSrcWin[3]; } else { nOXSize = ceil ((Env.MaxX - Env.MinX) / dfOutResX); nOYSize = ceil ((Env.MinY - Env.MaxY) / (adfGeoTransform[5] < 0 ? dfOutResY * -1 : dfOutResY)); } /* ==================================================================== */ /* Create a virtual dataset. */ /* ==================================================================== */ VRTDataset *poVDS; /* -------------------------------------------------------------------- */ /* Make a virtual clone. */ /* -------------------------------------------------------------------- */ poVDS = (VRTDataset *) VRTCreate( nOXSize, nOYSize ); if( pSrcRasterDataSet->GetSpatialReference() != NULL ) { poVDS->SetProjection( pDset->GetProjectionRef() ); } adfGeoTransform[0] += anSrcWin[0] * adfGeoTransform[1] + anSrcWin[1] * adfGeoTransform[2]; adfGeoTransform[3] += anSrcWin[0] * adfGeoTransform[4] + anSrcWin[1] * adfGeoTransform[5]; adfGeoTransform[1] *= anSrcWin[2] / (double) nOXSize; adfGeoTransform[2] *= anSrcWin[3] / (double) nOYSize; adfGeoTransform[4] *= anSrcWin[2] / (double) nOXSize; adfGeoTransform[5] *= anSrcWin[3] / (double) nOYSize; poVDS->SetGeoTransform( adfGeoTransform ); int nGCPs = pDset->GetGCPCount(); if( nGCPs > 0 ) { GDAL_GCP *pasGCPs = GDALDuplicateGCPs( nGCPs, pDset->GetGCPs() ); for(size_t i = 0; i < nGCPs; ++i ) { pasGCPs[i].dfGCPPixel -= anSrcWin[0]; pasGCPs[i].dfGCPLine -= anSrcWin[1]; pasGCPs[i].dfGCPPixel *= (nOXSize / (double) anSrcWin[2] ); pasGCPs[i].dfGCPLine *= (nOYSize / (double) anSrcWin[3] ); } poVDS->SetGCPs( nGCPs, pasGCPs, pDset->GetGCPProjection() ); GDALDeinitGCPs( nGCPs, pasGCPs ); CPLFree( pasGCPs ); } /* -------------------------------------------------------------------- */ /* Transfer generally applicable metadata. */ /* -------------------------------------------------------------------- */ if(!bSkipSourceMetadata) poVDS->SetMetadata( pDset->GetMetadata() ); /* ==================================================================== */ /* Process all bands. */ /* ==================================================================== */ for(size_t i = 0; i < nBandCount; ++i ) { VRTSourcedRasterBand *poVRTBand; GDALRasterBand *poSrcBand; GDALDataType eBandType; int nComponent = 0; poSrcBand = pDset->GetRasterBand(panBandList[i]); /* -------------------------------------------------------------------- */ /* Select output data type to match source. */ /* -------------------------------------------------------------------- */ if( eOutputType == GDT_Unknown ) eBandType = poSrcBand->GetRasterDataType(); else eBandType = eOutputType; /* -------------------------------------------------------------------- */ /* Create this band. */ /* -------------------------------------------------------------------- */ poVDS->AddBand( eBandType, NULL ); poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand( i + 1 ); /* -------------------------------------------------------------------- */ /* Create a simple data source depending on the */ /* translation type required. */ /* -------------------------------------------------------------------- */ //if( bUnscale || bScale || (nRGBExpand != 0 && i < nRGBExpand) ) //{ // poVRTBand->AddComplexSource( poSrcBand, // anSrcWin[0], anSrcWin[1], // anSrcWin[2], anSrcWin[3], // 0, 0, nOXSize, nOYSize, // dfOffset, dfScale, // VRT_NODATA_UNSET, // nComponent ); //} //else CPLString pszResampling = CSLFetchNameValueDef(papszOptions, "DEST_RESAMPLING", "near"); poVRTBand->AddSimpleSource( poSrcBand, anSrcWin[0], anSrcWin[1], anSrcWin[2], anSrcWin[3], 0, 0, nOXSize, nOYSize, pszResampling ); /* -------------------------------------------------------------------- */ /* copy some other information of interest. */ /* -------------------------------------------------------------------- */ CopyBandInfo( poSrcBand, poVRTBand, bCopyNodata ); /* -------------------------------------------------------------------- */ /* Set a forcable nodata value? */ /* -------------------------------------------------------------------- */ // if( bSetNoData ) // { // double dfVal = dfNoDataReal; // int bClamped = FALSE, bRounded = FALSE; // //#define CLAMP(val,type,minval,maxval) \ // do { if (val < minval) { bClamped = TRUE; val = minval; } \ // else if (val > maxval) { bClamped = TRUE; val = maxval; } \ // else if (val != (type)val) { bRounded = TRUE; val = (type)(val + 0.5); } } \ // while(0) // // switch(eBandType) // { // case GDT_Byte: // CLAMP(dfVal, GByte, 0.0, 255.0); // break; // case GDT_Int16: // CLAMP(dfVal, GInt16, -32768.0, 32767.0); // break; // case GDT_UInt16: // CLAMP(dfVal, GUInt16, 0.0, 65535.0); // break; // case GDT_Int32: // CLAMP(dfVal, GInt32, -2147483648.0, 2147483647.0); // break; // case GDT_UInt32: // CLAMP(dfVal, GUInt32, 0.0, 4294967295.0); // break; // default: // break; // } // // if (bClamped) // { // printf( "for band %d, nodata value has been clamped " // "to %.0f, the original value being out of range.\n", // i + 1, dfVal); // } // else if(bRounded) // { // printf("for band %d, nodata value has been rounded " // "to %.0f, %s being an integer datatype.\n", // i + 1, dfVal, // GDALGetDataTypeName(eBandType)); // } // // poVRTBand->SetNoDataValue( dfVal ); // } //if (eMaskMode == MASK_AUTO && // (GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) & GMF_PER_DATASET) == 0 && // (poSrcBand->GetMaskFlags() & (GMF_ALL_VALID | GMF_NODATA)) == 0) //{ // if (poVRTBand->CreateMaskBand(poSrcBand->GetMaskFlags()) == CE_None) // { // VRTSourcedRasterBand* hMaskVRTBand = // (VRTSourcedRasterBand*)poVRTBand->GetMaskBand(); // hMaskVRTBand->AddMaskBandSource(poSrcBand, // anSrcWin[0], anSrcWin[1], // anSrcWin[2], anSrcWin[3], // 0, 0, nOXSize, nOYSize ); // } //} } //if (eMaskMode == MASK_USER) //{ // GDALRasterBand *poSrcBand = // (GDALRasterBand*)GDALGetRasterBand(hDataset, ABS(nMaskBand)); // if (poSrcBand && poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None) // { // VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*) // GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1)); // if (nMaskBand > 0) // hMaskVRTBand->AddSimpleSource(poSrcBand, // anSrcWin[0], anSrcWin[1], // anSrcWin[2], anSrcWin[3], // 0, 0, nOXSize, nOYSize ); // else // hMaskVRTBand->AddMaskBandSource(poSrcBand, // anSrcWin[0], anSrcWin[1], // anSrcWin[2], anSrcWin[3], // 0, 0, nOXSize, nOYSize ); // } //} //else //if (eMaskMode == MASK_AUTO && nSrcBandCount > 0 && // GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) == GMF_PER_DATASET) //{ // if (poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None) // { // VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*) // GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1)); // hMaskVRTBand->AddMaskBandSource((GDALRasterBand*)GDALGetRasterBand(hDataset, 1), // anSrcWin[0], anSrcWin[1], // anSrcWin[2], anSrcWin[3], // 0, 0, nOXSize, nOYSize ); // } //} /* -------------------------------------------------------------------- */ /* Write to the output file using CopyCreate(). */ /* -------------------------------------------------------------------- */ GDALDataset* pOutDS = pDriver->CreateCopy(szDstPath, poVDS, false, papszOptions, GDALDummyProgress, NULL); //hOutDS = GDALCreateCopy( hDriver, pszDest, (GDALDatasetH) poVDS, bStrict, papszCreateOptions, pfnProgress, NULL ); if( pOutDS ) { CPLErrorReset(); GDALFlushCache( pOutDS ); if (CPLGetLastErrorType() != CE_None) { if(pTrackCancel) pTrackCancel->PutMessage(_("GDALFlushCache failed!"), -1, enumGISMessageErr); } GDALClose( pOutDS ); GDALClose( poVDS ); return true; } else { GDALClose( poVDS ); return false; } //CPLFree( panBandList ); // //CPLFree( pszOutputSRS ); //if( !bSubCall ) //{ // GDALDumpOpenDatasets( stderr ); // GDALDestroyDriverManager(); //} //CSLDestroy( papszCreateOptions ); return true; }
void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList, int bReversed, char** papszOptions ) { TPSTransformInfo *psInfo; int iGCP; /* -------------------------------------------------------------------- */ /* Allocate transform info. */ /* -------------------------------------------------------------------- */ psInfo = (TPSTransformInfo *) CPLCalloc(sizeof(TPSTransformInfo),1); psInfo->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList ); psInfo->nGCPCount = nGCPCount; psInfo->bReversed = bReversed; psInfo->poForward = new VizGeorefSpline2D( 2 ); psInfo->poReverse = new VizGeorefSpline2D( 2 ); memcpy( psInfo->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) ); psInfo->sTI.pszClassName = "GDALTPSTransformer"; psInfo->sTI.pfnTransform = GDALTPSTransform; psInfo->sTI.pfnCleanup = GDALDestroyTPSTransformer; psInfo->sTI.pfnSerialize = GDALSerializeTPSTransformer; psInfo->sTI.pfnCreateSimilar = GDALCreateSimilarTPSTransformer; /* -------------------------------------------------------------------- */ /* Attach all the points to the transformation. */ /* -------------------------------------------------------------------- */ std::map< std::pair<double, double>, int > oMapPixelLineToIdx; std::map< std::pair<double, double>, int > oMapXYToIdx; for( iGCP = 0; iGCP < nGCPCount; iGCP++ ) { double afPL[2], afXY[2]; afPL[0] = pasGCPList[iGCP].dfGCPPixel; afPL[1] = pasGCPList[iGCP].dfGCPLine; afXY[0] = pasGCPList[iGCP].dfGCPX; afXY[1] = pasGCPList[iGCP].dfGCPY; std::map< std::pair<double, double>, int >::iterator oIter; oIter = oMapPixelLineToIdx.find( std::pair<double,double>(afPL[0], afPL[1]) ); if( oIter != oMapPixelLineToIdx.end() ) { if( afXY[0] == pasGCPList[oIter->second].dfGCPX && afXY[1] == pasGCPList[oIter->second].dfGCPY ) { continue; } else { CPLError(CE_Warning, CPLE_AppDefined, "GCP %d and %d have same (pixel,line)=(%f,%f) but different (X,Y): (%f,%f) vs (%f,%f)", iGCP + 1, oIter->second, afPL[0], afPL[1], afXY[0], afXY[1], pasGCPList[oIter->second].dfGCPX, pasGCPList[oIter->second].dfGCPY); } } else { oMapPixelLineToIdx[ std::pair<double,double>(afPL[0], afPL[1]) ] = iGCP; } oIter = oMapXYToIdx.find( std::pair<double,double>(afXY[0], afXY[1]) ); if( oIter != oMapXYToIdx.end() ) { CPLError(CE_Warning, CPLE_AppDefined, "GCP %d and %d have same (x,y)=(%f,%f) but different (pixel,line): (%f,%f) vs (%f,%f)", iGCP + 1, oIter->second, afXY[0], afXY[1], afPL[0], afPL[1], pasGCPList[oIter->second].dfGCPPixel, pasGCPList[oIter->second].dfGCPLine); } else { oMapXYToIdx[ std::pair<double,double>(afXY[0], afXY[1]) ] = iGCP; } bool bOK = true; if( bReversed ) { bOK &= psInfo->poReverse->add_point( afPL[0], afPL[1], afXY ); bOK &= psInfo->poForward->add_point( afXY[0], afXY[1], afPL ); } else { bOK &= psInfo->poForward->add_point( afPL[0], afPL[1], afXY ); bOK &= psInfo->poReverse->add_point( afXY[0], afXY[1], afPL ); } if( !bOK ) { GDALDestroyTPSTransformer(psInfo); return NULL; } } psInfo->nRefCount = 1; int nThreads = 1; if( nGCPCount > 100 ) { const char* pszWarpThreads = CSLFetchNameValue(papszOptions, "NUM_THREADS"); if (pszWarpThreads == NULL) pszWarpThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "1"); if (EQUAL(pszWarpThreads, "ALL_CPUS")) nThreads = CPLGetNumCPUs(); else nThreads = atoi(pszWarpThreads); } if( nThreads > 1 ) { /* Compute direct and reverse transforms in parallel */ CPLJoinableThread* hThread = CPLCreateJoinableThread(GDALTPSComputeForwardInThread, psInfo); psInfo->bReverseSolved = psInfo->poReverse->solve() != 0; if( hThread != NULL ) CPLJoinThread(hThread); else psInfo->bForwardSolved = psInfo->poForward->solve() != 0; } else { psInfo->bForwardSolved = psInfo->poForward->solve() != 0; psInfo->bReverseSolved = psInfo->poReverse->solve() != 0; } if( !psInfo->bForwardSolved || !psInfo->bReverseSolved ) { GDALDestroyTPSTransformer(psInfo); return NULL; } return psInfo; }
static int ProxyMain(int argc, char **argv) { GDALDatasetH hDataset, hOutDS; int i; int nRasterXSize, nRasterYSize; const char *pszSource = NULL, *pszDest = NULL, *pszFormat = "GTiff"; GDALDriverH hDriver; int *panBandList = NULL; /* negative value of panBandList[i] means mask band of ABS(panBandList[i]) */ int nBandCount = 0, bDefBands = TRUE; double adfGeoTransform[6]; GDALDataType eOutputType = GDT_Unknown; int nOXSize = 0, nOYSize = 0; char *pszOXSize = NULL, *pszOYSize = NULL; char **papszCreateOptions = NULL; int anSrcWin[4], bStrict = FALSE; const char *pszProjection; int bScale = FALSE, bHaveScaleSrc = FALSE, bUnscale = FALSE; double dfScaleSrcMin = 0.0, dfScaleSrcMax = 255.0; double dfScaleDstMin = 0.0, dfScaleDstMax = 255.0; double dfULX, dfULY, dfLRX, dfLRY; char **papszMetadataOptions = NULL; char *pszOutputSRS = NULL; int bQuiet = FALSE, bGotBounds = FALSE; GDALProgressFunc pfnProgress = GDALTermProgress; int nGCPCount = 0; GDAL_GCP *pasGCPs = NULL; int iSrcFileArg = -1, iDstFileArg = -1; int bCopySubDatasets = FALSE; double adfULLR[4] = { 0, 0, 0, 0 }; int bSetNoData = FALSE; int bUnsetNoData = FALSE; double dfNoDataReal = 0.0; int nRGBExpand = 0; int bParsedMaskArgument = FALSE; int eMaskMode = MASK_AUTO; int nMaskBand = 0; /* negative value means mask band of ABS(nMaskBand) */ int bStats = FALSE, bApproxStats = FALSE; anSrcWin[0] = 0; anSrcWin[1] = 0; anSrcWin[2] = 0; anSrcWin[3] = 0; dfULX = dfULY = dfLRX = dfLRY = 0.0; /* Check strict compilation and runtime library version as we use C++ API */ if (!GDAL_CHECK_VERSION(argv[0])) exit(1); /* Must process GDAL_SKIP before GDALAllRegister(), but we can't call */ /* GDALGeneralCmdLineProcessor before it needs the drivers to be registered */ /* for the --format or --formats options */ for (i = 1; i < argc; i++) { if (EQUAL(argv[i], "--config") && i + 2 < argc && EQUAL(argv[i + 1], "GDAL_SKIP")) { CPLSetConfigOption(argv[i + 1], argv[i + 2]); i += 2; } } /* -------------------------------------------------------------------- */ /* Register standard GDAL drivers, and process generic GDAL */ /* command options. */ /* -------------------------------------------------------------------- */ GDALAllRegister(); argc = GDALGeneralCmdLineProcessor(argc, &argv, 0); if (argc < 1) exit(-argc); /* -------------------------------------------------------------------- */ /* Handle command line arguments. */ /* -------------------------------------------------------------------- */ for (i = 1; i < argc; i++) { if (EQUAL(argv[i], "--utility_version")) { printf("%s was compiled against GDAL %s and is running against GDAL %s\n", argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME")); return 0; } else if (EQUAL(argv[i], "-of") && i < argc - 1) pszFormat = argv[++i]; else if (EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet")) { bQuiet = TRUE; pfnProgress = GDALDummyProgress; } else if (EQUAL(argv[i], "-ot") && i < argc - 1) { int iType; for (iType = 1; iType < GDT_TypeCount; iType++) { if (GDALGetDataTypeName((GDALDataType)iType) != NULL && EQUAL(GDALGetDataTypeName((GDALDataType)iType), argv[i + 1])) { eOutputType = (GDALDataType) iType; } } if (eOutputType == GDT_Unknown) { printf("Unknown output pixel type: %s\n", argv[i + 1]); Usage(); GDALDestroyDriverManager(); exit(2); } i++; } else if (EQUAL(argv[i], "-b") && i < argc - 1) { const char *pszBand = argv[i + 1]; int bMask = FALSE; if (EQUAL(pszBand, "mask")) pszBand = "mask,1"; if (EQUALN(pszBand, "mask,", 5)) { bMask = TRUE; pszBand += 5; /* If we use tha source mask band as a regular band */ /* don't create a target mask band by default */ if (!bParsedMaskArgument) eMaskMode = MASK_DISABLED; } int nBand = atoi(pszBand); if (nBand < 1) { printf("Unrecognizable band number (%s).\n", argv[i + 1]); Usage(); GDALDestroyDriverManager(); exit(2); } i++; nBandCount++; panBandList = (int*) CPLRealloc(panBandList, sizeof(int) * nBandCount); panBandList[nBandCount - 1] = nBand; if (bMask) panBandList[nBandCount - 1] *= -1; if (panBandList[nBandCount - 1] != nBandCount) bDefBands = FALSE; } else if (EQUAL(argv[i], "-mask") && i < argc - 1) { bParsedMaskArgument = TRUE; const char *pszBand = argv[i + 1]; if (EQUAL(pszBand, "none")) { eMaskMode = MASK_DISABLED; } else if (EQUAL(pszBand, "auto")) { eMaskMode = MASK_AUTO; } else { int bMask = FALSE; if (EQUAL(pszBand, "mask")) pszBand = "mask,1"; if (EQUALN(pszBand, "mask,", 5)) { bMask = TRUE; pszBand += 5; } int nBand = atoi(pszBand); if (nBand < 1) { printf("Unrecognizable band number (%s).\n", argv[i + 1]); Usage(); GDALDestroyDriverManager(); exit(2); } eMaskMode = MASK_USER; nMaskBand = nBand; if (bMask) nMaskBand *= -1; } i++; } else if (EQUAL(argv[i], "-not_strict")) bStrict = FALSE; else if (EQUAL(argv[i], "-strict")) bStrict = TRUE; else if (EQUAL(argv[i], "-sds")) bCopySubDatasets = TRUE; else if (EQUAL(argv[i], "-gcp") && i < argc - 4) { char *endptr = NULL; /* -gcp pixel line easting northing [elev] */ nGCPCount++; pasGCPs = (GDAL_GCP*) CPLRealloc(pasGCPs, sizeof(GDAL_GCP) * nGCPCount); GDALInitGCPs(1, pasGCPs + nGCPCount - 1); pasGCPs[nGCPCount - 1].dfGCPPixel = CPLAtofM(argv[++i]); pasGCPs[nGCPCount - 1].dfGCPLine = CPLAtofM(argv[++i]); pasGCPs[nGCPCount - 1].dfGCPX = CPLAtofM(argv[++i]); pasGCPs[nGCPCount - 1].dfGCPY = CPLAtofM(argv[++i]); if (argv[i + 1] != NULL && (CPLStrtod(argv[i + 1], &endptr) != 0.0 || argv[i + 1][0] == '0')) { /* Check that last argument is really a number and not a filename */ /* looking like a number (see ticket #863) */ if (endptr && *endptr == 0) pasGCPs[nGCPCount - 1].dfGCPZ = CPLAtofM(argv[++i]); } /* should set id and info? */ } else if (EQUAL(argv[i], "-a_nodata") && i < argc - 1) { if (EQUAL(argv[i + 1], "none")) { bUnsetNoData = TRUE; } else { bSetNoData = TRUE; dfNoDataReal = CPLAtofM(argv[i + 1]); } i += 1; } else if (EQUAL(argv[i], "-a_ullr") && i < argc - 4) { adfULLR[0] = CPLAtofM(argv[i + 1]); adfULLR[1] = CPLAtofM(argv[i + 2]); adfULLR[2] = CPLAtofM(argv[i + 3]); adfULLR[3] = CPLAtofM(argv[i + 4]); bGotBounds = TRUE; i += 4; } else if (EQUAL(argv[i], "-co") && i < argc - 1) { papszCreateOptions = CSLAddString(papszCreateOptions, argv[++i]); } else if (EQUAL(argv[i], "-scale")) { bScale = TRUE; if (i < argc - 2 && ArgIsNumeric(argv[i + 1])) { bHaveScaleSrc = TRUE; dfScaleSrcMin = CPLAtofM(argv[i + 1]); dfScaleSrcMax = CPLAtofM(argv[i + 2]); i += 2; } if (i < argc - 2 && bHaveScaleSrc && ArgIsNumeric(argv[i + 1])) { dfScaleDstMin = CPLAtofM(argv[i + 1]); dfScaleDstMax = CPLAtofM(argv[i + 2]); i += 2; } else { dfScaleDstMin = 0.0; dfScaleDstMax = 255.999; } } else if (EQUAL(argv[i], "-unscale")) { bUnscale = TRUE; } else if (EQUAL(argv[i], "-mo") && i < argc - 1) { papszMetadataOptions = CSLAddString(papszMetadataOptions, argv[++i]); } else if (EQUAL(argv[i], "-outsize") && i < argc - 2) { pszOXSize = argv[++i]; pszOYSize = argv[++i]; } else if (EQUAL(argv[i], "-srcwin") && i < argc - 4) { anSrcWin[0] = atoi(argv[++i]); anSrcWin[1] = atoi(argv[++i]); anSrcWin[2] = atoi(argv[++i]); anSrcWin[3] = atoi(argv[++i]); } else if (EQUAL(argv[i], "-projwin") && i < argc - 4) { dfULX = CPLAtofM(argv[++i]); dfULY = CPLAtofM(argv[++i]); dfLRX = CPLAtofM(argv[++i]); dfLRY = CPLAtofM(argv[++i]); } else if (EQUAL(argv[i], "-a_srs") && i < argc - 1) { OGRSpatialReference oOutputSRS; if (oOutputSRS.SetFromUserInput(argv[i + 1]) != OGRERR_NONE) { fprintf(stderr, "Failed to process SRS definition: %s\n", argv[i + 1]); GDALDestroyDriverManager(); exit(1); } oOutputSRS.exportToWkt(&pszOutputSRS); i++; } else if (EQUAL(argv[i], "-expand") && i < argc - 1) { if (EQUAL(argv[i + 1], "gray")) nRGBExpand = 1; else if (EQUAL(argv[i + 1], "rgb")) nRGBExpand = 3; else if (EQUAL(argv[i + 1], "rgba")) nRGBExpand = 4; else { printf("Value %s unsupported. Only gray, rgb or rgba are supported.\n\n", argv[i]); Usage(); GDALDestroyDriverManager(); exit(2); } i++; } else if (EQUAL(argv[i], "-stats")) { bStats = TRUE; bApproxStats = FALSE; } else if (EQUAL(argv[i], "-approx_stats")) { bStats = TRUE; bApproxStats = TRUE; } else if (argv[i][0] == '-') { printf("Option %s incomplete, or not recognised.\n\n", argv[i]); Usage(); GDALDestroyDriverManager(); exit(2); } else if (pszSource == NULL) { iSrcFileArg = i; pszSource = argv[i]; } else if (pszDest == NULL) { pszDest = argv[i]; iDstFileArg = i; } else { printf("Too many command options.\n\n"); Usage(); GDALDestroyDriverManager(); exit(2); } } if (pszDest == NULL) { Usage(); GDALDestroyDriverManager(); exit(10); } if (strcmp(pszSource, pszDest) == 0) { fprintf(stderr, "Source and destination datasets must be different.\n"); GDALDestroyDriverManager(); exit(1); } if (strcmp(pszDest, "/vsistdout/") == 0) { bQuiet = TRUE; pfnProgress = GDALDummyProgress; } /* -------------------------------------------------------------------- */ /* Attempt to open source file. */ /* -------------------------------------------------------------------- */ hDataset = GDALOpenShared(pszSource, GA_ReadOnly); if (hDataset == NULL) { fprintf(stderr, "GDALOpen failed - %d\n%s\n", CPLGetLastErrorNo(), CPLGetLastErrorMsg()); GDALDestroyDriverManager(); exit(1); } /* -------------------------------------------------------------------- */ /* Handle subdatasets. */ /* -------------------------------------------------------------------- */ if (!bCopySubDatasets && CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0 && GDALGetRasterCount(hDataset) == 0) { fprintf(stderr, "Input file contains subdatasets. Please, select one of them for reading.\n"); GDALClose(hDataset); GDALDestroyDriverManager(); exit(1); } if (CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0 && bCopySubDatasets) { char **papszSubdatasets = GDALGetMetadata(hDataset, "SUBDATASETS"); char *pszSubDest = (char*) CPLMalloc(strlen(pszDest) + 32); int i; int bOldSubCall = bSubCall; char **papszDupArgv = CSLDuplicate(argv); int nRet = 0; CPLFree(papszDupArgv[iDstFileArg]); papszDupArgv[iDstFileArg] = pszSubDest; bSubCall = TRUE; for (i = 0; papszSubdatasets[i] != NULL; i += 2) { CPLFree(papszDupArgv[iSrcFileArg]); papszDupArgv[iSrcFileArg] = CPLStrdup(strstr(papszSubdatasets[i], "=") + 1); sprintf(pszSubDest, "%s%d", pszDest, i / 2 + 1); nRet = ProxyMain(argc, papszDupArgv); if (nRet != 0) break; } CSLDestroy(papszDupArgv); bSubCall = bOldSubCall; CSLDestroy(argv); GDALClose(hDataset); if (!bSubCall) { GDALDumpOpenDatasets(stderr); GDALDestroyDriverManager(); } return nRet; } /* -------------------------------------------------------------------- */ /* Collect some information from the source file. */ /* -------------------------------------------------------------------- */ nRasterXSize = GDALGetRasterXSize(hDataset); nRasterYSize = GDALGetRasterYSize(hDataset); if (!bQuiet) printf("Input file size is %d, %d\n", nRasterXSize, nRasterYSize); if (anSrcWin[2] == 0 && anSrcWin[3] == 0) { anSrcWin[2] = nRasterXSize; anSrcWin[3] = nRasterYSize; } /* -------------------------------------------------------------------- */ /* Build band list to translate */ /* -------------------------------------------------------------------- */ if (nBandCount == 0) { nBandCount = GDALGetRasterCount(hDataset); if (nBandCount == 0) { fprintf(stderr, "Input file has no bands, and so cannot be translated.\n"); GDALDestroyDriverManager(); exit(1); } panBandList = (int*) CPLMalloc(sizeof(int) * nBandCount); for (i = 0; i < nBandCount; i++) panBandList[i] = i + 1; } else { for (i = 0; i < nBandCount; i++) { if (ABS(panBandList[i]) > GDALGetRasterCount(hDataset)) { fprintf(stderr, "Band %d requested, but only bands 1 to %d available.\n", ABS(panBandList[i]), GDALGetRasterCount(hDataset)); GDALDestroyDriverManager(); exit(2); } } if (nBandCount != GDALGetRasterCount(hDataset)) bDefBands = FALSE; } /* -------------------------------------------------------------------- */ /* Compute the source window from the projected source window */ /* if the projected coordinates were provided. Note that the */ /* projected coordinates are in ulx, uly, lrx, lry format, */ /* while the anSrcWin is xoff, yoff, xsize, ysize with the */ /* xoff,yoff being the ulx, uly in pixel/line. */ /* -------------------------------------------------------------------- */ if (dfULX != 0.0 || dfULY != 0.0 || dfLRX != 0.0 || dfLRY != 0.0) { double adfGeoTransform[6]; GDALGetGeoTransform(hDataset, adfGeoTransform); if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0) { fprintf(stderr, "The -projwin option was used, but the geotransform is\n" "rotated. This configuration is not supported.\n"); GDALClose(hDataset); CPLFree(panBandList); GDALDestroyDriverManager(); exit(1); } anSrcWin[0] = (int) ((dfULX - adfGeoTransform[0]) / adfGeoTransform[1] + 0.001); anSrcWin[1] = (int) ((dfULY - adfGeoTransform[3]) / adfGeoTransform[5] + 0.001); anSrcWin[2] = (int) ((dfLRX - dfULX) / adfGeoTransform[1] + 0.5); anSrcWin[3] = (int) ((dfLRY - dfULY) / adfGeoTransform[5] + 0.5); if (!bQuiet) fprintf(stdout, "Computed -srcwin %d %d %d %d from projected window.\n", anSrcWin[0], anSrcWin[1], anSrcWin[2], anSrcWin[3]); if (anSrcWin[0] < 0 || anSrcWin[1] < 0 || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hDataset) || anSrcWin[1] + anSrcWin[3] > GDALGetRasterYSize(hDataset)) { fprintf(stderr, "Computed -srcwin falls outside raster size of %dx%d.\n", GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset)); exit(1); } } /* -------------------------------------------------------------------- */ /* Verify source window. */ /* -------------------------------------------------------------------- */ if (anSrcWin[0] < 0 || anSrcWin[1] < 0 || anSrcWin[2] <= 0 || anSrcWin[3] <= 0 || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hDataset) || anSrcWin[1] + anSrcWin[3] > GDALGetRasterYSize(hDataset)) { fprintf(stderr, "-srcwin %d %d %d %d falls outside raster size of %dx%d\n" "or is otherwise illegal.\n", anSrcWin[0], anSrcWin[1], anSrcWin[2], anSrcWin[3], GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset)); exit(1); } /* -------------------------------------------------------------------- */ /* Find the output driver. */ /* -------------------------------------------------------------------- */ hDriver = GDALGetDriverByName(pszFormat); if (hDriver == NULL) { int iDr; printf("Output driver `%s' not recognised.\n", pszFormat); printf("The following format drivers are configured and support output:\n"); for (iDr = 0; iDr < GDALGetDriverCount(); iDr++) { GDALDriverH hDriver = GDALGetDriver(iDr); if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL) != NULL || GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY, NULL) != NULL) { printf(" %s: %s\n", GDALGetDriverShortName(hDriver), GDALGetDriverLongName(hDriver)); } } printf("\n"); Usage(); GDALClose(hDataset); CPLFree(panBandList); GDALDestroyDriverManager(); CSLDestroy(argv); CSLDestroy(papszCreateOptions); exit(1); } /* -------------------------------------------------------------------- */ /* The short form is to CreateCopy(). We use this if the input */ /* matches the whole dataset. Eventually we should rewrite */ /* this entire program to use virtual datasets to construct a */ /* virtual input source to copy from. */ /* -------------------------------------------------------------------- */ int bSpatialArrangementPreserved = ( anSrcWin[0] == 0 && anSrcWin[1] == 0 && anSrcWin[2] == GDALGetRasterXSize(hDataset) && anSrcWin[3] == GDALGetRasterYSize(hDataset) && pszOXSize == NULL && pszOYSize == NULL); if (eOutputType == GDT_Unknown && !bScale && !bUnscale && CSLCount(papszMetadataOptions) == 0 && bDefBands && eMaskMode == MASK_AUTO && bSpatialArrangementPreserved && nGCPCount == 0 && !bGotBounds && pszOutputSRS == NULL && !bSetNoData && !bUnsetNoData && nRGBExpand == 0 && !bStats) { hOutDS = GDALCreateCopy(hDriver, pszDest, hDataset, bStrict, papszCreateOptions, pfnProgress, NULL); if (hOutDS != NULL) GDALClose(hOutDS); GDALClose(hDataset); CPLFree(panBandList); if (!bSubCall) { GDALDumpOpenDatasets(stderr); GDALDestroyDriverManager(); } CSLDestroy(argv); CSLDestroy(papszCreateOptions); return hOutDS == NULL; } /* -------------------------------------------------------------------- */ /* Establish some parameters. */ /* -------------------------------------------------------------------- */ if (pszOXSize == NULL) { nOXSize = anSrcWin[2]; nOYSize = anSrcWin[3]; } else { nOXSize = (int) ((pszOXSize[strlen(pszOXSize) - 1] == '%' ? CPLAtofM(pszOXSize) / 100 * anSrcWin[2] : atoi(pszOXSize))); nOYSize = (int) ((pszOYSize[strlen(pszOYSize) - 1] == '%' ? CPLAtofM(pszOYSize) / 100 * anSrcWin[3] : atoi(pszOYSize))); } /* ==================================================================== */ /* Create a virtual dataset. */ /* ==================================================================== */ VRTDataset *poVDS; /* -------------------------------------------------------------------- */ /* Make a virtual clone. */ /* -------------------------------------------------------------------- */ poVDS = (VRTDataset*) VRTCreate(nOXSize, nOYSize); if (nGCPCount == 0) { if (pszOutputSRS != NULL) { poVDS->SetProjection(pszOutputSRS); } else { pszProjection = GDALGetProjectionRef(hDataset); if (pszProjection != NULL && strlen(pszProjection) > 0) poVDS->SetProjection(pszProjection); } } if (bGotBounds) { adfGeoTransform[0] = adfULLR[0]; adfGeoTransform[1] = (adfULLR[2] - adfULLR[0]) / nOXSize; adfGeoTransform[2] = 0.0; adfGeoTransform[3] = adfULLR[1]; adfGeoTransform[4] = 0.0; adfGeoTransform[5] = (adfULLR[3] - adfULLR[1]) / nOYSize; poVDS->SetGeoTransform(adfGeoTransform); } else if (GDALGetGeoTransform(hDataset, adfGeoTransform) == CE_None && nGCPCount == 0) { adfGeoTransform[0] += anSrcWin[0] * adfGeoTransform[1] + anSrcWin[1] * adfGeoTransform[2]; adfGeoTransform[3] += anSrcWin[0] * adfGeoTransform[4] + anSrcWin[1] * adfGeoTransform[5]; adfGeoTransform[1] *= anSrcWin[2] / (double) nOXSize; adfGeoTransform[2] *= anSrcWin[3] / (double) nOYSize; adfGeoTransform[4] *= anSrcWin[2] / (double) nOXSize; adfGeoTransform[5] *= anSrcWin[3] / (double) nOYSize; poVDS->SetGeoTransform(adfGeoTransform); } if (nGCPCount != 0) { const char *pszGCPProjection = pszOutputSRS; if (pszGCPProjection == NULL) pszGCPProjection = GDALGetGCPProjection(hDataset); if (pszGCPProjection == NULL) pszGCPProjection = ""; poVDS->SetGCPs(nGCPCount, pasGCPs, pszGCPProjection); GDALDeinitGCPs(nGCPCount, pasGCPs); CPLFree(pasGCPs); } else if (GDALGetGCPCount(hDataset) > 0) { GDAL_GCP *pasGCPs; int nGCPs = GDALGetGCPCount(hDataset); pasGCPs = GDALDuplicateGCPs(nGCPs, GDALGetGCPs(hDataset)); for (i = 0; i < nGCPs; i++) { pasGCPs[i].dfGCPPixel -= anSrcWin[0]; pasGCPs[i].dfGCPLine -= anSrcWin[1]; pasGCPs[i].dfGCPPixel *= (nOXSize / (double) anSrcWin[2]); pasGCPs[i].dfGCPLine *= (nOYSize / (double) anSrcWin[3]); } poVDS->SetGCPs(nGCPs, pasGCPs, GDALGetGCPProjection(hDataset)); GDALDeinitGCPs(nGCPs, pasGCPs); CPLFree(pasGCPs); } /* -------------------------------------------------------------------- */ /* Transfer generally applicable metadata. */ /* -------------------------------------------------------------------- */ poVDS->SetMetadata(((GDALDataset*)hDataset)->GetMetadata()); AttachMetadata((GDALDatasetH) poVDS, papszMetadataOptions); const char *pszInterleave = GDALGetMetadataItem(hDataset, "INTERLEAVE", "IMAGE_STRUCTURE"); if (pszInterleave) poVDS->SetMetadataItem("INTERLEAVE", pszInterleave, "IMAGE_STRUCTURE"); /* -------------------------------------------------------------------- */ /* Transfer metadata that remains valid if the spatial */ /* arrangement of the data is unaltered. */ /* -------------------------------------------------------------------- */ if (bSpatialArrangementPreserved) { char **papszMD; papszMD = ((GDALDataset*)hDataset)->GetMetadata("RPC"); if (papszMD != NULL) poVDS->SetMetadata(papszMD, "RPC"); papszMD = ((GDALDataset*)hDataset)->GetMetadata("GEOLOCATION"); if (papszMD != NULL) poVDS->SetMetadata(papszMD, "GEOLOCATION"); } int nSrcBandCount = nBandCount; if (nRGBExpand != 0) { GDALRasterBand *poSrcBand; poSrcBand = ((GDALDataset*) hDataset)->GetRasterBand(ABS(panBandList[0])); if (panBandList[0] < 0) poSrcBand = poSrcBand->GetMaskBand(); GDALColorTable *poColorTable = poSrcBand->GetColorTable(); if (poColorTable == NULL) { fprintf(stderr, "Error : band %d has no color table\n", ABS(panBandList[0])); GDALClose(hDataset); CPLFree(panBandList); GDALDestroyDriverManager(); CSLDestroy(argv); CSLDestroy(papszCreateOptions); exit(1); } /* Check that the color table only contains gray levels */ /* when using -expand gray */ if (nRGBExpand == 1) { int nColorCount = poColorTable->GetColorEntryCount(); int nColor; for (nColor = 0; nColor < nColorCount; nColor++) { const GDALColorEntry *poEntry = poColorTable->GetColorEntry(nColor); if (poEntry->c1 != poEntry->c2 || poEntry->c1 != poEntry->c2) { fprintf(stderr, "Warning : color table contains non gray levels colors\n"); break; } } } if (nBandCount == 1) nBandCount = nRGBExpand; else if (nBandCount == 2 && (nRGBExpand == 3 || nRGBExpand == 4)) nBandCount = nRGBExpand; else { fprintf(stderr, "Error : invalid use of -expand option.\n"); exit(1); } } int bFilterOutStatsMetadata = (bScale || bUnscale || !bSpatialArrangementPreserved || nRGBExpand != 0); /* ==================================================================== */ /* Process all bands. */ /* ==================================================================== */ for (i = 0; i < nBandCount; i++) { VRTSourcedRasterBand *poVRTBand; GDALRasterBand *poSrcBand; GDALDataType eBandType; int nComponent = 0; int nSrcBand; if (nRGBExpand != 0) { if (nSrcBandCount == 2 && nRGBExpand == 4 && i == 3) nSrcBand = panBandList[1]; else { nSrcBand = panBandList[0]; nComponent = i + 1; } } else nSrcBand = panBandList[i]; poSrcBand = ((GDALDataset*) hDataset)->GetRasterBand(ABS(nSrcBand)); /* -------------------------------------------------------------------- */ /* Select output data type to match source. */ /* -------------------------------------------------------------------- */ if (eOutputType == GDT_Unknown) eBandType = poSrcBand->GetRasterDataType(); else eBandType = eOutputType; /* -------------------------------------------------------------------- */ /* Create this band. */ /* -------------------------------------------------------------------- */ poVDS->AddBand(eBandType, NULL); poVRTBand = (VRTSourcedRasterBand*) poVDS->GetRasterBand(i + 1); if (nSrcBand < 0) { poVRTBand->AddMaskBandSource(poSrcBand); continue; } /* -------------------------------------------------------------------- */ /* Do we need to collect scaling information? */ /* -------------------------------------------------------------------- */ double dfScale = 1.0, dfOffset = 0.0; if (bScale && !bHaveScaleSrc) { double adfCMinMax[2]; GDALComputeRasterMinMax(poSrcBand, TRUE, adfCMinMax); dfScaleSrcMin = adfCMinMax[0]; dfScaleSrcMax = adfCMinMax[1]; } if (bScale) { if (dfScaleSrcMax == dfScaleSrcMin) dfScaleSrcMax += 0.1; if (dfScaleDstMax == dfScaleDstMin) dfScaleDstMax += 0.1; dfScale = (dfScaleDstMax - dfScaleDstMin) / (dfScaleSrcMax - dfScaleSrcMin); dfOffset = -1 * dfScaleSrcMin * dfScale + dfScaleDstMin; } if (bUnscale) { dfScale = poSrcBand->GetScale(); dfOffset = poSrcBand->GetOffset(); } /* -------------------------------------------------------------------- */ /* Create a simple or complex data source depending on the */ /* translation type required. */ /* -------------------------------------------------------------------- */ if (bUnscale || bScale || (nRGBExpand != 0 && i < nRGBExpand)) { poVRTBand->AddComplexSource(poSrcBand, anSrcWin[0], anSrcWin[1], anSrcWin[2], anSrcWin[3], 0, 0, nOXSize, nOYSize, dfOffset, dfScale, VRT_NODATA_UNSET, nComponent); } else poVRTBand->AddSimpleSource(poSrcBand, anSrcWin[0], anSrcWin[1], anSrcWin[2], anSrcWin[3], 0, 0, nOXSize, nOYSize); /* -------------------------------------------------------------------- */ /* In case of color table translate, we only set the color */ /* interpretation other info copied by CopyBandInfo are */ /* not relevant in RGB expansion. */ /* -------------------------------------------------------------------- */ if (nRGBExpand == 1) { poVRTBand->SetColorInterpretation(GCI_GrayIndex); } else if (nRGBExpand != 0 && i < nRGBExpand) { poVRTBand->SetColorInterpretation((GDALColorInterp) (GCI_RedBand + i)); } /* -------------------------------------------------------------------- */ /* copy over some other information of interest. */ /* -------------------------------------------------------------------- */ else { CopyBandInfo(poSrcBand, poVRTBand, !bStats && !bFilterOutStatsMetadata, !bUnscale, !bSetNoData && !bUnsetNoData); } /* -------------------------------------------------------------------- */ /* Set a forcable nodata value? */ /* -------------------------------------------------------------------- */ if (bSetNoData) { double dfVal = dfNoDataReal; int bClamped = FALSE, bRounded = FALSE; #define CLAMP(val, type, minval, maxval) \ do { if (val < minval) { bClamped = TRUE; val = minval; \ } \ else if (val > maxval) { bClamped = TRUE; val = maxval; } \ else if (val != (type)val) { bRounded = TRUE; val = (type)(val + 0.5); } \ } \ while (0) switch (eBandType) { case GDT_Byte: CLAMP(dfVal, GByte, 0.0, 255.0); break; case GDT_Int16: CLAMP(dfVal, GInt16, -32768.0, 32767.0); break; case GDT_UInt16: CLAMP(dfVal, GUInt16, 0.0, 65535.0); break; case GDT_Int32: CLAMP(dfVal, GInt32, -2147483648.0, 2147483647.0); break; case GDT_UInt32: CLAMP(dfVal, GUInt32, 0.0, 4294967295.0); break; default: break; } if (bClamped) { printf("for band %d, nodata value has been clamped " "to %.0f, the original value being out of range.\n", i + 1, dfVal); } else if (bRounded) { printf("for band %d, nodata value has been rounded " "to %.0f, %s being an integer datatype.\n", i + 1, dfVal, GDALGetDataTypeName(eBandType)); } poVRTBand->SetNoDataValue(dfVal); } if (eMaskMode == MASK_AUTO && (GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) & GMF_PER_DATASET) == 0 && (poSrcBand->GetMaskFlags() & (GMF_ALL_VALID | GMF_NODATA)) == 0) { if (poVRTBand->CreateMaskBand(poSrcBand->GetMaskFlags()) == CE_None) { VRTSourcedRasterBand *hMaskVRTBand = (VRTSourcedRasterBand*)poVRTBand->GetMaskBand(); hMaskVRTBand->AddMaskBandSource(poSrcBand, anSrcWin[0], anSrcWin[1], anSrcWin[2], anSrcWin[3], 0, 0, nOXSize, nOYSize); } } } if (eMaskMode == MASK_USER) { GDALRasterBand *poSrcBand = (GDALRasterBand*)GDALGetRasterBand(hDataset, ABS(nMaskBand)); if (poSrcBand && poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None) { VRTSourcedRasterBand *hMaskVRTBand = (VRTSourcedRasterBand*) GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1)); if (nMaskBand > 0) hMaskVRTBand->AddSimpleSource(poSrcBand, anSrcWin[0], anSrcWin[1], anSrcWin[2], anSrcWin[3], 0, 0, nOXSize, nOYSize); else hMaskVRTBand->AddMaskBandSource(poSrcBand, anSrcWin[0], anSrcWin[1], anSrcWin[2], anSrcWin[3], 0, 0, nOXSize, nOYSize); } } else if (eMaskMode == MASK_AUTO && nSrcBandCount > 0 && GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) == GMF_PER_DATASET) { if (poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None) { VRTSourcedRasterBand *hMaskVRTBand = (VRTSourcedRasterBand*) GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1)); hMaskVRTBand->AddMaskBandSource((GDALRasterBand*)GDALGetRasterBand(hDataset, 1), anSrcWin[0], anSrcWin[1], anSrcWin[2], anSrcWin[3], 0, 0, nOXSize, nOYSize); } } /* -------------------------------------------------------------------- */ /* Compute stats if required. */ /* -------------------------------------------------------------------- */ if (bStats) { for (i = 0; i < poVDS->GetRasterCount(); i++) { double dfMin, dfMax, dfMean, dfStdDev; poVDS->GetRasterBand(i + 1)->ComputeStatistics(bApproxStats, &dfMin, &dfMax, &dfMean, &dfStdDev, GDALDummyProgress, NULL); } } /* -------------------------------------------------------------------- */ /* Write to the output file using CopyCreate(). */ /* -------------------------------------------------------------------- */ hOutDS = GDALCreateCopy(hDriver, pszDest, (GDALDatasetH) poVDS, bStrict, papszCreateOptions, pfnProgress, NULL); if (hOutDS != NULL) { int bHasGotErr = FALSE; CPLErrorReset(); GDALFlushCache(hOutDS); if (CPLGetLastErrorType() != CE_None) bHasGotErr = TRUE; GDALClose(hOutDS); if (bHasGotErr) hOutDS = NULL; } GDALClose((GDALDatasetH) poVDS); GDALClose(hDataset); CPLFree(panBandList); CPLFree(pszOutputSRS); if (!bSubCall) { GDALDumpOpenDatasets(stderr); GDALDestroyDriverManager(); } CSLDestroy(argv); CSLDestroy(papszCreateOptions); return hOutDS == NULL; }