打开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 );
该方法需要指明需要拷贝的文件以及要保存的文件。
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 );
如果不只是将现有文件拷贝到指定位置,则可以利用 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 );