GDAL API Tutorial中文翻译(只介绍C++部分)

来源 https://www.gdal.org/gdal_tutorial.html (2018-10-28版)

1 Opening The File(打开文件)
原文:
Before opening a GDAL supported raster datastore it is necessary to register drivers. There is a driver for each supported format. Normally this is accomplished with the GDALAllRegister() function which attempts to register all known drivers, including those auto-loaded from .so files using GDALDriverManager::AutoLoadDrivers(). If for some applications it is necessary to limit the set of drivers it may be helpful to review the code from gdalallregister.cpp. Python automatically calls GDALAllRegister() when the gdal module is imported.

Once the drivers are registered, the application should call the free standing GDALOpen() function to open a dataset, passing the name of the dataset and the access desired (GA_ReadOnly or GA_Update).
翻译:
打开GDAL的光栅数据之前,必须注册驱动.每一个被GDAL支持的格式都对应一个驱动.通常只要一次性调用函数GDALAllRegister(),就可以把所有驱动都注册完毕.(下略)
驱动注册完成后,你的程序就要利用GDALOpen()函数打开一个数据集.这个函数的两个输入参数分别是数据集的名字,以及打开方式(GA_ReadOnly只读,GA_Update更新)。

C++代码

#include "gdal_priv.h"
#include "cpl_conv.h" // for CPLMalloc()
int main()
{
    GDALDataset  *poDataset;
    GDALAllRegister();
    //驱动注册完成后,你的程序就要利用GDALOpen()函数打开一个数据集.这个函数的两个输入参数分别是数据集的名字,以及打开方式
    poDataset = (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
    if( poDataset == NULL )
    {
        ...;


    
原文:
Note that if GDALOpen() returns NULL it means the open failed, and that an error messages will already have been emitted via CPLError(). If you want to control how errors are reported to the user review the CPLError() documentation. Generally speaking all of GDAL uses CPLError() for error reporting. Also, note that pszFilename need not actually be the name of a physical file (though it usually is). It's interpretation is driver dependent, and it might be an URL, a filename with additional parameters added at the end controlling the open or almost anything. Please try not to limit GDAL file selection dialogs to only selecting physical files.
翻译:
假如GDALOpen()的返回值是NULL,说明数据集打开失败。此时错误信息会通过CPLError()发送出来,其使用方法参见对应的文档。总的来说,所有的错误都是通过CPLError()报告的。pszFilename也不一定是一个实体文件的名称(不一定是,但往往是实体文件的名称)。具体如何理解pszFilename的含义取决于具体的驱动:含义可以是URL,或者文件名+额外参数,或者其它什么东西。所以启动GDAL的文件选择对话框时,请不要将选择范围仅限于实体文件。

2 Getting Dataset Infomation(获取数据集信息)
原文:
As described in the GDAL Data Model, a GDALDataset contains a list of raster bands, all pertaining to the same area, and having the same resolution. It also has metadata, a coordinate system, a georeferencing transform, size of raster and various other information.

In the particular, but common, case of a "north up" image without any rotation or shearing, the georeferencing transform takes the following form :
adfGeoTransform[0] /* 左上角X坐标 */
adfGeoTransform[1] /* 西-东 方向像素分辨率 */
adfGeoTransform[2] /* 0 */
adfGeoTransform[3] /* 左上角Y坐标 */
adfGeoTransform[4] /* 0 */
adfGeoTransform[5] /* 北-南 方向像素分辨率(前面加负号) */
In the general case, this is an affine transform.

翻译:
正如在GDAL 数据模型里所说,数据集包括一系列的波段(可见光、红外等--译者注),这些波段对应同一个区域,且分辨率相同。数据集还包括元数据、坐标系、地理参考变换,光栅尺寸等信息。
着重讲一下,一副正北指向正上,并且没有任何旋转和拉伸的图片,其地理参考变换都保持如下形式:(略)
这通常是仿射变换。
C++代码:
 

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] );
}

