int main( int argc, char ** argv )

{
    const char         *pszSrcFilename = NULL;
    const char         *pszDstFilename = NULL;
    int                 nOrder = 0;
    void               *hTransformArg;
    GDALTransformerFunc pfnTransformer = NULL;
    int                 nGCPCount = 0;
    GDAL_GCP            *pasGCPs = NULL;
    int                 bInverse = FALSE;
    char              **papszTO = NULL;

    /* 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 );

/* -------------------------------------------------------------------- */
/*      Parse arguments.                                                */
/* -------------------------------------------------------------------- */
    int i;

    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],"-t_srs") && i < argc-1 )
        {
            char *pszSRS = SanitizeSRS(argv[++i]);
            papszTO = CSLSetNameValue( papszTO, "DST_SRS", pszSRS );
            CPLFree( pszSRS );
        }
        else if( EQUAL(argv[i],"-s_srs") && i < argc-1 )
        {
            char *pszSRS = SanitizeSRS(argv[++i]);
            papszTO = CSLSetNameValue( papszTO, "SRC_SRS", pszSRS );
            CPLFree( pszSRS );
        }
        else if( EQUAL(argv[i],"-order") && i < argc-1 )
        {
            nOrder = atoi(argv[++i]);
            papszTO = CSLSetNameValue( papszTO, "MAX_GCP_ORDER", argv[i] );
        }
        else if( EQUAL(argv[i],"-tps") )
        {
            papszTO = CSLSetNameValue( papszTO, "METHOD", "GCP_TPS" );
            nOrder = -1;
        }
        else if( EQUAL(argv[i],"-rpc") )
        {
            papszTO = CSLSetNameValue( papszTO, "METHOD", "RPC" );
        }
        else if( EQUAL(argv[i],"-geoloc") )
        {
            papszTO = CSLSetNameValue( papszTO, "METHOD", "GEOLOC_ARRAY" );
        }
        else if( EQUAL(argv[i],"-i") )
        {
            bInverse = TRUE;
        }
        else if( EQUAL(argv[i],"-to") && i < argc-1 )
        {
            papszTO = CSLAddString( papszTO, argv[++i] );
        }
        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 = atof(argv[++i]);
            pasGCPs[nGCPCount-1].dfGCPLine = atof(argv[++i]);
            pasGCPs[nGCPCount-1].dfGCPX = atof(argv[++i]);
            pasGCPs[nGCPCount-1].dfGCPY = atof(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 = atof(argv[++i]);
            }

            /* should set id and info? */
        }   

        else if( argv[i][0] == '-' )
            Usage();

        else if( pszSrcFilename == NULL )
            pszSrcFilename = argv[i];

        else if( pszDstFilename == NULL )
            pszDstFilename = argv[i];

        else
            Usage();
    }

