GDAL学习笔记——读取和创建栅格数据集

打开栅格文件

打开GDAL支持的栅格数据之前需要注册驱动,GDALAllRegister()函数将尝试注册所有已知的驱动,包含那些用GDALDriverManager::AutoLoadDrivers()函数自动加载的.so文件。

    GDALAllRegister();
    GDALDataset *poDataset;
    const char* pszFileName = "C:\\Users\\jinun\\Desktop\\SCRH\\dataset\\sub-TM-Spot-GS.img";
    poDataset = (GDALDataset *)GDALOpen( pszFileName, GA_ReadOnly);
    if( poDataset == NULL){
        printf( "Open the file failed!");
    }
    else{
        printf( "Open succeed!\n" );
    }

如果GDALOpen()函数返回NULL,则打开失败,失败信息可以通过CPLError()函数获取。

获取数据集信息

可以使用adfGeoTransform[]表示一些信息:

adfGeoTransform[0] /* top left x */
adfGeoTransform[1] /* w-e pixel resolution */
adfGeoTransform[2] /* 0 */
adfGeoTransform[3] /* top left y */
adfGeoTransform[4] /* 0 */
adfGeoTransform[5] /* n-s pixel resolution (negative value) */

下面代码是获取数据集中的一些信息:

    double adfGeoTransform[6];
    printf( "Driver: %s / %s\n",
            poDataset->GetDriver()->GetDescription(),
            poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ));
    printf( "Size is %dx%dx%d\n",
            poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
            poDataset->GetRasterCount());
    if ( poDataset->GetProjectionRef() != NULL)
    {
        printf( "Projection is '%s'\n",
                poDataset->GetProjectionRef() );
    }
    if (poDataset->GetGeoTransform( adfGeoTransform ) == CE_None){
        printf( "Origin = (%.6f,%.6f)\n",
                adfGeoTransform[0], adfGeoTransform[3] );
        printf( "Pixel Size = (%.6f,%.6f)\n",
                adfGeoTransform[1], adfGeoTransform[5] );
    }

获取栅格波段

获取栅格波段可以通过GDAL来完成,同时还会获得元数据、块大小、颜色表以及其他不同的信息。

    GDALRasterBand *poBand;
    int nBlockXSize, nBlockYSize;
    int nGotMin, nGotMax;
    double adfMinMax[2];
    poBand = poDataset->GetRasterBand( 1 );
    poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
    printf( "Block = %dx%d Type = %s, ColorInterp = %s\n",
            nBlockXSize, nBlockYSize,
            GDALGetDataTypeName( poBand->GetRasterDataType()),
            GDALGetColorInterpretationName( poBand->GetColorInterpretation()) );
    adfMinMax[0] = poBand->GetMinimum( &nGotMin );
    adfMinMax[1] = poBand->GetMaximum( &nGotMax );
    if( !( nGotMin && nGotMax )){
        GDALComputeRasterMinMax( (GDALRasterBandH)poBand, TRUE, adfMinMax );
    }
    printf( "Min = %.3fd, Max = %.3f\n",adfMinMax[0], adfMinMax[1] );

    if( poBand->GetOverviewCount() > 0 ){
        printf( "Band has %d overviews.\n", poBand->GetOverviewCount() );
    }
    if( poBand->GetColorTable() != NULL){
        printf( "Band has a color table with %d entries.\n",
                poBand->GetColorTable()->GetColorEntryCount() );
    }

读取栅格数据

有几种方法来读取栅格数据,最常用的是通过 GDALRasterBand::RasterIO()方法,这种方法会自动的进行数据类型转换,向上或向下采样。下面代码是读取相同大小缓冲区的数据的第一行,然后将其转换为浮点型。

float *pafScanline;
int   nXSize = poBand->GetXSize();
pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
poBand->RasterIO( GF_Read, 0, 0, nXSize, 1,
                  pafScanline, nXSize, 1, GDT_Float32,
                  0, 0 );

关于GDALRasterBand::RasterIO()的使用,可以参考这篇博客。

创建文件