3 Fetching a Raster Band(获取光栅波段)
原文:
At this time access to raster data via GDAL is done one band at a time. Also, there is metadata, block sizes, color tables, and various other information available on a band by band basis. The following codes fetches a GDALRasterBand object from the dataset (numbered 1 through GetRasterCount()) and displays a little information about it.
翻译:
打开数据集后,程序员可以每次读取一个光栅波段的数据。此外,每个波段还有各自的元数据、图像尺寸、色表等信息。下面的代码从数据集里取出一个GDALRasterBand对象(对象编号从1开始,最后一个编号用函数GetRasterCount()返回)并显示一些它的信息。
C++代码:

GDALRasterBand  *poBand;
int             nBlockXSize, nBlockYSize;
int             bGotMin, bGotMax;
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( &bGotMin );
adfMinMax[1] = poBand->GetMaximum( &bGotMax );
if( ! (bGotMin && bGotMax) )
    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() );

4 Reading Raster Data(读取光栅数据)
原文:
There are a few ways to read raster data, but the most common is via the GDALRasterBand::RasterIO() method. This method will automatically take care of data type conversion, up/down sampling and windowing. The following code will read the first scanline of data into a similarly sized buffer, converting it to floating point as part of the operation.

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


The pafScanline buffer should be freed with CPLFree() when it is no longer used.
The RasterIO call takes the following arguments.

CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
                                 int nXOff, int nYOff, int nXSize, int nYSize,
                                 void * pData, int nBufXSize, int nBufYSize,
                                 GDALDataType eBufType,
                                 int nPixelSpace,
                       int nLineSpace )


Note that the same RasterIO() call is used to read, or write based on the setting of eRWFlag (either GF_Read or GF_Write). The nXOff, nYOff, nXSize, nYSize argument describe the window of raster data on disk to read (or write). It doesn't have to fall on tile boundaries though access may be more efficient if it does.

The pData is the memory buffer the data is read into, or written from. It's real type must be whatever is passed as eBufType, such as GDT_Float32, or GDT_Byte. The RasterIO() call will take care of converting between the buffer's data type and the data type of the band. Note that when converting floating point data to integer RasterIO() rounds down, and when converting source values outside the legal range of the output the nearest legal value is used. This implies, for instance, that 16bit data read into a GDT_Byte buffer will map all values greater than 255 to 255, the data is not scaled!

The nBufXSize and nBufYSize values describe the size of the buffer. When loading data at full resolution this would be the same as the window size. However, to load a reduced resolution overview this could be set to smaller than the window on disk. In this case the RasterIO() will utilize overviews to do the IO more efficiently if the overviews are suitable.

The nPixelSpace, and nLineSpace are normally zero indicating that default values should be used. However, they can be used to control access to the memory data buffer, allowing reading into a buffer containing other pixel interleaved data for instance.
翻译:
读取光栅数据的办法不止一个,但是通常使用的函数式GDALRasterBand::RasterIO()这个办法可以自动执行数据类型转换、采样、开窗等操作。下面的代码自动把光栅数据的首行数据拷贝到大小相似的另一块内存里,同时把数据转化为浮点型。
pafScanline通过CPLMalloc申请,通过CPLFree()释放。eRWFlag决定RasterIO函数是向光栅数据读取还是写入(GF_Read是读取,GF_WRITE是写入)。nXOff, nYOff,定位了被操作的光栅数据的首地址在第几列,第几行。nXSize和nYSize代表被操作数据的宽度和高度。被操作的数据块的边界不需要与光栅数据的边界相同,但是假如重合,会提高读写效率。
与光栅数据的读写相对应的另一块数据地址是pData。从(向)光栅读取(写入)的数据将写入(读取自)pData。pData的类型必须与eBufType一致,如GDT_Float32或GDT_Byte。(假如光栅数据的类型与pData类型不同)RasterIO()将自动完成类型转换。注意,从浮点向整形转化时,小数点后面的被舍弃。当被读取一方的数据超过了被写入方数据类型的表数范围时,被写入方的数据将饱和。比方说,16比特的数据(表数范围0-65535)写入字节型数据(0-255,译者注)时,所有超过255的数据都作为255写入!
nBufXSzie与nBufYSize描述pData的尺寸。假如pData和光栅保持同等分辨率,那么pdata和光栅的尺寸将相等。假如(从光栅向转化pData后),分辨率降低,则pData占据的内存将少于原始数据。这时,RasterIO将采用缩略图来实现更高效的转化。
nPixelSpace和nLineSpace通常为0。假如不为0,RasterIO可以实现隔行/隔列的数据转移。

