ArcGISForServer10.3版本新型紧促切⽚缓存(.bundle)⽂件读取
ArcGIS For Server10.3版本新型紧促切⽚缓存(.bundle)⽂件读取及合并
前⾔
… ArcGIS10.3版本发布以后,Esri推出了新的紧凑型切⽚缓存格式,与之前.bundle+.bundlex⽂件组合相⽐,新的格式将所有信息整合到⼀个.bundle⽂件中,增强了⽤户的访问体验。
⼀、.bundle⽂件名
…bundle⽂件的⽂件名与其中所包含的切⽚有关,例如R0000C0000、R1c280C10080、R38680C20180、不难看出R和C分别作为⾏和列的标识,后跟的数字为16进制数,代表该切⽚中第⼀张图⽚的⾏号与列号,以R1c280C10080为例,换算成10进制为
雕梁画栋的拼音R:115328,C:65664,故该切⽚中的切⽚的⾏列号为:(R:115328,C:65664),(R:115328,C:65665)…(R:115456,C:65791),
(R:115456,C:65792),共计128*128张,在索引中的排列⽅式为第115328⾏的第65664-65792列,第115329⾏的65664-65792列,以此类推。
⼆、读取.bundle
直接说结论:
.bundle⽂件由3部分组成:①64个字节的头⽂件+②128 * 128 * 8个字节的索引③单个PNG切⽚的字节流
以下代码是Esri项⽬中创建.bundle⽂件的代码
BSZ2 =128*128
IDXSZ = BSZ2 *8
def init_bundle(fname):
'''Create an empty V2 bundle file'''
fd =open(fname,"wb")
眩晕停# Empty bundle file header, lots of magic numbers
header = struct.pack("<4I3Q6I",
3,# Version
BSZ2,# numRecords
0,# maxRecord Size
5,# Offt Size
0,# Slack Space
64+ IDXSZ,# File Size
40,# Ur Header Offt
20+ IDXSZ,# Ur Header Size
失色的意思3,# Legacy 1
16,# Legacy 2
BSZ2,# Legacy 3
5,# Legacy 4
IDXSZ # Index Size
)
fd.write(header)
# Write empty index.
fd.write(struct.pack("<{}Q".format(BSZ2),*((0,)* BSZ2)))
fd.clo()
①64个字节的头⽂件:包含⽂件的元数据,具体参考上述代码中的注释。
②128x128x8个字节的索引:每个bundle⽂件存放的切⽚数量为128*128个,每个索引占⽤8个字节。
③单个PNG切⽚的字节流:②中索引存放的是PNG切⽚的起始位置,值得注意的是,在起始位置前,还会额外插⼊4个字节⽤于存放PNG字节流总共的字节数量
三、⽰例
以上⽂提到的官⽅项⽬中的sample_cache为例,使⽤python读取bundle⽂件
f =open("sample_cache/_alllayers/L02/R0000C0000.bundle","rb")
header = struct.unpack("<4I3Q6I", f.read(64))
print(header)
控制台输出为:(3, 16384, 43588, 5, 0, 588369, 40, 131092, 3, 16, 16384, 5, 131072)
根据⼆中对头⽂件的定义可以知道最⼤切⽚占⽤字节数量为43588,⽂件的总字节数为588369,根据需求从中拿到需要的项即可。
f =open("sample_cache/_alllayers/L02/R0000C0000.bundle","rb")
header = struct.unpack("<4I3Q6I", f.read(64))
index = struct.unpack("<{}Q".format(128*128), f.read(128*128*8))
print(index)
控制台输出为:(32085948322026912, 18863221486421922, 16097949742582442, 24910535439221727,0,0…,0,0)从索引列表不难看出打开的bundle⽂件总共只有4张切⽚,其他的切⽚索引为零,表⽰没有切⽚。
但是索引中记录的索引位置明显超出了整个⽂件的总字节数588369,不能够算是有效信息,这⾥还是需要从官⽅项⽬中寻找答案,在该项⽬中设置索引时的代码如下
curr_index[(row % BSZ )* BSZ + col % BSZ]= curr_offt +(tsize <<40)
其中curr_offt为切⽚起始位置,官⽅代码对他加上了⼀个切⽚size<<40位的操作,这⾥暂时不清楚为什么要这么做,但是我们读⽂件只需要见招拆招就可以了。
家春秋f =open("sample_cache/_alllayers/L02/R0000C0000.bundle","rb")
header = struct.unpack("<4I3Q6I", f.read(64))
index = struct.unpack("<{}Q".format(128*128), f.read(128*128*8))
num =1
for i in index[:4]:
start_index = i %2**40
f.ek(start_index-4)
size = struct.unpack("I", f.read(4))[0]
img = f.read(size)
with open("sample_tiles/L02/{}.png".format(num),'wb')as im:
im.write(img)
num +=1第二天的英文
前汉书
表的组词通过以上代码,我们就以从该bundle中读取所有切⽚,如下图
最后
通过上⽂可以发现bundle是⼀种⾮常简单的数据格式,正如官⽅所说“simple and optimized for quick
茶分类
access”。只要理清了bundle ⽂件的构造,⽆论是读取还是写⼊bundle⽂件,都是⼀件⾮常简单的事情!