int main(int argc, char** argv)
{
	char* srcFileName1;
	char* srcFileName2;
	char* dstFileName;

	GDALDataset* srcDS1, *srcDS2;
	GDALDataset* dstDS;

	if(argc != 4)
		error("Usage: prog infile1 infile2 outfile");

	srcFileName1 = argv[1];
	srcFileName2 = argv[2];
	dstFileName = argv[3];

	GDALAllRegister();

	srcDS1 = (GDALDataset*) GDALOpen( srcFileName1, GA_ReadOnly );
	srcDS2 = (GDALDataset*) GDALOpen( srcFileName2, GA_ReadOnly );

	if(srcDS1 == NULL || srcDS2 == NULL)
		error("Could not open source dataset");

	printf("Got image %d x %d x %d\n",
	      srcDS1->GetRasterXSize(),
	      srcDS1->GetRasterYSize(),
	      srcDS1->GetRasterCount()
	);
	printf("Got image %d x %d x %d\n",
	      srcDS2->GetRasterXSize(),
	      srcDS2->GetRasterYSize(),
	      srcDS2->GetRasterCount()
	);
	if((srcDS1->GetRasterXSize() != srcDS2->GetRasterXSize()) || 
           (srcDS1->GetRasterYSize() != srcDS2->GetRasterYSize()) ||
	   (srcDS1->GetRasterCount() != srcDS2->GetRasterCount()))
		fprintf(stderr, "Warning: Source dataset geometries should match!\n");

	int x_size, y_size, n_bands;
	x_size = MY_MAX(srcDS1->GetRasterXSize(), srcDS2->GetRasterXSize());
	y_size = MY_MAX(srcDS1->GetRasterYSize(), srcDS2->GetRasterYSize());
	n_bands = MY_MIN(srcDS1->GetRasterCount(), srcDS2->GetRasterCount());

	dstDS = CreateOutputDataset(dstFileName, 
	                            x_size, y_size, n_bands
	                           );

	if(dstDS == NULL)
		error("Could not create destination dataset");

	CalcFFT(srcDS1, srcDS2, dstDS);

	delete srcDS1;
	delete srcDS2;
	delete dstDS;

	return 0;	
}
GDALDatasetH GDALRasterize( const char *pszDest, GDALDatasetH hDstDS,
                            GDALDatasetH hSrcDataset,
                            const GDALRasterizeOptions *psOptionsIn, int *pbUsageError )
{
    if( pszDest == NULL && hDstDS == NULL )
    {
        CPLError( CE_Failure, CPLE_AppDefined, "pszDest == NULL && hDstDS == NULL");

        if(pbUsageError)
            *pbUsageError = TRUE;
        return NULL;
    }
    if( hSrcDataset == NULL )
    {
        CPLError( CE_Failure, CPLE_AppDefined, "hSrcDataset== NULL");

        if(pbUsageError)
            *pbUsageError = TRUE;
        return NULL;
    }
    if( hDstDS != NULL && psOptionsIn && psOptionsIn->bCreateOutput )
    {
        CPLError( CE_Failure, CPLE_AppDefined, "hDstDS != NULL but options that imply creating a new dataset have been set.");

        if(pbUsageError)
            *pbUsageError = TRUE;
        return NULL;
    }

    GDALRasterizeOptions* psOptionsToFree = NULL;
    const GDALRasterizeOptions* psOptions;
    if( psOptionsIn )
        psOptions = psOptionsIn;
    else
    {
        psOptionsToFree = GDALRasterizeOptionsNew(NULL, NULL);
        psOptions = psOptionsToFree;
    }

    int bCloseOutDSOnError = (hDstDS == NULL);
    if( pszDest == NULL )
        pszDest = GDALGetDescription(hDstDS);

    if( psOptions->pszSQL == NULL && psOptions->papszLayers == NULL &&
        GDALDatasetGetLayerCount(hSrcDataset) != 1 )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Neither -sql nor -l are specified, but the source dataset has not one single layer.");
        if( pbUsageError )
            *pbUsageError = TRUE;
        GDALRasterizeOptionsFree(psOptionsToFree);
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Open target raster file.  Eventually we will add optional       */
/*      creation.                                                       */
/* -------------------------------------------------------------------- */
    int bCreateOutput = psOptions->bCreateOutput;
    if( hDstDS == NULL )
        bCreateOutput = TRUE;

    GDALDriverH hDriver = NULL;
    if (psOptions->bCreateOutput)
    {
/* -------------------------------------------------------------------- */
/*      Find the output driver.                                         */
/* -------------------------------------------------------------------- */
        hDriver = GDALGetDriverByName( psOptions->pszFormat );
        if( hDriver == NULL
            || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
        {
            int	iDr;

            CPLError( CE_Failure, CPLE_NotSupported,
                      "Output driver `%s' not recognised or does not support "
                      " direct output file creation.", psOptions->pszFormat);
            fprintf(stderr, "The following format drivers are configured\n"
                    "and support direct output:\n" );

            for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
            {
                hDriver = GDALGetDriver(iDr);

                if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL )
                {
                    fprintf(stderr, "  %s: %s\n",
                            GDALGetDriverShortName( hDriver  ),
                            GDALGetDriverLongName( hDriver ) );
                }
            }
            fprintf(stderr, "\n" );
            GDALRasterizeOptionsFree(psOptionsToFree);
            return NULL;
        }
    }

/* -------------------------------------------------------------------- */
/*      Process SQL request.                                            */
/* -------------------------------------------------------------------- */
    CPLErr eErr = CE_Failure;

    if( psOptions->pszSQL != NULL )
    {
        OGRLayerH hLayer;

        hLayer = GDALDatasetExecuteSQL( hSrcDataset, psOptions->pszSQL, NULL, psOptions->pszDialect );
        if( hLayer != NULL )
        {
            if (bCreateOutput)
            {
                std::vector<OGRLayerH> ahLayers;
                ahLayers.push_back(hLayer);

                hDstDS = CreateOutputDataset(ahLayers, psOptions->hSRS,
                                 psOptions->bGotBounds, psOptions->sEnvelop,
                                 hDriver, pszDest,
                                 psOptions->nXSize, psOptions->nYSize, psOptions->dfXRes, psOptions->dfYRes,
                                 psOptions->bTargetAlignedPixels,
                                 static_cast<int>(psOptions->anBandList.size()), psOptions->eOutputType,
                                 psOptions->papszCreationOptions, psOptions->adfInitVals,
                                 psOptions->bNoDataSet, psOptions->dfNoData);
                if( hDstDS == NULL )
                {
                    GDALDatasetReleaseResultSet( hSrcDataset, hLayer );
                    GDALRasterizeOptionsFree(psOptionsToFree);
                    return NULL;
                }
            }

            eErr = ProcessLayer( hLayer, psOptions->hSRS != NULL, hDstDS, psOptions->anBandList,
                          psOptions->adfBurnValues, psOptions->b3D, psOptions->bInverse, psOptions->pszBurnAttribute,
                          psOptions->papszRasterizeOptions, psOptions->pfnProgress, psOptions->pProgressData );

            GDALDatasetReleaseResultSet( hSrcDataset, hLayer );
        }
    }

/* -------------------------------------------------------------------- */
/*      Create output file if necessary.                                */
/* -------------------------------------------------------------------- */
    int nLayerCount = (psOptions->pszSQL == NULL && psOptions->papszLayers == NULL) ? 1 : CSLCount(psOptions->papszLayers);

    if (psOptions->bCreateOutput && hDstDS == NULL)
    {
        std::vector<OGRLayerH> ahLayers;

        for( int i = 0; i < nLayerCount; i++ )
        {
            OGRLayerH hLayer;
            if( psOptions->papszLayers )
                hLayer = GDALDatasetGetLayerByName( hSrcDataset, psOptions->papszLayers[i] );
            else
                hLayer = GDALDatasetGetLayer(hSrcDataset, 0);
            if( hLayer == NULL )
            {
                continue;
            }
            ahLayers.push_back(hLayer);
        }

        hDstDS = CreateOutputDataset(ahLayers, psOptions->hSRS,
                                psOptions->bGotBounds, psOptions->sEnvelop,
                                hDriver, pszDest,
                                psOptions->nXSize, psOptions->nYSize, psOptions->dfXRes, psOptions->dfYRes,
                                psOptions->bTargetAlignedPixels,
                                static_cast<int>(psOptions->anBandList.size()), psOptions->eOutputType,
                                psOptions->papszCreationOptions, psOptions->adfInitVals,
                                psOptions->bNoDataSet, psOptions->dfNoData);
        if( hDstDS == NULL )
        {
            GDALRasterizeOptionsFree(psOptionsToFree);
            return NULL;
        }
    }

/* -------------------------------------------------------------------- */
/*      Process each layer.                                             */
/* -------------------------------------------------------------------- */

    for( int i = 0; i < nLayerCount; i++ )
    {
        OGRLayerH hLayer;
        if( psOptions->papszLayers )
            hLayer = GDALDatasetGetLayerByName( hSrcDataset, psOptions->papszLayers[i] );
        else
            hLayer = GDALDatasetGetLayer(hSrcDataset, 0);
        if( hLayer == NULL )
        {
            CPLError(CE_Failure, CPLE_AppDefined, "Unable to find layer \"%s\", skipping.",
                     psOptions->papszLayers ? psOptions->papszLayers[i] : "0" );
            continue;
        }

        if( psOptions->pszWHERE )
        {
            if( OGR_L_SetAttributeFilter( hLayer, psOptions->pszWHERE ) != OGRERR_NONE )
                break;
        }

        void *pScaledProgress;
        pScaledProgress =
            GDALCreateScaledProgress( 0.0, 1.0 * (i + 1) / nLayerCount,
                                      psOptions->pfnProgress, psOptions->pProgressData );

        eErr = ProcessLayer( hLayer, psOptions->hSRS != NULL, hDstDS, psOptions->anBandList,
                      psOptions->adfBurnValues, psOptions->b3D, psOptions->bInverse, psOptions->pszBurnAttribute,
                      psOptions->papszRasterizeOptions, GDALScaledProgress, pScaledProgress );

        GDALDestroyScaledProgress( pScaledProgress );
        if( eErr != CE_None )
            break;
    }

    GDALRasterizeOptionsFree(psOptionsToFree);

    if( eErr != CE_None )
    {
        if( bCloseOutDSOnError )
            GDALClose(hDstDS);
        return NULL;
    }

    return hDstDS;
}
int main( int argc, char ** argv )

