void object::test<7>() { CPLStringList oCSL; ensure( "7nil", oCSL.List() == NULL ); oCSL.AddString( "def" ); oCSL.AddString( "abc" ); ensure_equals( "7", oCSL.Count(), 2 ); ensure( "70", EQUAL(oCSL[0], "def") ); ensure( "71", EQUAL(oCSL[1], "abc") ); ensure( "72", oCSL[17] == NULL ); ensure( "73", oCSL[-1] == NULL ); ensure_equals( "74", oCSL.FindString("abc"), 1 ); CSLDestroy( oCSL.StealList() ); ensure_equals( "75", oCSL.Count(), 0 ); ensure( "76", oCSL.List() == NULL ); // Test that the list will make an internal copy when needed to // modify a read-only list. oCSL.AddString( "def" ); oCSL.AddString( "abc" ); CPLStringList oCopy( oCSL.List(), FALSE ); ensure_equals( "77", oCSL.List(), oCopy.List() ); ensure_equals( "78", oCSL.Count(), oCopy.Count() ); oCopy.AddString( "xyz" ); ensure( "79", oCSL.List() != oCopy.List() ); ensure_equals( "7a", oCopy.Count(), 3 ); ensure_equals( "7b", oCSL.Count(), 2 ); ensure( "7c", EQUAL(oCopy[2], "xyz") ); }
/** * @details This method is the heart of the tiler. A `TileCoordinate` is used * to obtain the geospatial extent associated with that tile as related to the * underlying GDAL dataset. This mapping may require a reprojection if the * underlying dataset is not in the tile projection system. This information * is then encapsulated as a GDAL virtual raster (VRT) dataset and returned to * the caller. * * It is the caller's responsibility to call `GDALClose()` on the returned * dataset. */ GDALTile * GDALTiler::createRasterTile(double (&adfGeoTransform)[6]) const { if (poDataset == NULL) { throw CTBException("No GDAL dataset is set"); } // The source and sink datasets GDALDatasetH hSrcDS = (GDALDatasetH) dataset(); GDALDatasetH hDstDS; // The transformation option list CPLStringList transformOptions; // The source, sink and grid srs const char *pszSrcWKT = GDALGetProjectionRef(hSrcDS), *pszGridWKT = pszSrcWKT; if (!strlen(pszSrcWKT)) throw CTBException("The source dataset no longer has a spatial reference system assigned"); // Populate the SRS WKT strings if we need to reproject if (requiresReprojection()) { pszGridWKT = crsWKT.c_str(); transformOptions.SetNameValue("SRC_SRS", pszSrcWKT); transformOptions.SetNameValue("DST_SRS", pszGridWKT); } // Set the warp options GDALWarpOptions *psWarpOptions = GDALCreateWarpOptions(); psWarpOptions->eResampleAlg = options.resampleAlg; psWarpOptions->dfWarpMemoryLimit = options.warpMemoryLimit; psWarpOptions->hSrcDS = hSrcDS; psWarpOptions->nBandCount = poDataset->GetRasterCount(); psWarpOptions->panSrcBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount ); psWarpOptions->panDstBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount ); for (short unsigned int i = 0; i < psWarpOptions->nBandCount; ++i) { psWarpOptions->panDstBands[i] = psWarpOptions->panSrcBands[i] = i + 1; } // Create the image to image transformer void *transformerArg = GDALCreateGenImgProjTransformer2(hSrcDS, NULL, transformOptions.List()); if(transformerArg == NULL) { GDALDestroyWarpOptions(psWarpOptions); throw CTBException("Could not create image to image transformer"); } // Try and get an overview from the source dataset that corresponds more // closely to the resolution of this tile. GDALDatasetH hWrkSrcDS = getOverviewDataset(hSrcDS, GDALGenImgProjTransform, transformerArg); if (hWrkSrcDS == NULL) { hWrkSrcDS = psWarpOptions->hSrcDS = hSrcDS; } else { // We need to recreate the transform when operating on an overview. GDALDestroyGenImgProjTransformer( transformerArg ); transformerArg = GDALCreateGenImgProjTransformer2( hWrkSrcDS, NULL, transformOptions.List() ); if(transformerArg == NULL) { GDALDestroyWarpOptions(psWarpOptions); throw CTBException("Could not create overview image to image transformer"); } } // Specify the destination geotransform GDALSetGenImgProjTransformerDstGeoTransform(transformerArg, adfGeoTransform ); // Decide if we are doing an approximate or exact transformation if (options.errorThreshold) { // approximate: wrap the transformer with a linear approximator psWarpOptions->pTransformerArg = GDALCreateApproxTransformer(GDALGenImgProjTransform, transformerArg, options.errorThreshold); if (psWarpOptions->pTransformerArg == NULL) { GDALDestroyWarpOptions(psWarpOptions); GDALDestroyGenImgProjTransformer(transformerArg); throw CTBException("Could not create linear approximator"); } psWarpOptions->pfnTransformer = GDALApproxTransform; } else { // exact: no wrapping required psWarpOptions->pTransformerArg = transformerArg; psWarpOptions->pfnTransformer = GDALGenImgProjTransform; } // Specify a multi threaded warp operation using all CPU cores CPLStringList warpOptions(psWarpOptions->papszWarpOptions, false); warpOptions.SetNameValue("NUM_THREADS", "ALL_CPUS"); psWarpOptions->papszWarpOptions = warpOptions.StealList(); // The raster tile is represented as a VRT dataset hDstDS = GDALCreateWarpedVRT(hWrkSrcDS, mGrid.tileSize(), mGrid.tileSize(), adfGeoTransform, psWarpOptions); bool isApproxTransform = (psWarpOptions->pfnTransformer == GDALApproxTransform); GDALDestroyWarpOptions( psWarpOptions ); if (hDstDS == NULL) { GDALDestroyGenImgProjTransformer(transformerArg); throw CTBException("Could not create warped VRT"); } // Set the projection information on the dataset. This will always be the grid // SRS. if (GDALSetProjection( hDstDS, pszGridWKT ) != CE_None) { GDALClose(hDstDS); if (transformerArg != NULL) { GDALDestroyGenImgProjTransformer(transformerArg); } throw CTBException("Could not set projection on VRT"); } // If uncommenting the following line for debug purposes, you must also `#include "vrtdataset.h"` //std::cout << "VRT: " << CPLSerializeXMLTree(((VRTWarpedDataset *) hDstDS)->SerializeToXML(NULL)) << std::endl; // Create the tile, passing it the base image transformer to manage if this is // an approximate transform return new GDALTile((GDALDataset *) hDstDS, isApproxTransform ? transformerArg : NULL); }
CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, const char *pszUnused ) { PamInitialize(); /* -------------------------------------------------------------------- */ /* Apply any dataset level metadata. */ /* -------------------------------------------------------------------- */ oMDMD.XMLInit( psTree, TRUE ); /* -------------------------------------------------------------------- */ /* Collect various other items of metadata. */ /* -------------------------------------------------------------------- */ GDALMajorObject::SetDescription( CPLGetXMLValue( psTree, "Description", "" ) ); if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL ) { const char *pszLEHex = CPLGetXMLValue( psTree, "NoDataValue.le_hex_equiv", NULL ); if( pszLEHex != NULL ) { int nBytes; GByte *pabyBin = CPLHexToBinary( pszLEHex, &nBytes ); if( nBytes == 8 ) { CPL_LSBPTR64( pabyBin ); GDALPamRasterBand::SetNoDataValue( *((double *) pabyBin) ); } else { GDALPamRasterBand::SetNoDataValue( atof(CPLGetXMLValue( psTree, "NoDataValue", "0" )) ); } CPLFree( pabyBin ); } else { GDALPamRasterBand::SetNoDataValue( atof(CPLGetXMLValue( psTree, "NoDataValue", "0" )) ); } } GDALPamRasterBand::SetOffset( atof(CPLGetXMLValue( psTree, "Offset", "0.0" )) ); GDALPamRasterBand::SetScale( atof(CPLGetXMLValue( psTree, "Scale", "1.0" )) ); GDALPamRasterBand::SetUnitType( CPLGetXMLValue( psTree, "UnitType", NULL)); if( CPLGetXMLValue( psTree, "ColorInterp", NULL ) != NULL ) { const char *pszInterp = CPLGetXMLValue( psTree, "ColorInterp", NULL ); GDALPamRasterBand::SetColorInterpretation( GDALGetColorInterpretationByName(pszInterp)); } /* -------------------------------------------------------------------- */ /* Category names. */ /* -------------------------------------------------------------------- */ if( CPLGetXMLNode( psTree, "CategoryNames" ) != NULL ) { CPLXMLNode *psEntry; CPLStringList oCategoryNames; for( psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild; psEntry != NULL; psEntry = psEntry->psNext ) { /* Don't skeep <Category> tag with empty content */ if( psEntry->eType != CXT_Element || !EQUAL(psEntry->pszValue,"Category") || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) ) continue; oCategoryNames.AddString( (psEntry->psChild) ? psEntry->psChild->pszValue : "" ); } GDALPamRasterBand::SetCategoryNames( oCategoryNames.List() ); } /* -------------------------------------------------------------------- */ /* Collect a color table. */ /* -------------------------------------------------------------------- */ if( CPLGetXMLNode( psTree, "ColorTable" ) != NULL ) { CPLXMLNode *psEntry; GDALColorTable oTable; int iEntry = 0; for( psEntry = CPLGetXMLNode( psTree, "ColorTable" )->psChild; psEntry != NULL; psEntry = psEntry->psNext ) { GDALColorEntry sCEntry; sCEntry.c1 = (short) atoi(CPLGetXMLValue( psEntry, "c1", "0" )); sCEntry.c2 = (short) atoi(CPLGetXMLValue( psEntry, "c2", "0" )); sCEntry.c3 = (short) atoi(CPLGetXMLValue( psEntry, "c3", "0" )); sCEntry.c4 = (short) atoi(CPLGetXMLValue( psEntry, "c4", "255" )); oTable.SetColorEntry( iEntry++, &sCEntry ); } GDALPamRasterBand::SetColorTable( &oTable ); } /* -------------------------------------------------------------------- */ /* Do we have a complete set of stats? */ /* -------------------------------------------------------------------- */ if( CPLGetXMLNode( psTree, "Minimum" ) != NULL && CPLGetXMLNode( psTree, "Maximum" ) != NULL ) { psPam->bHaveMinMax = TRUE; psPam->dfMin = atof(CPLGetXMLValue(psTree, "Minimum","0")); psPam->dfMax = atof(CPLGetXMLValue(psTree, "Maximum","0")); } if( CPLGetXMLNode( psTree, "Mean" ) != NULL && CPLGetXMLNode( psTree, "StandardDeviation" ) != NULL ) { psPam->bHaveStats = TRUE; psPam->dfMean = atof(CPLGetXMLValue(psTree, "Mean","0")); psPam->dfStdDev = atof(CPLGetXMLValue(psTree,"StandardDeviation","0")); } /* -------------------------------------------------------------------- */ /* Histograms */ /* -------------------------------------------------------------------- */ CPLXMLNode *psHist = CPLGetXMLNode( psTree, "Histograms" ); if( psHist != NULL ) { CPLXMLNode *psNext = psHist->psNext; psHist->psNext = NULL; if (psPam->psSavedHistograms != NULL) { CPLDestroyXMLNode (psPam->psSavedHistograms ); psPam->psSavedHistograms = NULL; } psPam->psSavedHistograms = CPLCloneXMLTree( psHist ); psHist->psNext = psNext; } /* -------------------------------------------------------------------- */ /* Raster Attribute Table */ /* -------------------------------------------------------------------- */ CPLXMLNode *psRAT = CPLGetXMLNode( psTree, "GDALRasterAttributeTable" ); if( psRAT != NULL ) { if( psPam->poDefaultRAT != NULL ) { delete psPam->poDefaultRAT; psPam->poDefaultRAT = NULL; } psPam->poDefaultRAT = new GDALDefaultRasterAttributeTable(); psPam->poDefaultRAT->XMLInit( psRAT, "" ); } return CE_None; }
MAIN_START(argc, argv) { // Check that we are running against at least GDAL 1.5. // Note to developers: if we use newer API, please change the requirement. if (atoi(GDALVersionInfo("VERSION_NUM")) < 1500) { fprintf(stderr, "At least, GDAL >= 1.5.0 is required for this version of %s, " "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME); exit(1); } GDALAllRegister(); argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 ); if( argc < 1 ) exit( -argc ); const char *pszSrcFilename = nullptr; const char *pszDstFilename = nullptr; int nOrder = 0; void *hTransformArg; GDALTransformerFunc pfnTransformer = nullptr; int nGCPCount = 0; GDAL_GCP *pasGCPs = nullptr; int bInverse = FALSE; CPLStringList aosTO; int bOutputXY = FALSE; double dfX = 0.0; double dfY = 0.0; double dfZ = 0.0; double dfT = 0.0; bool bCoordOnCommandLine = false; /* -------------------------------------------------------------------- */ /* Parse arguments. */ /* -------------------------------------------------------------------- */ for( int i = 1; i < argc && argv[i] != nullptr; 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")); CSLDestroy(argv); return 0; } else if( EQUAL(argv[i],"--help") ) { Usage(); } else if( EQUAL(argv[i],"-t_srs") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); const char *pszSRS = argv[++i]; if( !IsValidSRS(pszSRS) ) exit(1); aosTO.SetNameValue("DST_SRS", pszSRS ); } else if( EQUAL(argv[i],"-s_srs") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); const char *pszSRS = argv[++i]; if( !IsValidSRS(pszSRS) ) exit(1); aosTO.SetNameValue("SRC_SRS", pszSRS ); } else if( EQUAL(argv[i],"-ct") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); const char *pszCT = argv[++i]; aosTO.SetNameValue("COORDINATE_OPERATION", pszCT ); } else if( EQUAL(argv[i],"-order") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); nOrder = atoi(argv[++i]); aosTO.SetNameValue("MAX_GCP_ORDER", argv[i] ); } else if( EQUAL(argv[i],"-tps") ) { aosTO.SetNameValue("METHOD", "GCP_TPS" ); nOrder = -1; } else if( EQUAL(argv[i],"-rpc") ) { aosTO.SetNameValue("METHOD", "RPC" ); } else if( EQUAL(argv[i],"-geoloc") ) { aosTO.SetNameValue("METHOD", "GEOLOC_ARRAY" ); } else if( EQUAL(argv[i],"-i") ) { bInverse = TRUE; } else if( EQUAL(argv[i],"-to") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); aosTO.AddString( argv[++i] ); } else if( EQUAL(argv[i],"-gcp") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4); char* endptr = nullptr; /* -gcp pixel line easting northing [elev] */ nGCPCount++; pasGCPs = static_cast<GDAL_GCP *>( CPLRealloc(pasGCPs, sizeof(GDAL_GCP) * nGCPCount)); GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 ); pasGCPs[nGCPCount-1].dfGCPPixel = CPLAtof(argv[++i]); pasGCPs[nGCPCount-1].dfGCPLine = CPLAtof(argv[++i]); pasGCPs[nGCPCount-1].dfGCPX = CPLAtof(argv[++i]); pasGCPs[nGCPCount-1].dfGCPY = CPLAtof(argv[++i]); if( argv[i+1] != nullptr && (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 = CPLAtof(argv[++i]); } /* should set id and info? */ } else if( EQUAL(argv[i],"-output_xy") ) { bOutputXY = TRUE; } else if( EQUAL(argv[i],"-coord") && i + 2 < argc) { bCoordOnCommandLine = true; dfX = CPLAtof(argv[++i]); dfY = CPLAtof(argv[++i]); if( i + 1 < argc && CPLGetValueType(argv[i+1]) != CPL_VALUE_STRING ) dfZ = CPLAtof(argv[++i]); if( i + 1 < argc && CPLGetValueType(argv[i+1]) != CPL_VALUE_STRING ) dfT = CPLAtof(argv[++i]); } else if( argv[i][0] == '-' ) { Usage(CPLSPrintf("Unknown option name '%s'", argv[i])); } else if( pszSrcFilename == nullptr ) { pszSrcFilename = argv[i]; } else if( pszDstFilename == nullptr ) { pszDstFilename = argv[i]; } else { Usage("Too many command options."); } } /* -------------------------------------------------------------------- */ /* Open src and destination file, if appropriate. */ /* -------------------------------------------------------------------- */ GDALDatasetH hSrcDS = nullptr; if( pszSrcFilename != nullptr ) { hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly ); if( hSrcDS == nullptr ) exit( 1 ); } GDALDatasetH hDstDS = nullptr; if( pszDstFilename != nullptr ) { hDstDS = GDALOpen( pszDstFilename, GA_ReadOnly ); if( hDstDS == nullptr ) exit( 1 ); } if( hSrcDS != nullptr && nGCPCount > 0 ) { fprintf(stderr, "Command line GCPs and input file specified, " "specify one or the other.\n"); exit( 1 ); } /* -------------------------------------------------------------------- */ /* Create a transformation object from the source to */ /* destination coordinate system. */ /* -------------------------------------------------------------------- */ if( nGCPCount != 0 && nOrder == -1 ) { pfnTransformer = GDALTPSTransform; hTransformArg = GDALCreateTPSTransformer( nGCPCount, pasGCPs, FALSE ); } else if( nGCPCount != 0 ) { pfnTransformer = GDALGCPTransform; hTransformArg = GDALCreateGCPTransformer( nGCPCount, pasGCPs, nOrder, FALSE ); } else { pfnTransformer = GDALGenImgProjTransform; hTransformArg = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, aosTO.List() ); } if( hTransformArg == nullptr ) { exit( 1 ); } /* -------------------------------------------------------------------- */ /* Read points from stdin, transform and write to stdout. */ /* -------------------------------------------------------------------- */ double dfLastT = 0.0; while( bCoordOnCommandLine || !feof(stdin) ) { if( !bCoordOnCommandLine ) { char szLine[1024]; if( fgets( szLine, sizeof(szLine)-1, stdin ) == nullptr ) break; char **papszTokens = CSLTokenizeString(szLine); const int nCount = CSLCount(papszTokens); if( nCount < 2 ) { CSLDestroy(papszTokens); continue; } dfX = CPLAtof(papszTokens[0]); dfY = CPLAtof(papszTokens[1]); if( nCount >= 3 ) dfZ = CPLAtof(papszTokens[2]); else dfZ = 0.0; if( nCount == 4 ) dfT = CPLAtof(papszTokens[3]); else dfT = 0.0; CSLDestroy(papszTokens); } if( dfT != dfLastT && nGCPCount == 0 ) { if( dfT != 0.0 ) { aosTO.SetNameValue("COORDINATE_EPOCH", CPLSPrintf("%g", dfT)); } else { aosTO.SetNameValue("COORDINATE_EPOCH", nullptr); } GDALDestroyGenImgProjTransformer(hTransformArg); hTransformArg = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, aosTO.List() ); } int bSuccess = TRUE; if( pfnTransformer( hTransformArg, bInverse, 1, &dfX, &dfY, &dfZ, &bSuccess ) && bSuccess ) { if( bOutputXY ) CPLprintf( "%.15g %.15g\n", dfX, dfY ); else CPLprintf( "%.15g %.15g %.15g\n", dfX, dfY, dfZ ); } else { printf( "transformation failed.\n" ); } if( bCoordOnCommandLine ) break; dfLastT = dfT; } if( nGCPCount != 0 && nOrder == -1 ) { GDALDestroyTPSTransformer(hTransformArg); } else if( nGCPCount != 0 ) { GDALDestroyGCPTransformer(hTransformArg); } else { GDALDestroyGenImgProjTransformer(hTransformArg); } if (nGCPCount) { GDALDeinitGCPs( nGCPCount, pasGCPs ); CPLFree( pasGCPs ); } if (hSrcDS) GDALClose(hSrcDS); if (hDstDS) GDALClose(hDstDS); GDALDumpOpenDatasets( stderr ); GDALDestroyDriverManager(); CSLDestroy( argv ); return 0; }
/** Load proj.4 geoidgrids as GDAL dataset * * @param pszProj4Geoidgrids Value of proj.4 geoidgrids parameter. * @param pbError If not NULL, the pointed value will be set to TRUE if an * error occurred. * * @return a dataset. If not NULL, it must be closed with GDALClose(). * * @since GDAL 2.2 */ GDALDatasetH GDALOpenVerticalShiftGrid( const char* pszProj4Geoidgrids, int* pbError ) { char** papszGrids = CSLTokenizeString2( pszProj4Geoidgrids, ",", 0); const int nGridCount = CSLCount(papszGrids); if( nGridCount == 1 ) { CSLDestroy(papszGrids); bool bMissingOk = false; if( *pszProj4Geoidgrids == '@' ) { pszProj4Geoidgrids ++; bMissingOk = true; } const CPLString osFilename(GetProj4Filename(pszProj4Geoidgrids)); const char* const papszOpenOptions[] = { "@SHIFT_ORIGIN_IN_MINUS_180_PLUS_180=YES", nullptr }; GDALDatasetH hDS = GDALOpenEx(osFilename, 0, nullptr, papszOpenOptions, nullptr); if( hDS == nullptr ) { CPLDebug("GDAL", "Cannot find file corresponding to %s", pszProj4Geoidgrids); } if( pbError ) *pbError = (!bMissingOk && hDS == nullptr); return hDS; } CPLStringList aosFilenames; for( int i = nGridCount - 1; i >= 0; i-- ) { const char* pszName = papszGrids[i]; bool bMissingOk = false; if( *pszName == '@' ) { pszName ++; bMissingOk = true; } const CPLString osFilename(GetProj4Filename(pszName)); VSIStatBufL sStat; if( osFilename.empty() || VSIStatL(osFilename, &sStat) != 0 ) { CPLDebug("GDAL", "Cannot find file corresponding to %s", pszName); if( !bMissingOk ) { if( pbError ) *pbError = true; CSLDestroy(papszGrids); return nullptr; } } else { aosFilenames.AddString(osFilename); } } CSLDestroy(papszGrids); if( aosFilenames.empty() ) { if( pbError ) *pbError = false; return nullptr; } char** papszArgv = nullptr; papszArgv = CSLAddString(papszArgv, "-resolution"); papszArgv = CSLAddString(papszArgv, "highest"); papszArgv = CSLAddString(papszArgv, "-vrtnodata"); papszArgv = CSLAddString(papszArgv, "-inf"); papszArgv = CSLAddString(papszArgv, "-oo"); papszArgv = CSLAddString(papszArgv, "@SHIFT_ORIGIN_IN_MINUS_180_PLUS_180=YES"); GDALBuildVRTOptions* psOptions = GDALBuildVRTOptionsNew(papszArgv, nullptr); CSLDestroy(papszArgv); GDALDatasetH hDS = GDALBuildVRT( "", aosFilenames.size(), nullptr, aosFilenames.List(), psOptions, nullptr ); GDALBuildVRTOptionsFree( psOptions ); if( pbError ) *pbError = hDS != nullptr; return hDS; }