zoukankan      html  css  js  c++  java
  • GDAL的RASTERIO功能

     
            为了能快速的显示大影像,最近一直在学习GDAL,GDAL确实是一个功能强大的开源库,其核心部分数据集和波段,下面这个图很详细的描述了它们之间的关系,还有其中的细节:

         GDAL的RASTERIO功能非常强大,简短的一句话就能实现图像的显示,但也是这个简单函数,把我折腾的半死。在学习使用GDAL的过程中,非常感谢李林大哥和貟建明大哥,他们不厌其烦地解答我的疑问,提示关键性要点,使我在解决问题的过程中事半功倍。
          我现在要把最近学习过程中的心得写下来,留给自己以后看看,也希望可以给新手们一点帮助!
         
    GDALAllRegister();    
    const char*    str ;
        
    m_pDataset = (GDALDataset*) GDALOpen( str, GA_ReadOnly );
        这一部分应该很好理解,首先打开一个影像,我们必须注册其驱动,因为每种不同的栅格数据都有不同的驱动,也就是driver。之后我们就可以用GDALOpen()函数来打开一个数据集dataset,如果打开的格式并不是GDAL支持的,我们就需要通过new GDALDriver()创建一个新的driver并设置,这样才能打开。如果GDALOpen()函数返回NULL,表示打开文件失败。
        打开了一个dataset之后,我们就可以对dataset的内部信息进行操作,dtaset的详细信息以及内部的关系在上图表述的非常详细。
    m_pDataset->GetGeoTransform( m_AdfGeoTransform );
    上面这行代码是用来获取仿射信息用的,m_AdfGeoTransform是一个含6个元素的数组,执行了这行代码后,我们就可以获取m_AdfGeoTransform数组的信息,m_AdfGeoTransform[0],m_AdfGeoTransform[3]是整个影像的坐下角坐标,m_AdfGeoTransform[1]是影像宽度上的分辨率,m_AdfGeoTransform[5]是影像高度上的分辨率,而对于m_AdfGeoTransform[2]和m_AdfGeoTransform[4]来说,如果影像是指北的,这两个参数的值为0。有了这几个参数,我们就能通过以下两行代码求出影像左下角和右上角的信息:
    XMin = m_AdfGeoTransform[0];
    YMin = m_AdfGeoTransform[3];

    XMax = m_AdfGeoTransform[0] + nX * m_AdfGeoTransform[1] + m_AdfGeoTransform[2]; 
    YMax = m_AdfGeoTransform[3] + m_AdfGeoTransform[4] + nY * m_AdfGeoTransform[5]; 

        有了影像的信息之后,我们要做的就是将影像显示出来,这里就有一个分辨率的问题,一个是图像分辨率,一个是显示分辨率。图像分辨率就是单位长度内的像素数,而显示分辨率就是把数字图像在输出设备(比如显示屏或打印机等)上能够显示的像素数目和所显示像素之间的点距。这两个分辨率在显示影像的时候非常有作用。弄清楚原理的东西确实是成功的基石!
        然后就到了GDAL的核心部分了:
    pBuffer = (BYTE*) CPLMalloc(sizeof(BYTE)*(xBuf)*(yBuf)*nBand);

    m_pDataset->RasterIO( GF_Read, xSrc, ySrc, xWidth, yHight, pBuffer, xBuf, yBuf,GDT_Byte, nBand, NULL, nBand, 0, 1 );    
    对于三个波段以上的影像,我们可以直接通过以上两行代码讲影像读入pBuffer这个内存,然后根据我们的需要,比如说OPENGL,我们就可以利用glDrawPixels( )这个函数直接显示出影像了。现在关键的地方就是RasterIO里面的几个参数了,对照GDAL官方的函数说明:
    GDALDataset::RasterIO  (  GDALRWFlag  eRWFlag,  
            int  nXOff,  
            int  nYOff,  
            int  nXSize,  
            int  nYSize,  
            void *  pData,  
            int  nBufXSize,  
            int  nBufYSize,  
            GDALDataType  eBufType,  
            int  nBandCount,  
            int *  panBandMap,  
            int  nPixelSpace,  
            int  nLineSpace,  
            int  nBandSpace 
     )  

    如果为GF_Read,则是将影像内容写入内存,如果为GF_Write,则是将内存中内容写入文件。
    nXOff,nYOff,nXSize,nYSize这四个参数是用于影像的,nXOff,nYOff就是说我们要从影像的这个像素坐标开始取数据,nXSize,nYSize就是从影像上取数据的宽度和高度,也就是说要从影像上取出来的数据范围是(nXOff,nYOff)到(nXOff+nXSize,nYOff+nYSize)。如果我们要显示这个取出来的范围,我们就要把这个数据域写入缓存pData中,nBufXSize,nBufYSize即是这个缓存区的大小范围。
           RasterIO这个函数只有这些说明,那我们在应用的时候就需要根据我们的实际需要计算,如果有一幅100M的影像,你想快速显示,那么这六个参数的设置就是关键,不过有一个前提条件就是这个影像是金字塔影像,这样你设置好了buffer的size,那么GDAL就会根据GDAL内部函数的实现过程,自动帮你完成缩放操作(把nXSize,nYSizen的数据缩放到BufXSize,nBufYSize的buffer里显示),而并不需要你去控制获取哪个overview,由于开始我并没有理解透这个函数的真正含义,在大影像的显示上走了很多弯路,自己去判断要读金字塔的第几层,以至于自己都把自己快搞崩溃了,这里要非常感谢李林大哥,呵呵,每个细节都给我讲的很详细,并且对于一些抽象的东西他也耐心的给我举些例子,加上自己的时间,最后终于明白了这个函数的原理所在。呵呵,在这里要真挚的感谢李大哥。 
           nBufXSize,nBufYSize这个缓存区的大小范围,决定了我们要在多大的屏幕范围显示你想显示的图像内容,因此我们要根据屏幕范围和缩放比例来计算这个buffer的size。
          nPixelSpace表示一个像素所占byte大小,假如是24位的,那么一个像素就占3个字节,那么nPixelSpace =  3。nLineSpace表示一行所占大小,如果设为0的话,就默认为nBufXSize*nBufYSize。
    nBandSpace为一个波段数据所占大小,如果设为0的话,就是以RRRGGGBBB这种形式存储,如果设为1的话,就是以RGBRGBRGB这种形式存储。
        不过这个函数还是要自己试了才知道真正的意义,呵呵,希望新手少走我的弯路!!以后还会陆续添加自己的学习心得的,^_^Fighting!!!o(∩_∩)o...
     
  • 相关阅读:
    Web.xml详解
    Spring 及 SpringMVC的web.xml配置详解
    <context-param>与<init-param>的区别与作用
    关系型数据库(RDBMS)与 MongoDB 的对应关系
    Dubbo通过注解实现RPC调用
    org.springframework.stereotype.Service和com.alibaba.dubbo.config.annotation.Service两种service的区别
    Linux下部署 jar包
    最新Dubbo-admin+Zookeeper搭建
    spring security3.1配置比较纠结的2个问题
    SpringSecurity——基于Spring、SpringMVC和MyBatis自定义SpringSecurity权限认证规则
  • 原文地址:https://www.cnblogs.com/lovebay/p/5335409.html
Copyright © 2011-2022 走看看