/* -------------------------------------------------------------------- */
/*      Open src and destination file, if appropriate.                  */
/* -------------------------------------------------------------------- */
    GDALDatasetH hSrcDS = NULL, hDstDS = NULL;

    if( pszSrcFilename != NULL )
    {
        hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
        if( hSrcDS == NULL )
            exit( 1 );
    }

    if( pszDstFilename != NULL )
    {
        hDstDS = GDALOpen( pszDstFilename, GA_ReadOnly );
        if( hDstDS == NULL )
            exit( 1 );
    }

    if( hSrcDS != NULL && nGCPCount > 0 )
    {
        fprintf( stderr, "Commandline 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, papszTO );
    }

    CSLDestroy( papszTO );

    if( hTransformArg == NULL )
    {
        exit( 1 );
    }

/* -------------------------------------------------------------------- */
/*      Read points from stdin, transform and write to stdout.          */
/* -------------------------------------------------------------------- */
    while( !feof(stdin) )
    {
        char szLine[1024];

        if( fgets( szLine, sizeof(szLine)-1, stdin ) == NULL )
            break;

        char **papszTokens = CSLTokenizeString(szLine);
        double dfX, dfY, dfZ = 0.0;
        int bSuccess = TRUE;

        if( CSLCount(papszTokens) < 2 )
        {
            CSLDestroy(papszTokens);
            continue;
        }

        dfX = atof(papszTokens[0]);
        dfY = atof(papszTokens[1]);
        if( CSLCount(papszTokens) >= 3 )
            dfZ = atof(papszTokens[2]);

        if( pfnTransformer( hTransformArg, bInverse, 1, 
                            &dfX, &dfY, &dfZ, &bSuccess )
            && bSuccess )
        {
            printf( "%.15g %.15g %.15g\n", dfX, dfY, dfZ );
        }
        else
        {
            printf( "transformation failed.\n" );
        }

        CSLDestroy(papszTokens);
    }

    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;
}
Exemple #2
0
int main( int nArgc, char ** papszArgv )
{
    // register drivers
    GDALAllRegister();

    if( nArgc < 2 )
        return EXIT_FAILURE;

    double dfaCornersX[5] = {0};
    double dfaCornersY[5] = {0};
    CPLString sFileName;

    // parse input values
    for( int iArg = 1; iArg < nArgc; iArg++ )
    {
        if( EQUAL(papszArgv[iArg],"-nw"))
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
            const char* pszCoord = papszArgv[++iArg];
            dfaCornersY[1] = CPLAtofM(pszCoord);
            pszCoord = papszArgv[++iArg];
            dfaCornersX[1] = CPLAtofM(pszCoord);
        }
        else if( EQUAL(papszArgv[iArg],"-ne"))
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
            const char* pszCoord = papszArgv[++iArg];
            dfaCornersY[2] = CPLAtofM(pszCoord);
            pszCoord = papszArgv[++iArg];
            dfaCornersX[2] = CPLAtofM(pszCoord);
        }
        else if( EQUAL(papszArgv[iArg],"-se"))
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
            const char* pszCoord = papszArgv[++iArg];
            dfaCornersY[3] = CPLAtofM(pszCoord);
            pszCoord = papszArgv[++iArg];
            dfaCornersX[3] = CPLAtofM(pszCoord);
        }
        else if( EQUAL(papszArgv[iArg],"-sw"))
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
            const char* pszCoord = papszArgv[++iArg];
            dfaCornersY[4] = CPLAtofM(pszCoord);
            pszCoord = papszArgv[++iArg];
            dfaCornersX[4] = CPLAtofM(pszCoord);
        }
        else if( EQUAL(papszArgv[iArg],"-c"))
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2);
            const char* pszCoord = papszArgv[++iArg];
            dfaCornersY[0] = CPLAtofM(pszCoord);
            pszCoord = papszArgv[++iArg];
            dfaCornersX[0] = CPLAtofM(pszCoord);
        }
        else if(sFileName.empty())
            sFileName = papszArgv[iArg];
    }

    OGRSpatialReference oOGRSpatialReference(SRS_WKT_WGS84);
    int nZoneNo = ceil( (180.0 + dfaCornersX[0]) / 6.0 );
    OGRSpatialReference oDstSpatialReference(SRS_WKT_WGS84);
    oDstSpatialReference.SetUTM(nZoneNo, dfaCornersY[0] > 0);

    // transform coordinates from WGS84 to UTM
    OGRCoordinateTransformation *poCT = OGRCreateCoordinateTransformation( &oOGRSpatialReference, &oDstSpatialReference);
    if(!poCT)
    {
        Usage("get coordinate transformation failed");
        return EXIT_FAILURE;
    }

    int nResult = poCT->Transform(5, dfaCornersX, dfaCornersY, NULL);
    if(!nResult)
    {
        Usage("transformation failed");
        return EXIT_FAILURE;
    }

    // open input dataset
    GDALDataset *poSrcDataset = (GDALDataset *) GDALOpen( sFileName, GA_ReadOnly ); // GA_Update
    char* pszSpaRefDef = NULL;
    if( oDstSpatialReference.exportToWkt(&pszSpaRefDef) != OGRERR_NONE)
    {
        CPLFree( pszSpaRefDef );
        GDALClose( (GDALDatasetH) poSrcDataset );
        return EXIT_FAILURE;
    }

    // search point along image
    // add GCP to opened raster
    OGRPoint ptCenter(dfaCornersX[0], dfaCornersY[0]);
    OGRPoint pt1(dfaCornersX[1], dfaCornersY[1]); // NW Cormer
    OGRPoint pt2(dfaCornersX[2], dfaCornersY[2]); // NE Corner
    OGRPoint pt3(dfaCornersX[3], dfaCornersY[3]); // SE Corner
    OGRPoint pt4(dfaCornersX[4], dfaCornersY[4]); // SW Corner
    int nGCPCount = 0;
    OGREnvelope DstEnv;
    GDAL_GCP *paGSPs = PrepareGCP(sFileName, &pt1, &pt2, &pt3, &pt4, &ptCenter, oDstSpatialReference, poSrcDataset->GetRasterXSize(), poSrcDataset->GetRasterYSize(), nGCPCount, DstEnv);

    if(poSrcDataset->SetGCPs(nGCPCount, paGSPs, pszSpaRefDef) != CE_None)
    {
        Usage( "Set GCPs failed" );
        return EXIT_FAILURE;
    }

    // create warper
    char **papszTO = NULL;
    papszTO = CSLSetNameValue( papszTO, "METHOD", "GCP_TPS" );
    papszTO = CSLSetNameValue( papszTO, "NUM_THREADS", "4" );
    papszTO = CSLSetNameValue( papszTO, "DST_SRS", pszSpaRefDef );
    papszTO = CSLSetNameValue( papszTO, "SRC_SRS", pszSpaRefDef );
    papszTO = CSLSetNameValue( papszTO, "INSERT_CENTER_LONG", "FALSE" );

    GDALDriver *poOutputDriver = (GDALDriver *) GDALGetDriverByName( "GTiff" );
    CPLSetConfigOption( "CHECK_WITH_INVERT_PROJ", "TRUE" );
    void* hTransformArg = GDALCreateGenImgProjTransformer2( poSrcDataset, NULL, papszTO );
    GDALTransformerInfo* psInfo = (GDALTransformerInfo*)hTransformArg;

    double adfThisGeoTransform[6];
    double adfExtent[4];
    int nThisPixels, nThisLines;

    // suggest the raster output size
    if( GDALSuggestedWarpOutput2( poSrcDataset, psInfo->pfnTransform, hTransformArg, adfThisGeoTransform, &nThisPixels, &nThisLines, adfExtent, 0 ) != CE_None )
    {
        Usage( "Suggest Output failed" );
        return EXIT_FAILURE;
    }

    adfThisGeoTransform[0] = DstEnv.MinX;
    adfThisGeoTransform[3] = DstEnv.MaxY;

    int nPixels = (int) ((DstEnv.MaxX - DstEnv.MinX) / adfThisGeoTransform[1] + 0.5);
    int nLines = (int) ((DstEnv.MaxY - DstEnv.MinY) / -adfThisGeoTransform[5] + 0.5);

    GDALSetGenImgProjTransformerDstGeoTransform( hTransformArg, adfThisGeoTransform);

    // create new raster
    CPLString sOutputRasterPath = CPLResetExtension(sFileName, "tif");
    GDALDataset  *poDstDataset = poOutputDriver->Create(sOutputRasterPath, nPixels, nLines, poSrcDataset->GetRasterCount(), GDT_Byte, NULL );
    if( NULL == poDstDataset )
    {
        Usage( "Create Output failed" );
        return EXIT_FAILURE;
    }
    poDstDataset->SetProjection( pszSpaRefDef );
    poDstDataset->SetGeoTransform( adfThisGeoTransform );