{
    int i, b3D = FALSE;
    int bInverse = FALSE;
    const char *pszSrcFilename = NULL;
    const char *pszDstFilename = NULL;
    char **papszLayers = NULL;
    const char *pszSQL = NULL;
    const char *pszBurnAttribute = NULL;
    const char *pszWHERE = NULL;
    std::vector<int> anBandList;
    std::vector<double> adfBurnValues;
    char **papszRasterizeOptions = NULL;
    double dfXRes = 0, dfYRes = 0;
    int bCreateOutput = FALSE;
    const char* pszFormat = "GTiff";
    int bFormatExplicitelySet = FALSE;
    char **papszCreateOptions = NULL;
    GDALDriverH hDriver = NULL;
    GDALDataType eOutputType = GDT_Float64;
    std::vector<double> adfInitVals;
    int bNoDataSet = FALSE;
    double dfNoData = 0;
    OGREnvelope sEnvelop;
    int bGotBounds = FALSE;
    int nXSize = 0, nYSize = 0;
    int bQuiet = FALSE;
    GDALProgressFunc pfnProgress = GDALTermProgress;
    OGRSpatialReferenceH hSRS = NULL;
    int bTargetAlignedPixels = FALSE;
    

    /* Check that we are running against at least GDAL 1.4 */
    /* Note to developers : if we use newer API, please change the requirement */
    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1400)
    {
        fprintf(stderr, "At least, GDAL >= 1.4.0 is required for this version of %s, "
                "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
        exit(1);
    }

    GDALAllRegister();
    OGRRegisterAll();

    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
    if( argc < 1 )
        exit( -argc );

/* -------------------------------------------------------------------- */
/*      Parse 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],"-q") || EQUAL(argv[i],"-quiet") )
        {
            bQuiet = TRUE;
            pfnProgress = GDALDummyProgress;
        }
        else if( EQUAL(argv[i],"-a") && i < argc-1 )
        {
            pszBurnAttribute = argv[++i];
        }
        else if( EQUAL(argv[i],"-b") && i < argc-1 )
        {
            if (strchr(argv[i+1], ' '))
            {
                char** papszTokens = CSLTokenizeString( argv[i+1] );
                char** papszIter = papszTokens;
                while(papszIter && *papszIter)
                {
                    anBandList.push_back(atoi(*papszIter));
                    papszIter ++;
                }
                CSLDestroy(papszTokens);
                i += 1;
            }
            else
            {
                while(i < argc-1 && ArgIsNumeric(argv[i+1]))
                {
                    anBandList.push_back(atoi(argv[i+1]));
                    i += 1;
                }
            }
        }
        else if( EQUAL(argv[i],"-3d")  )
        {
            b3D = TRUE;
            papszRasterizeOptions = 
                CSLSetNameValue( papszRasterizeOptions, "BURN_VALUE_FROM", "Z");
        }
        else if( EQUAL(argv[i],"-i")  )
        {
            bInverse = TRUE;
        }
        else if( EQUAL(argv[i],"-at")  )
        {
            papszRasterizeOptions = 
                CSLSetNameValue( papszRasterizeOptions, "ALL_TOUCHED", "TRUE" );
        }
        else if( EQUAL(argv[i],"-burn") && i < argc-1 )
        {
            if (strchr(argv[i+1], ' '))
            {
                char** papszTokens = CSLTokenizeString( argv[i+1] );
                char** papszIter = papszTokens;
                while(papszIter && *papszIter)
                {
                    adfBurnValues.push_back(atof(*papszIter));
                    papszIter ++;
                }
                CSLDestroy(papszTokens);
                i += 1;
            }
            else
            {
                while(i < argc-1 && ArgIsNumeric(argv[i+1]))
                {
                    adfBurnValues.push_back(atof(argv[i+1]));
                    i += 1;
                }
            }
        }
        else if( EQUAL(argv[i],"-where") && i < argc-1 )
        {
            pszWHERE = argv[++i];
        }
        else if( EQUAL(argv[i],"-l") && i < argc-1 )
        {
            papszLayers = CSLAddString( papszLayers, argv[++i] );
        }
        else if( EQUAL(argv[i],"-sql") && i < argc-1 )
        {
            pszSQL = argv[++i];
        }
        else if( EQUAL(argv[i],"-of") && i < argc-1 )
        {
            pszFormat = argv[++i];
            bFormatExplicitelySet = TRUE;
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-init") && i < argc - 1 )
        {
            if (strchr(argv[i+1], ' '))
            {
                char** papszTokens = CSLTokenizeString( argv[i+1] );
                char** papszIter = papszTokens;
                while(papszIter && *papszIter)
                {
                    adfInitVals.push_back(atof(*papszIter));
                    papszIter ++;
                }
                CSLDestroy(papszTokens);
                i += 1;
            }
            else
            {
                while(i < argc-1 && ArgIsNumeric(argv[i+1]))
                {
                    adfInitVals.push_back(atof(argv[i+1]));
                    i += 1;
                }
            }
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-a_nodata") && i < argc - 1 )
        {
            dfNoData = atof(argv[i+1]);
            bNoDataSet = TRUE;
            i += 1;
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-a_srs") && i < argc-1 )
        {
            hSRS = OSRNewSpatialReference( NULL );

            if( OSRSetFromUserInput(hSRS, argv[i+1]) != OGRERR_NONE )
            {
                fprintf( stderr, "Failed to process SRS definition: %s\n", 
                         argv[i+1] );
                exit( 1 );
            }

            i++;
            bCreateOutput = TRUE;
        }   

        else if( EQUAL(argv[i],"-te") && i < argc - 4 )
        {
            sEnvelop.MinX = atof(argv[++i]);
            sEnvelop.MinY = atof(argv[++i]);
            sEnvelop.MaxX = atof(argv[++i]);
            sEnvelop.MaxY = atof(argv[++i]);
            bGotBounds = TRUE;
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-a_ullr") && i < argc - 4 )
        {
            sEnvelop.MinX = atof(argv[++i]);
            sEnvelop.MaxY = atof(argv[++i]);
            sEnvelop.MaxX = atof(argv[++i]);
            sEnvelop.MinY = atof(argv[++i]);
            bGotBounds = TRUE;
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-co") && i < argc-1 )
        {
            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
            bCreateOutput = TRUE;
        }
        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();
            }
            i++;
            bCreateOutput = TRUE;
        }
        else if( (EQUAL(argv[i],"-ts") || EQUAL(argv[i],"-outsize")) && i < argc-2 )
        {
            nXSize = atoi(argv[++i]);
            nYSize = atoi(argv[++i]);
            if (nXSize <= 0 || nYSize <= 0)
            {
                printf( "Wrong value for -outsize parameters\n");
                Usage();
            }
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-tr") && i < argc-2 )
        {
            dfXRes = atof(argv[++i]);
            dfYRes = fabs(atof(argv[++i]));
            if( dfXRes == 0 || dfYRes == 0 )
            {
                printf( "Wrong value for -tr parameters\n");
                Usage();
            }
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-tap") )
        {
            bTargetAlignedPixels = TRUE;
            bCreateOutput = TRUE;
        }
        else if( pszSrcFilename == NULL )
        {
            pszSrcFilename = argv[i];
        }
        else if( pszDstFilename == NULL )
        {
            pszDstFilename = argv[i];
        }
        else
            Usage();
    }

    if( pszSrcFilename == NULL || pszDstFilename == NULL )
    {
        fprintf( stderr, "Missing source or destination.\n\n" );
        Usage();
    }

    if( adfBurnValues.size() == 0 && pszBurnAttribute == NULL && !b3D )
    {
        fprintf( stderr, "At least one of -3d, -burn or -a required.\n\n" );
        Usage();
    }

    if( bCreateOutput )
    {
        if( dfXRes == 0 && dfYRes == 0 && nXSize == 0 && nYSize == 0 )
        {
            fprintf( stderr, "'-tr xres yes' or '-ts xsize ysize' is required.\n\n" );
            Usage();
        }
    
        if (bTargetAlignedPixels && dfXRes == 0 && dfYRes == 0)
        {
            fprintf( stderr, "-tap option cannot be used without using -tr\n");
            Usage();
        }

        if( anBandList.size() != 0 )
        {
            fprintf( stderr, "-b option cannot be used when creating a GDAL dataset.\n\n" );
            Usage();
        }

        int nBandCount = 1;

        if (adfBurnValues.size() != 0)
            nBandCount = adfBurnValues.size();

        if ((int)adfInitVals.size() > nBandCount)
            nBandCount = adfInitVals.size();

        if (adfInitVals.size() == 1)
        {
            for(i=1;i<=nBandCount - 1;i++)
                adfInitVals.push_back( adfInitVals[0] );
        }

        int i;
        for(i=1;i<=nBandCount;i++)
            anBandList.push_back( i );
    }
    else
    {
        if( anBandList.size() == 0 )
            anBandList.push_back( 1 );
    }

/* -------------------------------------------------------------------- */
/*      Open source vector dataset.                                     */
/* -------------------------------------------------------------------- */
    OGRDataSourceH hSrcDS;

    hSrcDS = OGROpen( pszSrcFilename, FALSE, NULL );
    if( hSrcDS == NULL )
    {
        fprintf( stderr, "Failed to open feature source: %s\n", 
                 pszSrcFilename);
        exit( 1 );
    }

    if( pszSQL == NULL && papszLayers == NULL )
    {
        if( OGR_DS_GetLayerCount(hSrcDS) == 1 )
        {
            papszLayers = CSLAddString(NULL, OGR_L_GetName(OGR_DS_GetLayer(hSrcDS, 0)));
        }
        else
        {
            fprintf( stderr, "At least one of -l or -sql required.\n\n" );
            Usage();
        }
    }

/* -------------------------------------------------------------------- */
/*      Open target raster file.  Eventually we will add optional       */
/*      creation.                                                       */
/* -------------------------------------------------------------------- */
    GDALDatasetH hDstDS = NULL;

    if (bCreateOutput)
    {
/* -------------------------------------------------------------------- */
/*      Find the output driver.                                         */
/* -------------------------------------------------------------------- */
        hDriver = GDALGetDriverByName( pszFormat );
        if( hDriver == NULL 
            || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
        {
            int	iDr;

            printf( "Output driver `%s' not recognised or does not support\n", 
                    pszFormat );
            printf( "direct output file creation.  The following format drivers are configured\n"
                    "and support direct output:\n" );

            for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
            {
                GDALDriverH hDriver = GDALGetDriver(iDr);

                if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL )
                {
                    printf( "  %s: %s\n",
                            GDALGetDriverShortName( hDriver  ),
                            GDALGetDriverLongName( hDriver ) );
                }
            }
            printf( "\n" );
            exit( 1 );
        }

        if (!bQuiet && !bFormatExplicitelySet)
            CheckExtensionConsistency(pszDstFilename, pszFormat);
    }
    else
    {
        hDstDS = GDALOpen( pszDstFilename, GA_Update );
        if( hDstDS == NULL )
            exit( 2 );
    }

/* -------------------------------------------------------------------- */
/*      Process SQL request.                                            */
/* -------------------------------------------------------------------- */
    if( pszSQL != NULL )
    {
        OGRLayerH hLayer;

        hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszSQL, NULL, NULL ); 
        if( hLayer != NULL )
        {
            if (bCreateOutput)
            {
                std::vector<OGRLayerH> ahLayers;
                ahLayers.push_back(hLayer);

                hDstDS = CreateOutputDataset(ahLayers, hSRS,
                                 bGotBounds, sEnvelop,
                                 hDriver, pszDstFilename,
                                 nXSize, nYSize, dfXRes, dfYRes,
                                 bTargetAlignedPixels,
                                 anBandList.size(), eOutputType,
                                 papszCreateOptions, adfInitVals,
                                 bNoDataSet, dfNoData);
            }

            ProcessLayer( hLayer, hSRS != NULL, hDstDS, anBandList, 
                          adfBurnValues, b3D, bInverse, pszBurnAttribute,
                          papszRasterizeOptions, pfnProgress, NULL );

            OGR_DS_ReleaseResultSet( hSrcDS, hLayer );
        }
    }