在GDAL支持的文件格式中,如果格式驱动支持创建,则可以创建新文件。有两种方法创建新文件:CreateCopy()和Create()。第一个方法是调用CreateCopy()函数,传递一个需要拷贝的源数据集参数。第二个方法是调用Create()函数。创建新文件的所有驱动支持CreateCopy方法,只有部分驱动支持Create方法。
为了确定驱动支持CreateCopy方法还是Create方法,需要检查格式驱动对象中的DCAP_CREATE 和DCAP_CREATECOPY 元数据。在调用GetDriverByName函数之前,需要用GDALAllRegister()进行驱动注册。下面代码是测试该驱动支持哪种方法:

    GDALAllRegister();
    /*
     * 目前,子数据集支持的驱动有ADRG、ECRGTOC、GEORASTER、GTiff、HDF4、HDF5、netCDF、
     * NITF、NTv2、OGDI、PDF、PostGISRaster、Rasterlite、RPFTOC、RS2、WCS和WMS。
     */
    const char *pszFormat = "GTiff";
    GDALDriver *poDriver;
    char **papszMetadata;
    poDriver = GetGDALDriverManager()->GetDriverByName( pszFormat );
    if (poDriver == NULL){
        exit(1);
    }
    papszMetadata = poDriver->GetMetadata();
    if (CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ))
        printf( "Driver %s supports Create() method.\n", pszFormat );
    if ( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE) )
        printf( "Driver %s supports CreateCopy() method.\n", pszFormat );

使用CreateCopy方法

该方法需要指明需要拷贝的文件以及要保存的文件。

 const char* pszSrcFileName = "C:\\Users\\jinun\\SCRH\\dataset\\sub-TM-Spot-GS.img";
    const char* pszDstFileName = "C:\\Users\\jinun\\SCRH\\dataset\\dst.img";;

    GDALDataset *poSrcDS = (GDALDataset *) GDALOpen( pszSrcFileName, GA_ReadOnly );
    GDALDataset *poDstDS;
    poDstDS = poDriver->CreateCopy( pszDstFileName, poSrcDS, FALSE,
                                    NULL, NULL, NULL );
    if( poDstDS != NULL){
        GDALClose( (GDALDatasetH) poDstDS );
    }
    GDALClose( (GDALDatasetH) poSrcDS );

当需要传入更多的参数并且显示拷贝的进度,可以进行如下设计:

    char **papszOptions = NULL;
    papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
    papszOptions = CSLSetNameValue( papszOptions, "COMPRESS" ,"PACKBITS" );
    poDstDS = poDriver->CreateCopy( pszDstFileName, poSrcDS, FALSE,
                                    papszOptions, GDALTermProgress, NULL);

    if( poDstDS != NULL){
            GDALClose( (GDALDatasetH) poDstDS );
        }
        GDALClose( (GDALDatasetH) poSrcDS );

使用Create方法

如果不只是将现有文件拷贝到指定位置,则可以利用 GDALDriver::Create()方法创建新的文件。create()方法接受参数和createcopy()类似,但是必须要提供图像的大小、波段数及波段类型。

GDALDataset *poDstDS;
char **papszOptions = NULL;
poDstDS = poDriver->Create( pszDstFilename, 512, 512, 1, GDT_Byte,
                            papszOptions );

当数据集创建成功,所有恰当的元数据和栅格数据信息就必须写到新建的文件中。

double adfGeoTranform[6] = { 444720, 30, 0, 3751320, 0, -30 };
    OGRSpatialReference oSRS;//该类需要#include "ogr_spatialref.h"头文件
    char *pszSRS_WKT = NULL;
    GDALRasterBand *poBand;
    GByte abyRaster[512 * 512];
    poDstDS->SetGeoTransform( adfGeoTranform );

    oSRS.SetUTM( 11, TRUE );
    oSRS.SetWellKnownGeogCS( "NAD27" );
    oSRS.exportToWkt( &pszSRS_WKT );
    CPLFree( pszSRS_WKT );

    poBand = poDstDS->GetRasterBand(1);
    poBand->RasterIO( GF_Write, 0, 0, 512, 512,
                      abyRaster, 512, 512, GDT_Byte, 0, 0);
    GDALClose( (GDALDatasetH) poDstDS );

你可能感兴趣的:(GDAL学习笔记)