5 Closing the Dataset(关闭数据集)
原文:
Please keep in mind that GDALRasterBand objects are owned by their dataset, and they should never be destroyed with the C++ delete operator. GDALDataset's can be closed by calling GDALClose() (it is NOT recommended to use the delete operator on a GDALDataset for Windows users because of known issues when allocating and freeing memory across module boundaries. See the relevant topic on the FAQ). Calling GDALClose will result in proper cleanup, and flushing of any pending writes. Forgetting to call GDALClose on a dataset opened in update mode in a popular format like GTiff will likely result in being unable to open it afterwards.
翻译:
请牢记,波段数据的拥有者是数据集,因此不能用c++的 delete操作释放。数据集可以用GDALClose()关闭(在windows平台上,不建议用delete操作直接删除,这可能导致边界内存无法释放,见FAQ)。只有调用GDALClose()此能妥善释放内存,并且完成等待中的写操作(假如有的话)。假如有一个更新模式下的数据集,正在写入GTiff数据,但程序退出时没有用GDALClose()关闭,则这个Tiff文件很可能无法再正常打开。

6 Techniques for Creating Files(打开文件的手段)
原文:
New files in GDAL supported formats may be created if the format driver supports creation. There are two general techniques for creating files, using CreateCopy() and Create(). The CreateCopy method involves calling the CreateCopy() method on the format driver, and passing in a source dataset that should be copied. The Create method involves calling the Create() method on the driver, and then explicitly writing all the metadata, and raster data with separate calls. All drivers that support creating new files support the CreateCopy() method, but only a few support the Create() method.

To determine if a particular format supports Create or CreateCopy it is possible to check the DCAP_CREATE and DCAP_CREATECOPY metadata on the format driver object. Ensure that GDALAllRegister() has been called before calling GetDriverByName(). In this example we fetch a driver, and determine whether it supports Create() and/or CreateCopy().
Note that a number of drivers are read-only and won't support Create() or CreateCopy().

C++代码:

#include "cpl_string.h"
...
    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 );


翻译:
创建文件的办法有两个:Create()和CreateCopy().CreateCopy()通过对应格式的驱动来调用CreateCopy函数,并且在函数输入参数里注明数据源.Create()也通过对应格式的驱动调用Create函数,调用Create函数之后,再调用其它函数,写入元数据,光栅数据等.所有驱动,只要支持创建新文件,都支持CreateCopy方法,只有少数支持Create方法.
通过查询元数据DCAP_CREATE/DCAP_CREATECOPY,检查一个驱动是否支持Create/CreateCopy.确保调用GetDriverByName之前先调用GDALAllRegister().下面的例子,我们检查驱动是否支持Create/CreateCopy.
注意,有一些只读驱动,不支持Create/CreateCopy

7 Using CreateCopy()(使用CreateCopy)
原文:
The GDALDriver::CreateCopy() method can be used fairly simply as most information is collected from the source dataset. However, it includes options for passing format specific creation options, and for reporting progress to the user as a long dataset copy takes place. A simple copy from the a file named pszSrcFilename, to a new file named pszDstFilename using default options on a format whose driver was previously fetched might look like this:

GDALDataset *poSrcDS =
   (GDALDataset *) GDALOpen( pszSrcFilename, GA_ReadOnly );
GDALDataset *poDstDS;
poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE,
                                NULL, NULL, NULL );
/* Once we're done, close properly the dataset */
if( poDstDS != NULL )
    GDALClose( (GDALDatasetH) poDstDS );
GDALClose( (GDALDatasetH) poSrcDS );

Note that the CreateCopy() method returns a writable dataset, and that it must be closed properly to complete writing and flushing the dataset to disk. In the Python case this occurs automatically when "dst_ds" goes out of scope. The FALSE (or 0) value used for the bStrict option just after the destination filename in the CreateCopy() call indicates that the CreateCopy() call should proceed without a fatal error even if the destination dataset cannot be created to exactly match the input dataset. This might be because the output format does not support the pixel datatype of the input dataset, or because the destination cannot support writing georeferencing for instance.

A more complex case might involve passing creation options, and using a predefined progress monitor like this:

#include "cpl_string.h"
...
    char **papszOptions = NULL;
    papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
    papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE,
                                    papszOptions, GDALTermProgress, NULL );
    /* Once we're done, close properly the dataset */
    if( poDstDS != NULL )
        GDALClose( (GDALDatasetH) poDstDS );
    CSLDestroy( papszOptions );


翻译:
CreateCopy函数使用较简单,因为多数信息可以从源数据集获得.但是,函数输入参数里包括与格式相关的创建选项,以及向用户回报拷贝进度的选项.下面的例子展示的是从pszSrcFilename向pszDstFilename拷贝的过程,文件格式由驱动决定.
注意,CreateCopy返回一个可写的数据集,它必须采用合适的方法关闭,以保证待写数据写入磁盘.在例子里,紧跟在目标文件名pszDstFilename后的选项为FASLE,含义是,即使目标文件创建后,与原数据集不能完全一致,CreateCopy函数也不要报"致命错误",而是要继续运行下去.这可能是因为输出的文件格式不支持源数据集的格式,或者因为输出文件不支持写入地理参考.
更复杂的例子,输入变量里包括创建选项,并且结合了一个已经定义的进度监视对象.

8 Using Create()(使用Create())
原文:
For situations in which you are not just exporting an existing file to a new file, it is generally necessary to use the GDALDriver::Create() method (though some interesting options are possible through use of virtual files or in-memory files). The Create() method takes an options list much like CreateCopy(), but the image size, number of bands and band type must be provided explicitly.

GDALDataset *poDstDS;
char **papszOptions = NULL;
poDstDS = poDriver->Create( pszDstFilename, 512, 512, 1, GDT_Byte,
                            papszOptions );
Once the dataset is successfully created, all appropriate metadata and raster data must be written to the file. What this is will vary according to usage, but a simple case with a projection, geotransform and raster data is covered here.
double adfGeoTransform[6] = { 444720, 30, 0, 3751320, 0, -30 };
OGRSpatialReference oSRS;
char *pszSRS_WKT = NULL;
GDALRasterBand *poBand;
GByte abyRaster[512*512];
poDstDS->SetGeoTransform( adfGeoTransform );
oSRS.SetUTM( 11, TRUE );
oSRS.SetWellKnownGeogCS( "NAD27" );
oSRS.exportToWkt( &pszSRS_WKT );
poDstDS->SetProjection( pszSRS_WKT );
CPLFree( pszSRS_WKT );
poBand = poDstDS->GetRasterBand(1);
poBand->RasterIO( GF_Write, 0, 0, 512, 512,
                  abyRaster, 512, 512, GDT_Byte, 0, 0 );
/* Once we're done, close properly the dataset */
GDALClose( (GDALDatasetH) poDstDS );


翻译:
假如你不是要从已有文件拷贝到新文件,那么你可以采用Create函数(还有其它办法,如虚拟文件,内存文件等).Create函数的输入格式与CreateCopy类似,但是必须明确其图片尺寸,波段数目,波段类型.
创建完成后,元数据和光栅数据都要写入新文件.其内容与具体使用有关,下面介绍一个含有投影数据,地理变换和光栅数据的例子.

猜你喜欢

转载自blog.csdn.net/liji_digital/article/details/83477063