/* -------------------------------------------------------------------- */
/*      Create output file if necessary.                                */
/* -------------------------------------------------------------------- */
    int nLayerCount = CSLCount(papszLayers);

    if (bCreateOutput && hDstDS == NULL)
    {
        std::vector<OGRLayerH> ahLayers;

        for( i = 0; i < nLayerCount; i++ )
        {
            OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i] );
            if( hLayer == NULL )
            {
                continue;
            }
            ahLayers.push_back(hLayer);
        }

        hDstDS = CreateOutputDataset(ahLayers, hSRS,
                                bGotBounds, sEnvelop,
                                hDriver, pszDstFilename,
                                nXSize, nYSize, dfXRes, dfYRes,
                                bTargetAlignedPixels,
                                anBandList.size(), eOutputType,
                                papszCreateOptions, adfInitVals,
                                bNoDataSet, dfNoData);
    }

/* -------------------------------------------------------------------- */
/*      Process each layer.                                             */
/* -------------------------------------------------------------------- */

    for( i = 0; i < nLayerCount; i++ )
    {
        OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i] );
        if( hLayer == NULL )
        {
            fprintf( stderr, "Unable to find layer %s, skipping.\n", 
                      papszLayers[i] );
            continue;
        }

        if( pszWHERE )
        {
            if( OGR_L_SetAttributeFilter( hLayer, pszWHERE ) != OGRERR_NONE )
                break;
        }

        void *pScaledProgress;
        pScaledProgress =
            GDALCreateScaledProgress( 0.0, 1.0 * (i + 1) / nLayerCount,
                                      pfnProgress, NULL );

        ProcessLayer( hLayer, hSRS != NULL, hDstDS, anBandList, 
                      adfBurnValues, b3D, bInverse, pszBurnAttribute,
                      papszRasterizeOptions, GDALScaledProgress, pScaledProgress );

        GDALDestroyScaledProgress( pScaledProgress );
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */

    OGR_DS_Destroy( hSrcDS );
    GDALClose( hDstDS );

    OSRDestroySpatialReference(hSRS);

    CSLDestroy( argv );
    CSLDestroy( papszRasterizeOptions );
    CSLDestroy( papszLayers );
    CSLDestroy( papszCreateOptions );
    
    GDALDestroyDriverManager();
    OGRCleanupAll();

    return 0;
}