zoukankan      html  css  js  c++  java
  • GDAL指定自定义的金字塔目录

    缘起

    对于一般的遥感影像文件,金字塔文件默认都是与影像文件放在同一个目录下,金字塔文件名一般与源影像文件名相同,但后缀名不同。或者金字塔内建于影像内部,但这不是这里所涉及的。
    在使用ArcGIS桌面版或者Erdas遥感影像处理软件打开遥感影像文件的时候,如果影像不含(带有)金字塔,则会提示是否创建金字塔。

    ArcGIS提示建立金字塔

    我们碰到这么一种情况,就是原始影像是不带金字塔的,并且所在的目录不允许修改,也就是不能将金字塔创建在其中,原始影像文件更是不允许修改,所以也不能更新内建金字塔。

    解决

    对于这个问题,为了加速影像的浏览,只能将金字塔建立在外部的目录,而读取的时候根据读取输出的分辨率,来确认是使用源影像读取还是使用金字塔文件读取,这都需要自己控制。
    因为自己控制会将一些控制流程变复杂,所以我想让GDAL直接支持索引到这个外部的金字塔文件。

    在GDAL中,金字塔称之为Overviews(概览视图),所以与之相关的接口都带有Overview单词。

    我看了GDAL的RasterIO流程相关的代码,简单的制作了如下的流程图:

    GDALDataset::RasterIO简单流程图

    GDALDefaultOverviews::OverviewScan()函数

    与金字塔路径查找的关键代码在函数GDALDefaultOverviews::OverviewScan()中。

    通过查看其实现代码,和被调用时候的参数(参数在GDALDefaultOverviews::Initialize函数被调用的时候确定,可以搜索poDS->oOvManager.Initialize查看,都是在对应格式的XXXDataset::Open()函数中被调用,不同格式影像调用时候传的参数可能不同),可以知道GDAL搜寻金字塔的方式与顺序。

    这里不详细说这里面的流程结构了,一些判断条件也略过,只大概说一下搜索顺序(如果有内建金字塔则不会读取外部金字塔):

    • 1、.ovr后缀金字塔文件
    • 2、.aux后缀金字塔文件
    • 3、.rrd后缀金字塔文件(如果配置有USE_RRD=YES
    • 4、影像元数据Metadata中的OVERVIEW_FILE指定的金字塔路径

    如果需要使用到自定义的金字塔文件,可以在此处修改,添加一段搜索代码,示例如下:

        if( poODS == nullptr )
        {
            osOvrFilename = MyOverviewFileSearch(pszInitName);
            poODS = GDALDataset::Open(osOvrFilename,
                GDAL_OF_RASTER | (poDS->GetAccess() == GA_Update ? GDAL_OF_UPDATE: 0));
        }
    

    MyOverviewFileSearch是用于搜索自定义路径下金字塔的函数。

    关于 GDALRasterBand::GetOverview

    上面说如果有内建金字塔则不会读取外部金字塔,这个实际上是各个影像文件格式的相关代码里面自己定义的。
    因为virtual GDALRasterBand* GDALRasterBand::GetOverview(int);本来就是一个虚函数,而GDAL中又基本都是依赖指针进行操作,所以实际上会调用各自的实现。

    GeoTiff格式为例,在它的Overview相关函数中就是先搜索Tiff目录内的金字塔,如果找不到才调用GDALRasterBand中对应的接口,进而访问外部金字塔文件。

    例如以下代码:

    /************************************************************************/
    /*                          GetOverviewCount()                          */
    /************************************************************************/
    int GTiffRasterBand::GetOverviewCount()
    {
        poGDS->ScanDirectories();
        if( poGDS->nOverviewCount > 0 )
        {
            return poGDS->nOverviewCount;
        }
    
        const int nOverviewCount = GDALRasterBand::GetOverviewCount();
        if( nOverviewCount > 0 )
            return nOverviewCount;
    
        // Implicit JPEG overviews are normally hidden, except when doing
        // IRasterIO() operations.
        if( poGDS->nJPEGOverviewVisibilityCounter )
            return poGDS->GetJPEGOverviewCount();
    
        return 0;
    }
    
    /************************************************************************/
    /*                            GetOverview()                             */
    /************************************************************************/
    GDALRasterBand *GTiffRasterBand::GetOverview( int i )
    {
        poGDS->ScanDirectories();
        if( poGDS->nOverviewCount > 0 )
        {
            // Do we have internal overviews?
            if( i < 0 || i >= poGDS->nOverviewCount )
                return nullptr;
            return poGDS->papoOverviewDS[i]->GetRasterBand(nBand);
        }
    
        GDALRasterBand* const poOvrBand = GDALRasterBand::GetOverview( i );
        if( poOvrBand != nullptr )
            return poOvrBand;
    
        // For consistency with GetOverviewCount(), we should also test
        // nJPEGOverviewVisibilityCounter, but it is also convenient to be able
        // to query them for testing purposes.
        if( i >= 0 && i < poGDS->GetJPEGOverviewCount() )
            return poGDS->papoJPEGOverviewDS[i]->GetRasterBand(nBand);
    
        return nullptr;
    }
    

    上面代码中的poGDS->ScanDirectories();语句,内部调用去遍历Tiff目录,找到TIFFTAG_SUBFILETYPE(子文件类型)字段为FILETYPE_REDUCEDIMAGE(缩小图像)的目录,然后解析出需要的金字塔信息(仅第一次调用时做,后面调用会判断bScanDeferred直接跳过)。

    如果没有找到才调用基类GDALRasterBand对应的函数去访问外部金字塔。

    关于构建外部金字塔等

    构建也是差不多的过程,这里就简单的写一下调用过程:GDALDataset::BuildOverviews ---> GDALDataset::IBuildOverviews ---> GDALDefaultOverviews::BuildOverviews

    所以设置构建外部金字塔的路径,也可以修改GDALDefaultOverviews::BuildOverviews
    同样,对于不同的影像格式,可以有自己的GDALDataset::IBuildOverviews实现,例如GeoTiff的就是GTiffDataset::IBuildOverviews,如果需要创建内建的金字塔,则做另外的实现。

  • 相关阅读:
    微软新一代Surface,该怎么看?
    Windows 8创新之路——样章分享
    微软新一代Surface发布,参数曝光
    从MS Word到Windows Live Writer
    《计算机科学基础》学习笔记_Part 1 Computer and Data
    我看Windows 8.1
    Hyper-V初涉_早期Windows安装虚拟硬件驱动
    2020.09.05【省选组】模拟 总结
    2020.08.15【NOIP提高组】模拟 总结
    2020.08.14【省选B组】模拟 总结
  • 原文地址:https://www.cnblogs.com/oloroso/p/10411893.html
Copyright © 2011-2022 走看看