图片磁盘中的格式,bmp没有压缩,png,tga,jpeg等都是压缩格式!地图上标注绘制思路,各家都类似:

1)采用android系统的paint渲染到内存画布,
2)然后把画布的图像数据上传到显存中,创建纹理。出于适配性考虑,android上所有纹理宽高必须是2的幂次,而且纹理必须是RGBA格式,对应的画布为AGBA_8888格式。

地图中的文字有横向的也有纵向的,横向的有一行、多行的。为避免动态创建销毁画布开销,在内存中预创建一系列候选画布(常驻内存),然后每次根据文字的矩形大小select合适的画布用于生成标注纹理。

优化前做法:

内存创建一系列长宽相等的正方向画布:

level1 = 32*32
level2 = 64*64
level3 = 128*128
level4 = 256*256
level5 // 更大尺寸

内存根据文字矩形区域去选一个标注,如果level1 - level4 的画布均不合适,则动态创建能容纳当前文字的画布返回,当文字纹理创建成功后删除该大尺寸的画布;level5的分支会有动态创建、删除画布开发,但是其概率实际上非常低,一般256*256画布足以容纳95%的文字。

这种做法不需要区分横向和纵向文字,处理逻辑简单,但是导致文字纹理空间利用率十分低:




androidGraphics 持续增长 android graphics内存 android 显存_优化

上图一个标注宽度为130*30像素,结果被用了256*256的画布创建纹理,显存利用率不足6%。


优化V1:


画布创建一系列条状画布:


level1 = 64 * 32
level2 = 128 * 32
level3 = 256 * 32
level4 = 128 * 64
level5 = 32 * 64
level6 = 64 * 128
level7 = 64 * 256
其他

上图中的130*30纹理,只需要使用256*32画布,显存利用率提升为48%。

较方块画布,条状画布内存使用更少,而且显存利用率得到明显提升。处理逻辑稍微复杂,需要区分文字横向、纵向布局。level1 - level4为横向,level5- level7为纵向。横向放最上面是因为横向布局文字概率远大于纵向。


优化V2:

内存中只创建一系列横向的条状画布:

level1 = 64 * 32
level2 = 128 * 32
level3 = 256 * 32
level4 = 128 * 64

对于纵向的文字,先将其画到横向画布中,然后通过纹理坐标将每个字纹理单独扣出,最终根据文字纵向布局绘制一系列四边形。(

汉字大小尺寸一致


这种方案更加节约内存, 但是文字绘制逻辑会稍微复杂点。

极端优化Tips:

waze地图中文字比较少,他们实现方案在预处理过程中,将所有文字打包到一系列512*512图片中,同时对应每个文字的纹理坐标,绘制时每个字作为一个quad贴纹理。避免了小纹理的使用,减小纹理空间浪费同时成倍减小draw call。

这种方案在每屏上百个标注,而且前后两屏文字动态性十分之大的地图中使用不现实。


BTW:纹理尺寸如果不为2的幂次,android不同版本手机rom行为不一致,开发过程中在小米2这样的机器上都可能会导致纹理创建失败。。