缘起

对于一般的遥感影像文件,金字塔文件默认都是与影像文件放在同一个目录下,金字塔文件名一般与源影像文件名相同,但后缀名不同。或者金字塔内建于影像内部,但这不是这里所涉及的。

在使用ArcGIS桌面版或者Erdas遥感影像处理软件打开遥感影像文件的时候,如果影像不含(带有)金字塔,则会提示是否创建金字塔。

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

解决

对于这个问题,为了加速影像的浏览,只能将金字塔建立在外部的目录,而读取的时候根据读取输出的分辨率,来确认是使用源影像读取还是使用金字塔文件读取,这都需要自己控制。

因为自己控制会将一些控制流程变复杂,所以我想让GDAL直接支持索引到这个外部的金字塔文件。

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

我看了GDAL的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,如果需要创建内建的金字塔,则做另外的实现。

GDAL指定自定义的金字塔目录的更多相关文章

  1. Visual Studio 中指定自定义生成事件

    自定义生成事件打开方式 通过指定自定义生成事件,可以在生成开始之前或在它完成之后自动运行命令.在Visual Studio中通过右键项目->属性 进入项目属性菜单. 自定义生成事件的语法 生成事 ...

  2. 把自解压的RAR压缩包解压到指定的软件安装目录

    原文 把自解压的RAR压缩包解压到指定的软件安装目录 今天千里独行同学给轻狂来信问了一个问题:如何把一个自解压的RAR压缩包解压到我们指定的软件安装目录.   其实,在NSIS中,我们可以灵活运用相关 ...

  3. red5 自定义文件存放目录

    Red5 流媒体服务器 自定义文件存放目录 Red5在正常情况下,安装之后文件必须存放在Red5安装目录下的oflaDemo\streams中,不能自定义存放目录,例如Red5 安装在C盘,但是我的文 ...

  4. Ubuntu 安装mysql & 自定义数据存储目录

    一.安装 apt-get install mysql-server 执行过程如下: root@duke:~# apt-get install mysql-server 正在读取软件包列表... 完成 ...

  5. 为Docker容器指定自定义网段的固定IP/静态IP地址

    第一步:创建自定义网络 备注:这里选取了172.172.0.0网段,也可以指定其他任意空闲的网段 docker network create --subnet=172.172.0.0/16 docke ...

  6. grep时排除指定的文件和目录

    参考:http://winterth.duapp.com/notes/ar03s04.htmlhttp://blog.sina.com.cn/s/blog_7169c8ce0100qkyf.html ...

  7. Django自定义上传目录

    由于数据库的upload_to功能,有时不能满足每次上传灵活自定义的需求, 基于DEF的上传,有时不能满足基于CLASS的视图要求, 于是,只好慢慢用土法实现. 当然,首先,要使用上传功能时,form ...

  8. vs指定QT的工作目录(其它项目也是如此)

    当一个工程依赖第三方动态库时,这时vs编译出来后,运行会提示缺少动态库.解决方法: 项目->属性->调试: 工作目录:指定程序运行时的目录 环境:指定程序运行时的环境变量 我们可以在环境变 ...

  9. Linux tar命令之--exclude参数 排除指定的文件或目录

    https://my.oschina.net/u/3285916/blog/1632552 参数: --exclude 打包时排除不需要处理的文件或目录 说明: tar -zcf a.tar.gz 打 ...

随机推荐

  1. 随GCTY

    1.用常数1来取代运行时间中所有加法常数. 2.修改后的运行次数函数中,只保留最高阶项 3.如果最高阶项存在且不是1,则去除与这个项相乘的常数. 如果sum = (1+n)*n/2这条语句再执行10遍 ...

  2. Painting the Fence Gym - 101911E(构造)

    There is a beautiful fence near Monocarp's house. The fence consists of nn planks numbered from left ...

  3. CUDA版Grabcut的实现

    在上次用 CUDA实现导向滤波 后,想着导向滤波能以很小的mask还原高分辨率下的边缘,能不能搞点事情出来,当时正好在研究Darknet框架,然后又看到grabcut算法,用opencv试了下,感觉效 ...

  4. JVM之对象分配:栈上分配 & TLAB分配

    1. Java对象分配流程 2. 栈上分配 2.1 本质:Java虚拟机提供的一项优化技术 2.2 基本思想: 将线程私有的对象打散分配在栈上 2.3 优点: 2.3.1 可以在函数调用结束后自行销毁 ...

  5. Django之模板1

    Django模板 一.变量(只需要记住两种特殊符号) {{ }} 和{% %} {{ }}表示变量,在模板渲染的时候替换成值,变量名由字母数字和下划线组成. {% %}表示逻辑相关的操作. 点(.)在 ...

  6. php curl函数采集网页出现gzip压缩、编码不同导致的乱码 图文解决方法

    方法一: header("content-type:text/html;charset=utf-8");$url="http://115.47.116.10/rest/k ...

  7. FPGA - 认识FPGA

    一.何为FPGA? FPGA,英文全拼:Field-Programmable Gate Array 现场可编程门阵列,它是在PAL.GAL.CPLD等可编程器件的基础上进一步发展的产物.它是作为专用集 ...

  8. BZOJ1889 : Maximal

    二分答案,判断是否存在合法方案使得每个数都不超过$mid$. 考虑网络流建图: $i$点的流量下限为$\max(a_i-mid,0)$,费用为$1$,故拆点进行限制. $i$向$i+1$.$S$向$i ...

  9. vim小技巧2

    yyp:复制当前行到下一行 cw:改变当前字符串 xp:交换当前字符和右边字符

  10. mysql的基本查询(等于,不等于,between...and...,)

    单个字段多个字段查询 查询员工姓名 *注:在SQL语句中不区分大小写:SQL语句以“:”分号结束 select ename from emp; 注:select询句后面跟的是字段名称,select是关 ...