Zade's Weblog

程序人生

Monthly Archives: 8月 2010

GIS影像数据的显示

GIS的数据分成两大类:矢量数据,以.shp数据和oracle spatial geometry为代表;还有就是栅格数据,以geotiff和oracle spatial georaster为代表.

矢量数据的显示比较直观,矢量符号配上显示符号即可.我用了不少的时间实现矢量数据的显示,最近一段时间以GDAL为底层的数据引擎,实现了栅格数据的显示,现在把我实现栅格数据显示的思路整理一下.

在实现思路上,我参考了开源的SharpMap软件.

栅格数据显示需要考虑的因素:

  1. 波段和颜色通道的映射.一个波段可以映射为不同的颜色通道,不同的颜色通道可以显示,也可以不显示.有些数据存储这些映射信息,有些数据不存储这些映射信息
  2. 波段数据和颜色通道数据的映射.颜色通道数据一般是8bit的,但是GIS的影像数据有很多的格式,这意味着我们必须通过某种手段进行映射.GeoAPI给出了3中方法:None,Normalize,Histogram.我们在这里并不解释这些具体的映射方式,具体的可以参考GEOAPI.

一旦完成了这两个工作,栅格数据就可以显示了.

波段和颜色通道的映射

颜色通道有多种模型,RGB,CMYK,HLS,YUV等.虽然并不精确,但是不同的模型之间存在一定的转换关系.因为现在的很多显示引擎直接支持的是RGB的模型,所以从实现的角度来看,我们按照给定的模型获得不同的颜色模型,然后转化为RGB的模型即可.当然,RGB模型本身不需要转化.以CMYK为例

byte* c_data  = read_channel_data(C_CHANNEL);//这里具体的读取过程涉及波段数据和颜色通道数据的映射,参见下一个议题

byte* m_data  = read_channel_data(M_CHANNEL);//同上

byte* y_data  = read_channel_data(Y_CHANNEL);//

byte* k_data  = read_channel_data(K_CHANNEL);//

byte* a_data  = read_channel_data(ALPHA_CHANNEL);//

ARGB* data = get_img_data(ImageFormat::ARGB_FORMAT);

for (ARGB* end = data + bytes; data!= end;++ cdata,++ c_buf,++ m_buf,++ y_buf,++ k_buf,++ a_buf){
     *data = Color::fromCmyk(*c_buf,*m_buf,*y_buf,*k_buf,*a_buf).rgba();
}

其他颜色模型的转换是类似的.

颜色的像素格式我们使用ARGB的格式,虽然有些空间占用,但是对于屏显数据而言,并不是很多.这样做的好处是不管使用什么颜色模型,到最后都要转换为ARGB的模型,在算法实现上是非常的便利的.

有的数据格式存储这样的映射关系,有的数据不存储这样的数据关系.为了解决和这个问题,我们使用栅格符号RasterSymbolizer来定义这个映射关系.如果数据本身存储这样的映射关系,那么我们直接的使用这个映射关系;如果数据本身不存储这样的映射关系,我们的做法是:如果波段的个数>=3,选取前三个波段映射为RGB模型,否则,选取第一个作为灰度波段显示

波段数据和颜色通道数据的映射

栅格数据的格式很多,不仅包含我们常见的图像数据,例如GIF/PNG等数据,也包括DEM等数据.从GDAL的类型我们可以知道,存储的格网数据类型包括整型,从8bit到32bit,包括无符号有符号的整型.浮点型,从32bit到64bit.实数型,16bit到32bit的整数型实数,32bit到64bit的实数.具体参见GDAL文档.

从ARGB的格式上说,每个颜色通道的数据类型就是8bit的byte,这个映射很显然的要损失一些精度.我们把这个转换定义为一个函数:

byteValueOfColorComponent = Function(channelValue)

这个映射从GeoAPI的角度kan,有三种:

None:从实现的角度看,none意味着截取和转换,比如16bit截取为8bit,float转换为byte等.很显然,这里面有数据丢失的情况,严重的时候是不可接受的.但是这个方法的好处:一旦原始数据类型是byte,那么不存在截取和转换的情况.另外这种方法是最快的,最为初始的显示方式是可以接受的.

Normalize:归一化.从实现的角度上说,就是在最大值和最小值之间做一个线性映射,最大值显示为某种颜色(一般是最亮的值),最小值显示为某种颜色(一般是最暗色).

Histogram:柱状图.Normalize是一个波段数据值和颜色值之间的一个线性映射,Histogram是波段数据出现的频率值和颜色值之间的映射,同样的是:最大平率值显示为某种颜色(一般是最亮的值),最小频率值显示为某种颜色(一般是最暗色).

在映射的过程中,单值映射比较容易,实数值映射的是实数实部和虚部的平方根(也就是轴长).

灰度值和颜色表

灰度值映射为颜色值的公式是:color = makeARGB(gray,gray,gray,Alpha),gray来自于单一的一个波段数值.

颜色表是直接把波段数值作为颜色索引,在这里我们假设所有的索引值都小于256。