早在2010年年底,牛魔王中王在其博客空间牛魔王的作坊中对ArcGIS 10中推出的紧凑型缓存格式进行了详细的解读,详见《ArcGIS 切片缓存紧凑文件格式分析与使用》。紧随着的4年时间里,ArcGIS for Server本身经历了10、10.1.X和10.2.X各版本的逐级更替,特别是软件架构发生了显著的变化。然而,就紧凑型缓存本身而言,牛魔王中王的解读一直都是适用的。衷心地向我们的大牛致敬!

  直到2014年年底ArcGIS 10.3正式发布,Esri才推出了新的紧凑型缓存格式以增强用户的访问体验。新的缓存格式下,关键的差别在于Esri将缓存的索引信息.bundlx包含在了缓存的切片文件.bundle中。

  接下来,我们就简单解读一下这一新型的紧凑型缓存格式。俗语说,万变不离其宗。既然缓存文件夹下仅包含了bundle文件,可以想见,切片的索引,切片的偏移和切片的图片流都必然包含在这一文件中。根据经验,缓存本身遵循的是16进制的形式。依照这一思路,利用UltraEdit打开bundle文件并以16进制格式进行查看。

 为了便于分析,我们先创建一个在L00级只包含一个切片的缓存服务,并在UltraEdit中以16进制格式查看L00级下的R0000C0000.bundle文件。

  通过对这一文件中信息存储规律的分析,可初步得出如下结论:(1) 文件中包含大量04 00 00 00 00 00 00 00的16进制字节组,共计16893组;(2) 文件中仅包含一个PNG24的文件头字节组89504E47,即第一行第一列的切片,bundle文件中唯一的一张图片。图片流紧随(1)中所提到的字节组之后,但偏移4个字节;(3) (2)中所述的4字节偏移量的数值恰等于图片流的长度;(4) 文件第5行的起始4个字节44 00 02 00按照低位到高位换算出的数值等于131140,这一值与(2)中所述的PNG文件头位置恰恰吻合。

  综上分析:(1)起始4行是bundle的文件头信息,可忽略;(2)bundle的文件头之后记录了16384张切片的切片位置,仅4字节,从低位到高位,后4字节可忽略;(3)位置信息之后,对于切片的记录,先以4字节记录切片的长度,而后紧跟图片流信息。到此,bundle结束。

  下一步呢,我们将选择一个狭长的矩形面要素发布服务并切图,以分析行列切片在bundle文件中的具体存储规律。

  通过对bundle文件和对应的松散缓存在L02级别上的对比,可推断:(1)bundle中索引的存储是按行依次存储,即第1行的1至128,第2行的1至128,以此类推,直至最后一张切片即第128行128列;(2)bundle中图片流的存储仅包含非空切片。此外,通过对这一更复杂的地图缓存的分析,再次论证了前面的推论。

  既然上述的分析完毕,接下来就要对上述的分析进行一番验证啦。这里呢,我会利用ArcGIS Runtime SDK for Android实现抽象理论的实践工作。本次验证的核心在于,通过对TiledServiceLayer进行扩展,按照上面的存储推论覆写getTile(int mLevel, int mColumn, int mRow)方法。

  第一步,根据参数中的比例级别、列号和行号定位到Bundle文件。

     String level = Integer.toString(mLevel);
int levelLength = level.length();
if(levelLength == 1){
level = "0" + level;
}
level = "L" + level; int rowGroup = 128*(mRow/128);
String row = Integer.toHexString(rowGroup);
int rowLength = row.length();
if(rowLength < 4){
for(int i=0; i<4-rowLength; i++){
row = "0" + row;
}
}
row = "R" + row; int columnGroup = 128*(mColumn/128);
String column = Integer.toHexString(columnGroup);
int columnLength = column.length();
if(columnLength < 4) {
for(int i=0; i<4-columnLength; i++){
column = "0" + column;
}
}
column = "C" + column; String bundleName = String.format("%s/%s/%s%s", compactTileLoc, level, row, column) + ".bundle";

  第二步,读取bundle文件,根据前面分析中所推断出的切片的起始位置和切片的长度获取对应的切片并返回。

     int index = 128*(mRow - rowGroup) + (mColumn-columnGroup);

     RandomAccessFile isBundle = new RandomAccessFile(bundleFileName, "r");
isBundle.skipBytes(64 + 8*index); //获取位置索引并计算切片位置偏移量
byte[] indexBytes = new byte[4];
isBundle.read(indexBytes, 0, 4);
long offset = (long)(indexBytes[0]&0xff) +(long)(indexBytes[1]&0xff)*256 + (long)(indexBytes[2]&0xff)*65536
+ (long)(indexBytes[3]&0xff)*16777216; //获取切片长度索引并计算切片长度
long startOffset = offset - 4;
isBundle.seek(startOffset);
byte[] lengthBytes = new byte[4];
isBundle.read(lengthBytes, 0, 4);
int length = (int)(lengthBytes[0] & 0xff) + (int)(lengthBytes[1] & 0xff)*256 + (int)(lengthBytes[2] & 0xff) * 65536
+ (int)(lengthBytes[3] & 0xff) * 16777216; //根据切片位置和切片长度获取切片
ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] tileBytes = new byte[length];
int bytesRead = 0;
if(length > 0){
bytesRead = isBundle.read(tileBytes, 0, tileBytes.length);
if(bytesRead > 0){
bos.write(tileBytes, 0, bytesRead);
}
} tile = bos.toByteArray();

  呵呵,成功实现。直接奉上Android端的显示效果吧。

  

