读取栅格数据。
有
几种方法来读取栅格数据。但是最普遍的就是使用GDALRasterBand::RasterIO()
。这个方法自动会照顾到数据类型转换,以及取数据的时候对数据窗口的放大缩小。下面是几个例子可以说明在图像中如何读取第一行数据到一个简单得设定了大小
的数据内存缓冲中。其中有的例子有把数据转换成浮点类型。
C++:
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 );
C:
float *pafScanline;
int nXSize = GDALGetRasterBandXSize( hBand );
pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
GDALRasterIO( hBand, GF_Read, 0, 0, nXSize, 1,
pafScanline, nXSize, 1, GDT_Float32,
0, 0 );
Python:
scanline = band.ReadRaster( 0, 0, band.XSize, 1, \
band.XSize, 1, GDT_Float32 )
注意在python的例子中,返回的数据被组织成字符串形式。而且返回的数据大小是Xsize*4字节的未加工的二进制浮点数据。你可以用python的标准包中的struct模块来把它转化成python的数据。
代码
import struct
tuple_of_floats = struct.unpack(‘f‘ * b2.XSize, scanline)
这样返回的tuple_of_floats就是一个经过unpack拆分后的float型数组。(译者)
RasterIO的具体形式如下:
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 )
注
意:这个方法可以同时用于读和写。你可以使用RWFlag来设置(或者GF_Read或者GF_Write)读写权限。nXOff,nYOff,
nXSize,nYSize参数用来描述栅格在硬盘上读取或者写入数据的窗口大小。该窗口不一定要落在边界上,虽然这样存取可能更加有效。
pData
是指向缓冲数据的指针。如果是写入,pData就是要写到实际数据中的数据,如果是读取,pData就是从实际数据中获取的数据值存放的地方。它的真实的
数据类型是什么是通过eBufType参数设定的。如GDT_Float32,或者是GDT_Byte。RasterIo会照顾到从缓冲到实际数据的转
换。注意:当从浮点数转换到整形时,数据将四舍五入。而且从一个过大的存储单位转到较小的存储单位时所进行的操作是截断而不是按比例缩小所有的数,比如原
来实际数据中float中存取的数据范围超过了缓冲数据指定数据类型byte的最大范围,操作将把超过byte的范围截去顶端数据,而不是把每个
float缩小到0~256范围内。
nBufXSize和nBufYSize值描述缓冲区的大小。当加载的数据是完整分辨率的时候(原始数据,没
有缩放)它们应该设成和取值窗口一样的大小。但是在加载时使用了缩小分辨率。它们需要设置得比取值窗口小。在这种情况下,RasterIO利用略缩图组
(overviews)中的某个合适的略缩图来做存取将更加有效。
nPixelSpace和nLineSpace一般情况下是0作为缺省值。但是,它们可以用于控制用于存取的内存数据缓冲。可以利用它们把包含的象元数据按另一种组织形式读入内存缓冲内。
################################################################
http://www.gdal.org/classGDALRasterBand.html#1eef7a21cf4809425c3edced99aa088f中的解释:
这
个方法允许读取GDALRasterBand的一个区域的数据到一个缓冲或者把一个缓冲中的数据写入GDALRasterBand的指定区域内。它自动考
虑到了在波段数据和指定缓冲之间如果用eBufType指定数据类型后不同的数据类型间的转换。它也考虑到了如果缓冲大小(nBufXSize *
nBufYSize)和实际数据读取窗口大小(nXSize * nYSize)不一样的时候的数据替代。
nPixelSpace
and
nLineSpace参数允许读取或者写入非常规组织的缓冲数据。这首先可以用于一个缓冲中包含多个波段数据,并且各个数据之间是交叉排列的。(比如一个
数据表中的数据组织是RGBRGBRGB……而普通的数据可能是RRR……GGG……BBB……)
一些数据格式如果从低分辨率图中读取数据可能会更有效率。
在全分辨率中存取的最快的操作是使用 GetBlockSize()获得波段范围, 然后用 ReadBlock()和 WriteBlock()存取数据。
这个方法和C中的GDALRasterIO是一样的。
参数:
eRWFlag 可选GF_Read来读取数据,GT_Write来写入数据
nXOff 读取区域的左上角象元在整幅图中偏移左边框的象元数
nYOff 读取区域的左上角象元在整幅图中偏移上边框的象元数
nXSize 要存取的实际区域的宽度
nYSize 要存取的实际区域的高度
pData 存取数据的数据缓冲。大小至少为nBufXSize*nBufYSize*eBufType类型表示的大小。数据组织顺序是从左到右,从上到下。间隔由nPixelSpace和nLineSpace来控制。
nBufXSize 缓冲区域的宽
nBufYSize 缓冲区域的高
eBufType 缓冲中的数据类型。在需要的时候会和实际波段中的数据类型自动进行互相转换。
nPixelSpace 在一个扫描行中的一个象元的字节偏移起始点到下一个象元字节偏移起始点之间的字节间隔。如果使用默认的0,则使用eBufType作为实际的两个象元其实字节之间的字节间隔。
nLineSpace 在一行数据和下一行数据之间的起始字节间的间隔。如果使用偏移值(是不是为0?译者)则用eBufType*nBufXSize来表示实际间隔。
返回值:
CE_Failure是存取失败,否则返回CE_None
#################################################################
下
面是我的一个小例子:我使用了python中读取数据的另一种方式,使用的是ReadAsArray,作用等同于RasterIO,返回的是
Numeric的Array,这样就不要用struct去拆分二进制字符串了。而且通过Numeric的数组操作,很容易看似很专业地变换整个矩阵(这是
一个C的python扩展,非常快!)。但是我喜欢它的是因为它排列很工整,看起来很好看。
>>> import gdal
>>> from gdalconst import *
>>> dataset = gdal.Open("f:/pyproj/gtif/asp.tif")
>>> band = dataset.GetRasterBand(1)
>>> band.ReadAsArray(100,100,5,5,10,10)
array([[ 61, 61, 58, 58, 90, 90, 87, 87, 45, 45],
[ 61, 61, 58, 58, 90, 90, 87, 87, 45, 45],
[ 36, 36, 59, 59, 113, 113, 88, 88, 37, 37],
[ 36, 36, 59, 59, 113, 113, 88, 88, 37, 37],
[255, 255, 82, 82, 135, 135, 72, 72, 22, 22],
[255, 255, 82, 82, 135, 135, 72, 72, 22, 22],
[ 45, 45, 129, 129, 144, 144, 255, 255, 255, 255],
[ 45, 45, 129,