#ifdef APRROX_MAXERROR
    hTransformArg = GDALCreateApproxTransformer( GDALGenImgProjTransform,  hTransformArg, APRROX_MAXERROR);
    GDALTransformerFunc pfnTransformer = GDALApproxTransform;
    GDALApproxTransformerOwnsSubtransformer(hTransformArg, TRUE);
#else
    GDALTransformerFunc pfnTransformer = GDALGenImgProjTransform;
#endif // APRROX_MAXERROR

    // warp
    GDALWarpOptions *psWO = GDALCreateWarpOptions();

    psWO->eWorkingDataType = GDT_Byte;
    psWO->eResampleAlg = GRA_NearestNeighbour;

    psWO->hSrcDS = poSrcDataset;
    psWO->hDstDS = poDstDataset;

    psWO->pfnTransformer = pfnTransformer;
    psWO->pTransformerArg = hTransformArg;

    psWO->pfnProgress = GDALTermProgress;
    psWO->nBandCount = poSrcDataset->GetRasterCount();

    psWO->panSrcBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
    psWO->panDstBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));

    for(int i = 0; i < psWO->nBandCount; ++i )
    {
        psWO->panSrcBands[i] = i+1;
        psWO->panDstBands[i] = i+1;
    }

    GDALWarpOperation oWO;
    if( oWO.Initialize( psWO ) == CE_None )
    {
#ifdef MULTI
        if( oWO.ChunkAndWarpMulti( 0, 0, poDstDataset->GetRasterXSize(), poDstDataset->GetRasterYSize() ) != CE_None)
#else //MULTI
        if( oWO.ChunkAndWarpImage( 0, 0, poDstDataset->GetRasterXSize(), poDstDataset->GetRasterYSize() ) != CE_None)
#endif //MULTI
        {
            const char* err = CPLGetLastErrorMsg();
            Usage( CPLSPrintf("Warp failed.%s", err) );
            return EXIT_FAILURE;
        }
    }

    // cleanup
    GDALDestroyWarpOptions( psWO );
    CSLDestroy( papszTO );

    CPLFree( pszSpaRefDef );
    GDALClose( (GDALDatasetH) poSrcDataset );
    GDALClose( (GDALDatasetH) poDstDataset );

    GDALDestroyDriverManager();

    return EXIT_SUCCESS;
}
Exemple #3
0
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;
}