cocos-js,内存管理1---一张图片的内存
一.1张图片内存如何计算一张图片占用的内存由以下两个因素决定:
其中图片的像素点个数是图片的宽度与长度的积,所以一张图片占用的内存值为: 图片长度 * 图片宽度 * 单位像素占用的字节数 单位像素所占用的字节数与图片的解码方式有关。 举例来说,一张1136x640的背景图占用的内存为 1136x640x32/8 = 2840 KB 当然我们也可以改变图片的解码格式: cc.Texture2D.setDefaultAlphaPixelFormat(cc.Texture2D.PIXEL_FORMAT_RGBA4444) 此时,图片的解码都会使用 举例来说,一张1136x640的背景图占用的内存为 1136x640x16/8 = 1420 KB
二.cocos支持的纹理像素格式
RGBA8888是默认的格式。 对于16位的纹理来说,使用RGB565可以获得最佳颜色质量,因为16位全部用来显示颜色:总共有65536总颜色值。但是,这里有个缺点,除非图片是矩形的,并且没有透明像素。所以RBG565格式比较适合背景图片和一些矩形的用户控件。 RBG5A1格式使用一位颜色来表示alpha通道,因此图片可以拥有透明区域。只是,1位似乎有点不够用,它只能表示32768种可用颜色值。而且图片要么只能全部是透明像素,或者全部是不透明的像素。因为一位的alpha通道的缘故,所以没有中间值。但是你可以使用fade in/out动作来改变纹理的opacity属性。 如果你的图片包含有半透明的区域,那么RBGA4444格式很有用。它允许每一个像素值有127个alpha值,因此透明效率与RGBA8888格式的纹理差别不是很大。但是,由于颜色总量减少至4096,所以,RBGA4444是16位图片格式里面颜色质量最差的。 现在,你可以得到16位纹理的不足之处了:它由于颜色总量的减少,有一些图片显示起来可能会失真,而且可能会产生“梯度”。 三.如何优化内存1.忽视文件图片大小
2.用SetDefaultAlphaPixelFormat()来实现
抖动算法 3.使用NPOT纹理NOPT是“non power of two”的缩写,译作“不是2的幂”。如果纹理图集(texture atlas)使用NPOT的纹理,它将有一个具大的优势:它允许TP更好地压缩纹理。因此,我们会更少地浪费纹理图集的空白区域。而且,这样的纹理在加载的时候,会少使用1%到49%左右的内存。而且你可以使用TP强制生成NPOT的纹理。 4.使用pvr格式纹理因为jpg是没有透明色的,一个像素最多3字节,而png一个像素4字节,jpg纹理应该占用内存更小才对,但是cocos把所有纹理转换成rgba8888格式,所以无论是jpg还是png,占用的都是4字节。正因cocos2d对其他纹理支持不够好,pvr才会显得那么高效。 pvr格式可以被显卡所认可,而不需要开辟临时内存来读取,所以即便同为argb8888格式的图片,pvr也会比png有效率,虽然不会节约程序稳定运行时的内存,但是会避免加载大量图片时的内存暴涨。 并且如果是ios设备的话,可以使用pvrtc4格式的图片,这个格式相当于windows下的dds图片,是可以被显卡直接支持的。它是有损压缩,一个像素只占4位,不过如果不是有渐变半透明色的话,一般效果可以接受,而其节约的内存和cpu时间非常非常显著。 pvr也不是万金油。android设备下虽然可以使用pvr格式,但是不能使用pvrtc4,希望通过pvr像ios设备上一样真正减少游戏内存是不太可行的。 pvr.ccz其实就是pvr图片zip打包下,程序读的时候还是先解压出pvr资源,然后再读取pvr。不过由于压缩下可以极大的减小图片体积,所以虽然多了解压过程也不会有特别多的cpu消耗。 一张jpg图片实际加载过程内存消耗,以一张1024*1024 argb8888 500k的jpg图片为例: a.读取图片文件(消耗图片大小内存,500k) b、解析jpg数据(cgimage,4mb) c、释放500k的图片内存 d、opengl纹理数据(4mb) e、释放cgimage的4mb内存。 注意,这个过程不是必然的顺序执行,释放cgimage内存的实际是有系统决定的,会很快,但是不一定是立即执行。 所以内存会瞬间飙升9mb左右,然后减少5mb,稳定到4mb左右. png图片的加载过程与此相同. pvr图片可以节约解析图片数据到纹理这一步的消耗。也就是说读取pvr图片资源(等价于解压pvr.ccz到内存,如果是1024*1024 argb8888格式的话,那么图片大小就是4mb,ccz压缩后图片1mb左右)消耗4mb,将pvr图片数据提交给显卡消耗4mb。然后释放文件数据4mb。这么看似乎跟Png从内存占用上相比也不是非常有优势。(注意这里说的pvr是指pvr封装的argb8888,与pvrtc4的性能有天壤之别) 这里还有一点需要说明,一般我们处理windows下的dds纹理的时候,都习惯将其按2的整次幂对其,虽然图片内容只有900*900,但是图片大小却是1024*1024。那我们读取这个图片所消耗的内存就是4mb,按2的整次幂对其是有助于提高运行效率的,但是不是非常必须的。ios和android的设备都支持非2的整次幂的纹理。所以如果是png图片,那么它该多大就多大。此时消耗的内存就只有900*900*4=3mb。 rgb565和rgb5551的图片所消耗的内存是rgba8888的一半,如果没有透明渐变的话,视觉上也看不出什么区别。一些大的背景图可以优先选择这种格式。 pvr图片加载速度要比png和jpg快3~5倍(同样1024*1024 argb8888),png消耗的时间可能是700ms左右,但是pvr只需要100ms左右。如果是pvr.ccz压缩下,消耗的时间是200ms左右。可见pvr在加载速度上还是有非常大的优势的。这个应该是因为png和jpg需要把图片数据还原为rgba,但是pvr可以直接把图片数据传递给显卡。pvrtc4的图片是可以被powervr显卡直接支持的。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |