第六节GDAL的使用一.什么是GDALGDAL(GeospatialDataAbstractionLibrary)是一个在X/MIT许可协议下的开源栅格空间数据转换库。它利用抽象数据模型来表达所支持的各种文件格式。它还有一系列命令行工具来进行数据转换和处理。GDAL提供对多种栅格数据的支持,包括Arc/InfoASCIIGrid(asc),GeoTiff(tiff),ErdasImagineImages(img),ASCIIDEM(dem)等格式。GDAL使用抽象数据模型(abstractdatamodel)来解析它所支持的数据格式,抽象数据模型包括数据集(dataset),坐标系统,仿射地理坐标转换(AffineGeoTransform),大地控制点(GCPs),元数据(Metadata),栅格波段(RasterBand),颜色表(ColorTable),子数据集域(SubdatasetsDomain),图像结构域(Image_StructureDomain),XML域(XML:Domains)。GDALMajorObject类:带有元数据的对象。GDALDdataset类:通常是从一个栅格文件中提取的相关联的栅格波段集合和这些波段的元数据;GDALDdataset也负责所有栅格波段的地理坐标转换(georeferencingtransform)和坐标系定义。GDALDriver类:文件格式驱动类,GDAL会为每一个所支持的文件格式创建一个该类的实体,来管理该文件格式。GDALDriverManager类:文件格式驱动管理类,用来管理GDALDriver类。二.GDAL的安装GDAL编译详细过程:1)网上下载最新版本的proj开源投影库,解压到c:\下然后使用VS的命令行工具进入到该目录,执行nmakemakefile.vc2)网上下载最新版本的geos几何库,解压到c:\下,双击目录下的autogen.bat,执行后然后使用VS的命令行工具进入到该目录,执行nmakemakefile.vc3)拷贝hdf和HDF5、HDF5SZLIB到C:\4)打开gdal主目录下的nmake.opt修改:#UncommentforGEOSsupportGEOS_DIR=C:\geos-3.0.4GEOS_CFLAGS=-I$(GEOS_DIR)/capi-I$(GEOS_DIR)/source/headers-DHAVE_GEOSGEOS_LIB=$(GEOS_DIR)/source/geos_c_i.lib#UncommentthefollowingandupdatetoenableNCSAHDFRelease4support.HDF4_DIR=C:\HDFHDF4_LIB=$(HDF4_DIR)\dll\hd424m.lib$(HDF4_DIR)\dll\hm424m.lib\$(HDF4_DIR)\lib\hd424.lib$(HDF4_DIR)\lib\hm424.libWs2_32.lib#UncommentthefollowingandupdatetoenableNCSAHDFRelease5support.HDF5_DIR=C:\HDF5SZIP_DIR=C:\HDF5SZLIBHDF5_LIB=$(HDF5_DIR)\dll\hdf5dll.lib$(HDF5_DIR)\dll\hdf5_hldll.lib\$(SZIP_DIR)\dll\szlibdll.lib5)静态链接proj4编译GDAL时,你可以按需要添加其它支持,如ProJ,GeoTiff等等,添加方法只要在nmake.opt找到相关配置节,把前面的“#”去掉,即取消注释,然后修改相关的路径即可。如:nmake.opt中的PROJ.4stuff节#PROJ.4stuff#UncommentthefollowinglinestolinkPROJ.4librarystatically.Otherwise#itwillbelinkeddynamicallyduringruntime.#PROJ_FLAGS=-DPROJ_STATIC#PROJ_INCLUDE=-ID:\GDAL\proj-4.5.0\src#PROJ_LIBRARY=D:\GDAL\proj-4.5.0\src\proj_i.lib本节的作用是控制链接方式,默认是注释的,即采用动态链接方式。只需拷贝proj的动态库。若要采用静态链接方式,通过取消gdal的该节注释,并设置proj源码的对应路径即可。静态链接的好处是,加载之初就会判断库的依赖关系,这可以避免采用动态链接库而又缺少依赖库而出现莫名其妙的现象。如:#PROJ.4stuff#UncommentthefollowinglinestolinkPROJ.4librarystatically.Otherwise#itwillbelinkeddynamicallyduringruntime.PROJ_FLAGS=-DPROJ_STATICPROJ_INCLUDE=-IC:\proj-4.7.0\srcPROJ_LIBRARY=C:\proj-4.7.0\src\proj_i.lib6)去下一个版本,解压到c:\,修改frmts下leverers的CPP文件的?号。当然,如果没问题就不用修改7)打开gdal文件夹下的nmake.opt修改GDAL_HOME=C:\warmerda\bld把路径改到需要把gdal安装的地方。不改也可以。如果需要python支持(我的主要目的,没有python活不下去)修改PY_INST_DIR=$(GDAL_HOME)\pymod把路径改成python下的Lib\site-packages文件夹下。PYDIR=C:\Software\Python24改成python的安装路径。下面的参数爱改什么就把前面的#删除(要看您有没有那些库的源码),注意一下路径就可以了。后面就依次运行nmake/fmakefile.vcnmake/fmakefile.vcinstallnmake/fmakefile.vcdevinstall三.GDAL的使用首先创建工程,选择‘单文档’,工程名为‘six’,基类选择‘CView’,创建完成后在项目—six属性—配置属性—常规—字符集选择‘使用多字节字符集’。然后将GDAL相关的dll和proj等资料拷贝到工程的文件夹下。在sixview.h中需要添加引用的头文件gdal_priv.h和ogrsf_frmts.h。(1)调色板位图的显示如果我们需要显示图像,我们需要添加上节我们所使用的BitmapPainter类,并在sixview.h中引用该类的头文件“#includeinclude\BitmapPainter.h”。同时声明变量:protected:CPalBitmapPainterimage;intnWidth;intnHeight;在sixview.cpp的构造函数中为nWidth和nHeight赋值:Csixview::Csixview(){//TODO:在此处添加构造代码nWidth=0;nHeight=0;}添加OnCreat消息,生成的OnCreat函数中添加代码,用以读取图像信息,并将信息传给image。代码如下:intCTestGdalView::OnCreate(LPCREATESTRUCTlpCreateStruct){charszFilter[]=GeoTiff(*.tif)|*.tif|bmp(*.bmp)|*.bmp|AllFiles(*.*)|*.*||;//设置打开文件类型CStringfilePath();CFileDialogfileOpenDlg(TRUE,tif,NULL,OFN_HIDEREADONLY,szFilter);//打开浏览文件夹对话框if(fileOpenDlg.DoModal()==IDOK){VERIFY(filePath=fileOpenDlg.GetPathName());}elsereturn;CStringstrFilePath(filePath);//下面利用GDAL读取图像GDALDataset*poDataset;GDALAllRegister();poDataset=(GDALDataset*)GDALOpen(strFilePath,GA_ReadOnly);//用GDALOpen()函数来打开一个数据集datasetdoubleadfGeoTransform[6];intCols=poDataset-GetRasterXSize();//图像的宽度intRows=poDataset-GetRasterYSize();//图像的高度//DOUBLELeft,Top,Right,Bottom;//DOUBLEXCellSize,YCellSize;//CStringsp;//if(poDataset-GetGeoTransform(adfGeoTransform)==CE_None)//获取仿射影像//{//Left=adfGeoTransform[0];//Top=adfGeoTransform[3];//XCellSize=adfGeoTransform[1];//YCellSize=fabs(adfGeoTransform[5]);//Right=adfGeoTransform[0]+Cols*XCellSize;//Bottom=adfGeoTransform[3]-Rows*YCellSize;//}//if(poDataset-GetProjectionRef()!=NULL)//{//sp=poDataset-GetProjectionRef();//}GDALRasterBand*poBand;intBandCount=poDataset-GetRasterCount();//获得图像的波段数poBand=poDataset-GetRasterBand(1);BYTE*pafScanline;pafScanline=newBYTE[Cols];//每行所需的byte数nWidth=Cols;//OnDraw的时候需要用来调整设备区域和客户区域nHeight=Rows;image.InitialImage(Rows,Cols);//利用BitmapPainter类中的方法初始化图像//CColorTable*pTable=newCColorTable;//intColorCount=256;//pTable-SetColorCount(ColorCount);//image.CopyColorTable(pTable);//deletepTable;for(intk=0;kRows;k++){poBand-RasterIO(GF_Read,0,k,Cols,1,pafScanline,Cols,1,GDT_Byte,0,0);//将图像读入pafScanline内存中去image.CopyRowData(k,pafScanline);}delete[]pafScanline;GDALClose(poDataset);//关闭GDALInvalidate();//使视图无效,然后刷新}现在我就只需将图像显示出来就是了,图像的显示当然要在OnDraw函数中编写:voidCsixview::OnDraw(CDC*pDC){CTestGdalDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);if(!pDoc)return;CRectrect;GetClientRect(rect);//获得客户区范围image.PaintDIB(pDC-m_hDC,CRect(0,0,nWidth,nHeigh