Tips:

  关于紧凑型切片,唠唠叨叨的我还是忍不住要嘱咐几句:(1)新型的紧凑型切片无法被直接用于先前版本的ArcGIS for Server;(2)新型的紧凑型切片可通过导出切片即export tiles获取先前格式的缓存;(3)老版本的紧凑型切片可直接在新版本的ArcGIS for Server中复用,但可通过升级存储格式即Upgrade Storage Format更新为新型紧凑型切片格式。

ArcGIS for Server 10.3.X 新型紧凑型缓存的解读和应用的更多相关文章

  1. ArcGIS for Server 10.2 发布Feature Service

    折腾一下午,终于把自带的例子发布成Feature Service了,这样就可以通过web编辑了.记录一下步骤. 环境:已经安装好SQL Server 2008 R2,ArcGIS for Deskto ...

  2. [转]arcgis for server 10.2 下载及安装

    转自:https://blog.csdn.net/nominior/article/details/80211963 https://blog.csdn.net/mrib/article/detail ...

  3. ArcGIS Server 10中的切图/缓存机制深入【转】

    http://blog.newnaw.com/?p=789 两年前我写过一篇关于ArcGIS地图切图/缓存原理的文章,<ArcGIS Server的切图原理深入>,里面以tiling sc ...

  4. [ ArcGIS for Server 10.1 系列 ] - 重新创建Site

    一般当ArcGIS Server Site发生错误.ArcGIS Server无法启动或者ArcGIS Server某服务没有实例,就可能需要重新的创建Site.有时可以通过重新创建Site,就发现其 ...

  5. ArcGIS for Server 10.2 开启GeometryService

    过程非常简单,所以网上文档比较少. 打开网站管理页面: http://localhost:6080/arcgis/manager/ 点左边Utilities

  6. ArcGIS for Sever 10.1 服务迁移与恢复

    === 声明:以下内容本是自己写给单位内部同事的参考手册,但是被传到百度文库中.陆续有用户就这方面的问题,通过电话,邮件等方式联系我.首先,感到荣幸.其次是,由于本人当时测试和编写的时候,由于仓促,可 ...

  7. arcgis for server 登陆manager失败解决办法

    版本是 arcgis for server 10.02 症状 1. manager网页无法打开http://localhost:6080/arcgis/manager/ 2. 查看服务无法启动,启动后 ...

  8. ArcGIS for Server新建站点异常,Failed to create the site.Failed to configure the server machine'XXXX',Server machine'XXXX' is not a local server machine.

      系统环境:操作系统Win7 64位,装在虚拟机VM中,ArcGIS for Server 10.2.1 问题描述:ArcGIS for Server 10.2.1安装并授权完成后,站点初始化时显示 ...

  9. ArcGIS for Server内置JS Viewer的离线部署和配置

    很多情况下,在地图服务发布完毕后,我们往往利用 ArcGIS for Server内置的 JS Viewer来查看和检测所发布的地图服务是否满足我们的要求.具体操作如下: 点击开始 -> 所有程 ...

随机推荐

  1. AR/VR-VR-Info-Micron-Insight:一镜观一屋:VR 将建筑设计变为现实

    ylbtech-AR/VR-VR-Info-Micron-Insight:一镜观一屋:VR 将建筑设计变为现实 1.返回顶部 1. 一镜观一屋:VR 将建筑设计变为现实 想象一下,在一栋为你设计的还没 ...

  2. 关于SetTimer间隔小于OmTimer执行时间的问题

    如果SetTimer的时间间隔为t,其响应事件OnTimer代码执行一遍的时间为T,且T>t.这样,一次未执行完毕,下一次定时到,这时候程序会如何执行? 可能的情况:1.丢弃还未执行的代码,开始 ...

  3. vs2013错误 1 Unable to find messages file 'cscui.dll'

    最近使用VS编译的时候,提示错误 错误 1 Unable to find messages file 'cscui.dll' 搜索后,几乎只有1个结果,就是搜索cscui.dll  把正常大小的文件替 ...

  4. excel批量提取网页标题

    最近时间比较忙,有时候很多网页需要临时保存,以便空闲的时候查看.单纯的保存网页链接会让人很枯燥,所以需要自动批量提取标题. 为了这个小功能去写个小程序有点不划算,所以就利用excel实现了这个功能. ...

  5. JDK5特性

    静态导入(了解) JDK 1.5 增加的静态导入语法用于导入类的某个静态属性或方法.使用静态导入可以简化程序对类静态属性和方法的调用. 语法: import static 包名.类名.静态属性|静态方 ...

  6. json字符串与json对象之间的转换

    字符串转对象(strJSON代表json字符串)   var obj = eval(strJSON); (运用时候需要除了eval()以外需要json.js包)  var obj = strJSON. ...

  7. 无监督学习:Deep Auto-encoder(深度自动编码器)

    一 Auto-encoder NN Encoder & NN Decoder 要一起训练. 二 Starting from PCA 三 Deep Auto-encoder PCA&De ...

  8. 51nod1105(二分)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1105 题意:中文题诶- 思路:直接二分答案,再通过二分找有多少 ...

  9. js的Element.scrollIntoView的学习

    1.Element.scrollIntoView()    该方法让当前元素滚动到浏览器窗口的可是区域内: 2.语法: element.scrollIntoView();//等同于element.sc ...

  10. Vue2中实现微信分享支付功能

    Vue2中实现微信分享支付功能  近期做了一个微信公众号前后分离项目,前端采用Vue2开发,后端SpringBoot,今天迫不及待的来给大家分享一下这次在开发中遇到的一些坑以及解决办法. 在这里,一些 ...