在GDAL库中包含栅格数据的读写,矢量数据的读写,以及栅格和矢量数据的相关算法。下面主要对GDAL中栅格数据和矢量数据的体系架构做一个简单的说明。本人英文很烂,有些部分写出来的东西自己都看不懂,如果不懂,可以看英文。
一、GDAL体系架构
参考GDAL官方文档:http://www.gdal.org/gdal_datamodel.html。
GDAL使用抽象数据模型(abstract data model)来解析它所支持的数据格式,抽象数据模型包括数据集(dataset),坐标系统(Coordinate System),仿射地理坐标转换(Affine GeoTransform), 大地控制点(GCPs), 元数据(Metadata),子数据集域(Subdatasets Domain),图像结构域(Image_Structure Domain),RPC域(RPC Domain),XML域(XML:Domains),栅格波段(Raster Band),颜色表(Color Table)和快视图(Overviews)。
1、数据集(Dataset)
数据集是由栅格波段和一些相关的信息共同组成的(具体参考GDALDataset类),在一个指定的数据集中所有的波段都具有相同的大小(图像行数和列数);数据集同时负责对所有的波段定义地理坐标和投影等信息;数据集中还有一些元数据信息,这些信息是由字符串组成的一系列(名称:值)的字符串列表。
GDAL数据集是基于OpenGIS网格数据的说明来实现的。
2、坐标系统(CoordinateSystem)
数据集中的坐标系统是基于OpenGIS的WKT(WellKnown Text)字符串格式的。里面包含下面内容:
- 坐标系统名称
- 地理坐标系统名称
- 大地水准面
- 托球体名称,长半轴和扁率
- 中央经线名称和与本初子午线的偏移量
- 投影方式(如:横轴墨卡托)
- 投影参数列表(如:中央经线)
- 单位名称和与米或者弧度之间的转换系数
- 名称和坐标轴顺序
- 以上项对应的EPSG代码
更多关于OpenGIS的WKT坐标定义和相关信息,可以参考文档osr_tutorial。获取坐标系统可以使用函数 GDALDataset::GetProjectionRef(),如果该函数的返回值为"",说明该图像没有地理坐标系统。
1、仿射地理坐标转换(Affine GeoTransform)
GDAL数据集有两种方式来表示栅格行列号坐标和地理坐标之间的关系,第一种,也是最常用的,就是使用仿射变换来表示(另外一种是GCP点)。
仿射变换包含六个参数,可以使用函数 GDALDataset::GetGeoTransform()获取,图像行列号和地理空间之间的变换关系如下:
Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
在北方向上的图像中,参数GT(2)和GT(4)的值是0,GT(1)表示象元宽度,GT(5)表示象元高度。点 (GT(0),GT(3))表示图像左上角的横纵坐标值。
值得注意的是:行列号坐标系统中,图像的(0.0,0.0)坐标在图像的左上角,坐标(象元宽个数,象元高个数)表示图像的右下角坐标。图像的左上角象元的中心点坐标是(0.5,0.5)。
2、大地控制点(GCPs)
数据集中可能会包括一系列的控制点,用来确定图像的地理参考坐标。所有的控制点都是在同一个坐标系统下的(可以使用函数GDALDataset::GetGCPProjection()来获取该坐标系),每一个GCP(使用GDAL_GCP类来表示)包括下面的内容:
typedef struct { char *pszId; char *pszInfo; double dfGCPPixel; double dfGCPLine; double dfGCPX; double dfGCPY; double dfGCPZ; } GDAL_GCP;
pszId字符串表示一个唯一的字符串,用来藐视在当前数据集中的GCP点中的具体的GCP点(通常情况下,可能是由数字构成,但不是所有的情况下)。pszInfo通常是一个空字符串,但是可以用来存储用户自定义用来描述GCP的文本信息。很可能包含GCP的一些状态信息,如获取时间等。
坐标(Pixel,Line)表示GCP在图像上的位置,坐标(X,Y,Z)表示在地理参考坐标系中的位置,通常Z值是0。
GDAL数据模型中不会都包含GCP点构成的转换方程,这个工作常常在应用程序中处理。通常使用1次到5次多项式进行转换。
通常数据集包括一个仿射地理坐标变换,GCP点可能会有,有时候这两个都没有。
3、元数据(Metadata)
GDAL元数据是辅助格式和应用程序指定的数据使用一个名称/值的点对列表。名称需要能够很好的表示其作用(不含有空格或者其他特殊字符)。值可以有任意长度,可以包括任何东西除了空值(ASCII的0值)。
元数据在系统中不能处理太大的数据,如果元数据超过100kb就会导致性能下降。
一些常用的的格式的元数据都可以支持,比如在TIFF驱动返回一些了标签信息作为元数据,比如日期/时间的形式如下:
TIFFTAG_DATETIME=1999:05:11 11:29:56
元数据可以按照名称组来拆分为不同的域,默认域是没有名称的,如(NULL或者"")。一些特殊的域用于特殊的目的。
下面的元数据项目定义在默认的域中:
- AREA_OR_POINT: 可以是“Area”或者“Point”,默认为Area。表明一个像素值表示中心像元的像素值或者像元中心点的采样值。但这并不影响整个区域的地理参考信息。
- NODATA_VALUES:NODATA值。这个值是使用空格隔开的一系列的像素值,个数和波段数相同。使用这种方式是为了使所有波段都有一个NODATA值相匹配。这个元数据没有广泛的用于数据驱动,算法或者工具集中。
- MATRIX_REPRESENTATION:这个值用来表示极化SAR数据集,包含矩阵表示的数据。矩阵可以用下面的值来进行表示:
- SCATTERING 散射
- SYMMETRIZED_SCATTERING 对称散射
- COVARIANCE 协方差
- SYMMETRIZED_COVARIANCE 对称协方差
- COHERENCY 相干
- SYMMETRIZED_COHERENCY 对称相干
- KENNAUGH
- SYMMETRIZED_KENNAUGH
- POLARMETRIC_INTERP:这个元数据项用来定义多波段极化SAR数据的栅格波段。指定的矩阵表示这个波段的数据。数据集就是一个散射矩阵,比如,这个元数据可接受的值有,HH、HV、VH、VV四个。当数据集是一个协方差矩阵时,这个元数据将分别是Covariance_11、Covariance_22、Covariance_33、Covariance_12、Covariance_13、Covariance_23中的一个(因为这个矩阵本身就是一个Hermitian矩阵,即所有的数据都用来表示这个矩阵)。
4、子数据集域(Subdatasets Domain)
子数据集域中含有一个子数据集的列表。通常用来存储在一个文件的多个文件(如HDF和NITF格式),例如,一个NITF格式的文件中获取子数据集的信息如下:
SUBDATASET_1_NAME=NITF_IM:0:multi_1b.ntf
SUBDATASET_1_DESC=Image 1 of multi_1b.ntf
SUBDATASET_2_NAME=NITF_IM:1:multi_1b.ntf
SUBDATASET_2_DESC=Image 2 of multi_1b.ntf
SUBDATASET_3_NAME=NITF_IM:2:multi_1b.ntf
SUBDATASET_3_DESC=Image 3 of multi_1b.ntf
SUBDATASET_4_NAME=NITF_IM:3:multi_1b.ntf
SUBDATASET_4_DESC=Image 4 of multi_1b.ntf
SUBDATASET_5_NAME=NITF_IM:4:multi_1b.ntf
SUBDATASET_5_DESC=Image 5 of multi_1b.ntf
含有_NAME的字符串,可以使用GDALOpen()函数来进行访问子文件。含有_DESC字符串是用来方便的展示给用户选择哪个文件。
5、图像结构域(Image_Structure Domain)
在默认域的元数据用来描述图像的相关信息,这些元数据并没有以特殊的方式保存在磁盘中。意思就是说,当这些元数据信息被复制到一个新的图像中的时候,会以合适的方式存在新的图像中。此外还有一些信息是和图像的格式紧密关联的。为了防止这些信息在写入新图像的时候被复制,将这些信息存储在一个叫IMAGE_STRUCTURE的特殊域中,通常这里存储的东西不会写入到新的图像中去。
目标,在IMAGE_STRUCTURE域中定义的项目主要有下面几个。
- COMPRESSION:压缩方式用来指定数据集或者波段的压缩方式,这个是没有固定的压缩类型名称,但是一个指定的格式,如果指定压缩方式,那么在创建的时候会使用这种压缩方式进行压缩。
- NBITS:当前波段或者当前数据集的波段中真实的数据存储bit数。通常只有非标准的数据类型才会使用该值,比如TIFF图像中的1bit数据,在GDAL会使用GDT_Byte来表示。
- INTERLEAVE:这个只能用在数据集中,用来表示一个像元,一行和一个波段之间的间隔,可以用来作为读取数据的一个提示。
- PIXELTYPE:这个值会出现在一个GDT_Byte类型的波段(或者相应的数据集)中,并且会使用SIGNEDBYTE值来表示无符号byte值介于128和255之间值应该转换为-128到-1之间。
6、RPC域(RPCDomain)
RPC元数据域存储的是有理函数模型的系数,该模型表示从图像行列号与空间参考位置间的变换关系,该模型具体定义如下:
· ERR_BIAS: 偏移误差,图像上所有的点在水平轴上的偏移的中误差,-1.0表示未知。
· ERR_RAND: 随机误差,图像上所有的点在水平轴上的随机中误差,-1.0表示未知。
· LINE_OFF: 行偏移量
· SAMP_OFF: 列偏移量
· LAT_OFF: 纬度偏移量
· LONG_OFF: 经度偏移量
· HEIGHT_OFF: 高程偏移量
· LINE_SCALE: 行缩放比例
· SAMP_SCALE: 列缩放比例
· LAT_SCALE: 纬度缩放比例
· LONG_SCALE: 经度缩放比例
· HEIGHT_SCALE: 高程缩放比例
· LINE_NUM_COEFF (1-20): 行分子系数,一共20个(使用空格隔开)
· LINE_DEN_COEFF (1-20): 行分母系数,一共20个(使用空格隔开)
· SAMP_NUM_COEFF (1-20): 列分子系数,一共20个(使用空格隔开)
· SAMP_DEN_COEFF (1-20): 列分母系数,一共20个(使用空格隔开)
这些内容都是来自GeoTIFF的RPC文档(http://geotiff.maptools.org/rpc_prop.html)。
7、XML域(XML:Domains)
任何前缀是“xml:”的一个字符串,但不是名称/值这种类型的,这是一个简单的XML格式的长字符串。
8、栅格波段(Raster Band)
一个栅格波段在GDAL中使用GDALRasterBand类来进行表示。他表示一个栅格波段、通道或者图层。波段不能完全用来表示整个图像,比如一个24位的RGB图像中就含有三个波段,分别是红波段,绿波段和蓝波段。
栅格波段含有下面属性:
· 图像的宽和高,这个和数据集里面的定义一样,如果这个波段是全分辨率波段的话。(这里有个说明,GDALRasterBand还可以表示金字塔的波段,如果是金字塔的波段的话,里面的宽高就和图像的宽高不一样)。
· 数据类型(GDALDataType)。应该是Byte、UInt16、Int16、UInt32、Int32、Float32、Float64以及复数类型CInt16、CInt32、CFloat32和CFloat64中的一个。
· 块大小。通过块是读取数据最高效的方式,对于分块数据,就是一个分块大小,对于大多数图像来说,一块就是一行。
· 名称/值的元数据对,格式和数据集中的一员,但是包含的信息可能是波段特有的。
· 一个可选的波段描述字符串。
· 一个可选的用来描述NODATA值的像元值。
· 一个可选的NODATA值表示的掩码波段或者在某些时候作为透明通道。
· 可选的类别名称列表(用于分类图)
· 可选的最大值和最小值。
· 可选的偏移量和缩放比例,用来对图像的像素值进行变换,比如变换高度到米等。
· 图像单位名称,可选。比如可以用来表示高程数据的海拔。
· 波段的颜色信息,是下面值中的某一个:
o GCI_Undefined:默认值,未知
o GCI_GrayIndex: 灰度图像
o GCI_PaletteIndex:颜色表图像
o GCI_RedBand: RGBA图像的R部分
o GCI_GreenBand: RGBA图像的G部分
o GCI_BlueBand: RGBA图像的B部分
o GCI_AlphaBand: RGBA图像的Alpha部分
o GCI_HueBand: HLS图像的色调部分
o GCI_SaturationBand: HLS图像的饱和度部分
o GCI_LightnessBand:HLS图像的亮度部分
o GCI_CyanBand: CMYK图像的青色部分
o GCI_MagentaBand: CMYK图像的品红部分
o GCI_YellowBand: CMYK图像的黄色部分
o GCI_BlackBand: CMYK图像的黑色部。
· 颜色表,下面有更详细的说明。
· 如果金字塔可用,含有一些关于金字塔的信息。
9、颜色表(Color Table)
颜色表的定义如下,使用C语言的风格定义:
typedef struct { /- gray, red, cyan or hue-/ short c1; /- green, magenta, orlightness -/ short c2; /- blue, yellow, orsaturation -/ short c3; /- alpha or blackband -/ short c4; } GDALColorEntry;
颜色表通常是颜色调色板的一个值,对于c1/c2/c3/c4 四个值对应不同的调色板,其表示的含义不同,具体表示见下:
l GPI_Gray: 使用c1表示灰度值。
l GPI_RGB: c1表示红色,c2表示绿色,c3表示蓝色,c4表示alpha通道。
l GPI_CMYK: c1表示青色,c2表示洋红,c3表示黄色,c4表示黑色。
l GPI_HLS: c1表示色调,c2表示亮度,c3表示饱和度。
通过颜色表,将象元值用颜色表中的颜色来进行表示,颜色表中的值是从0开始递增。
10、快视图(Overviews)
一个波段中可能没有或者有很多个快视图。每个快视图都是一个GDALRasterBand,略缩图大小将和其下层的栅格大小不一样,但是快视图表示的区域与整个图像的区域是一致的。
快视图是用来快速显示图像用的,使用全分辨率图像进行降采样得到。
波段可以通过函数HasArbitraryOverviews,返回TRUE表示可以快速读取任何分辨率的快视图,这个主要应用在一些如FFT编码的图像(这句有点别扭,自己看英文原文吧)。
11、GDAL核心类结构设计
GDAL的核心类结构设计如图所示:
其中的类说明如下:
GDALMajorObject类:带有元数据的对象。
GDALDdataset类:通常是从一个栅格文件中提取的相关联的栅格波段集合和这些波段的元数据;GDALDdataset也负责所有栅格波段的地理坐标转换(georeferencingtransform)和坐标系定义。
GDALDriver类:文件格式驱动类,GDAL会为每一个所支持的文件格式创建一个该类的实体,来管理该文件格式。
GDALDriverManager类:文件格式驱动管理类,用来管理GDALDriver类。
二、OGR体系架构
1、OGR体系结构
OGR包括如下几部分:
Geometry:类Geometry (包括OGRGeometry等类)封装了OpenGIS的矢量数据模型,并提供了一些几何操作,WKB(Well Knows Binary)和WKT(Well Known Text)格式之间的相互转换,以及空间参考系统(投影)。
Spatial Reference:类OGRSpatialReference封装了投影和基准面的定义。
Feature:类OGRFeature封装了一个完整feature的定义,一个完整的feature包括一个geometry和geometry的一系列属性。
Feature Definition:类OGRFeatureDefn里面封装了feature的属性,类型、名称及其默认的空间参考系统等。一个OGRFeatureDefn对象通常与一个层(layer)对应。
Layer:类OGRLayer是一个抽象基类,表示数据源类OGRDataSource里面的一层要素(feature)。
Data Source:类OGRDataSource是一个抽象基类,表示含有OGRLayer对象的一个文件或一个数据库。
Drivers:类OGRSFDriver对应于每一个所支持的矢量文件格式。类OGRSFDriver由类OGRSFDriverRegistrar来注册和管理。
2、OGR的Geometry模型
OGR的Geometry模型是建立在OpenGIS的简单要素数据模型之上的。如下图所示:
图-OGR的Geometry模型关系图
OpenGIS的简单要素数据模型,其关系图如下所示:
图-OpenGIS的简单要素数据模型
由上面两图的对比,可以清楚的看到,OGR的Geometry模型是严格遵循OpenGIS的简单要素数据规范的。OGR的Geometry模型不仅在继承体系上与OpenGIS的简单要素数据模型一致,在函数接口上也向其靠拢,从基本的获取Geometry对象信息的方法如Dimension ()、GeometryType ()、SRID ()、Envelope()、AsText()、Boundary()等到判定空间未知关系的方法如Equals(anotherGeometry:Geometry)、Disjoint(anotherGeometry:Geometry)、
Intersects(anotherGeometry:Geometry)、Touches(anotherGeometry:Geometry)等都是符合其标准的。
对于OGR库后面会专门进行说明,这里简单说明一下就好。