简体   繁体   中英

C++ Implementation of the GDAL Algorithm GDALFillNodata()

Looking for some help with some C++ code to implement/call the GDALFillNoData() algorithm. I already have a working version using python and gdal, which is somewhat slow filling elevation DEMs (1.5GB). I'm curious if this is possible. I've written the code for a command line application and posted it here. File paths are hard coded at the moment. It builds (CodeBlocks 16.1/MinGW) and runs in but then crashes.

I'm not a C++ programmer, though I wish I were, but I'm trying to understand the language better. I'm moderately decent at python. I'm likely missing some thing basic here that's normal to C++.

There likely code that's been commented out through testing. So if something doesn't make sense that's why.

Here's the Code:

#include <iostream>
#include "gdal.h"
#include "gdal_priv.h"
#include "cpl_conv.h"
#include "gdal_alg.h"

int main()
{
    GDALAllRegister();
    //CPLPushErrorHandler(CPLQuietErrorHandler);

    // Read/Write Files
    const char *input = "D:/myIn.tif";

    GDALDataset *pSrcDataset;
    //GDALRasterBandH hMaskBand;
    GDALRasterBand  *poBand;
    //CPLErr maskBand;
    int maskFlags;
    int noData;
    double maxSearch = 10.0;
    int maxInt = 1;
    int nBlockXSize, nBlockYSize;
    double adfGeoTransform[6];
    //CPLErr eErr;

    pSrcDataset = (GDALDataset*) GDALOpen(input, GA_Update);
    CPLAssert( pSrcDataset != NULL );

    poBand = pSrcDataset->GetRasterBand( 1 );
    poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
    printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
           nBlockXSize, nBlockYSize,
           GDALGetDataTypeName(poBand->GetRasterDataType()),
           GDALGetColorInterpretationName(
           poBand->GetColorInterpretation()) );

    noData = pSrcDataset->GetRasterBand(1)->GetNoDataValue();
    printf( "No Data Value = %i\n",noData );

    printf( "Driver: %s/%s\n",
           pSrcDataset->GetDriver()->GetDescription(),
           pSrcDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) );

    printf( "Size is %dx%dx%d\n",
           pSrcDataset->GetRasterXSize(), pSrcDataset->GetRasterYSize(),
           pSrcDataset->GetRasterCount() );

    if( pSrcDataset->GetProjectionRef()  != NULL )
        printf( "Projection is `%s'\n", pSrcDataset->GetProjectionRef() );

    if( pSrcDataset->GetGeoTransform( adfGeoTransform ) == CE_None )
        printf( "Origin = (%.6f,%.6f)\n", adfGeoTransform[0], 
               adfGeoTransform[3] );
        printf( "Pixel Size = (%.6f,%.6f)\n",adfGeoTransform[1], 
               adfGeoTransform[5] );

    //maskBand = pSrcDataset->GetRasterBand(1)->GetMaskBand();

    //hMaskBand = GDALGetMaskBand( maskBand );
    //hMaskBand = pSrcDataset->GetRasterBand(1)->GetNoDataValue();
    maskFlags = pSrcDataset->GetRasterBand(1)->GetMaskFlags();
    printf ( "Mask Flags = %i\n", maskFlags );

    printf ( "Processing image\n" );

    // Ignore that this is on two lines here
    GDALFillNodata(pSrcDataset, pSrcDataset->GetRasterBand(1)- 
    >GetMaskBand(), maxSearch, 0, maxInt, NULL, NULL, NULL); 
    //CPLAssert( eErr == CE_None);

    GDALClose(pSrcDataset);

    return 0;
}

Some errors that I'm getting when running this code (see image links). The process returns a 255 which is I think something that is unique to CodeBlocks?

Program Crashes

Process returns 255

Here is the python implementation. Pretty straight forward. Is None the same as NULL? Because one of the errors I got when using NULL as the hMaskBand ( rasterfill.cpp )

#Run the gdal fill
    ET = gdal.Open(infile, GA_Update)
    ETband = ET.GetRasterBand(1)

    result = gdal.FillNodata(targetBand = ETband, maskBand = None, 
    maxSearchDist = 500, smoothingIterations = 1)

    print result # return 0

    ET = None

Please let me know if you need more information. Knowing what little I know about C++ it's probably my build environment. :)

Thanks, Heath

As a follow up for the comments above, the problem is the fact that the first argument given to the GDALFillNoData API is a GDALDataset* instead of a GDALRasterBand*.

But I've been struggling too much with GDAL to keep myself from giving a much explanatory answer.

The implementation of the GDAL lib is very C oriented, while it is indeed written using C++ features (eg classes). So, you will find that in many of the available APIs the arguments are not referring to types defined in the library. Instead, they use typedef like the GDALRasterBandH , that are indeed alias to the void* type.

This has the nasty effect that, whatever type of argument you feed to the compiler, it won't complain, hence you will get a lot of errors at runtime if you make such (very common) mistakes.

Why they do this? I think it was a way to exploit PIMPL in order to avoid the compiler to work on several translation units , every time one of this classes was modified.

The real problem of this approach is that you lose all the benefits from static type checking , ie the compiler telling you when there is a type mismatch. As a side note, this is not a critics to the GDAL lib (thank God we have it!! And it is a huge and very useful project), it's just the way it is.

By the way, I'm currently working on a C++ opensource project, Rasterix , that is meant to be a user friendly GUI to GDAL tools for raster datasets. Do not take it as do it like me hint, as this app still needs proper testing, but there is a lot of GDAL APIs use cases there that may help if you need sort of examples on how to use them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM