使用较少内存的bitmapdata的替代方案?

时间:2013-11-13 21:05:32

标签: actionscript-3 flash vector bitmapdata

我使用非常大的BitmapData作为我的平台游戏的路径图,但是我只使用4个特定值的像素,而不是4294967295。

将此Bitmapdata转换为布尔的2个2D向量会为我节省一些内存吗? 如果确实如此,那么性能如何,做下面的事情会更快或更慢:

MapGetPixel(x:int, y:int):int
{
    return MapBoolFirst[x][y] + MapBoolSecond[x][y]*2;
}

而不是bitmapdata类getPixel32(x:int, y:int):uint

总之我正在寻找一种减小尺寸和/或优化我的4色bitmapdata的方法。

编辑: 使用我的布尔方法显然比bitmapdata消耗的内存多2倍。 我猜一个布尔值在内存中占用多个位,否则就太容易了。因此,我正在考虑bithifting int,因此有一个int存储几个像素的值,但我不确定这...

编辑2: 使用int bitshifts我可以将16个像素的数据管理成一个int,这个技巧应该可以节省一些内存,即使它可能会达到一点性能。

3 个答案:

答案 0 :(得分:1)

Bitshifting将是最优化内存的处理方式。性能方面,这不应该是一个大问题,除非你需要轮询很多问每帧。 AS的问题是布尔值是4比特:(

我认为你可以在不同的情况下处理它:

1)为命中检测创建一个较低的res纹理,通常可以将它缩小4次(256x256 - > 64x64)

2)使用某种技术将数据保存到某种存储中(bool最简单,但如果这个太大,那么你需要为它找到另一种解决方案)

3)做整数解决方案(我以前没有使用过位移,所以我认为这将是一个有趣的挑战,这是结果)

并且该解决方案比用于布尔值的解决方案小,并且更难以理解:/

public class Foobar extends MovieClip {
    const MAX_X:int = 32;
    const MAX_Y:int = 16;

    var _itemPixels:Vector.<int> = new Vector.<int>(Math.ceil(MAX_X * MAX_Y / 32));

    public function Foobar() {
        var pre:Number = System.totalMemory;
        init();
        trace("size=" + _itemPixels.length);
        for (var i = 0; i < MAX_Y; ++i) {
            for (var j = 0; j < MAX_X; ++j) {
                trace("item=" + (i*MAX_X+j) + "=" +  isWalkablePixel(j, i));
            }
        }
        trace("memory preInit=" + pre);
        trace("memory postInit=" + System.totalMemory);
    }

    public function init() {
        var MAX_SIZE:int = MAX_X * MAX_Y;
        var id:int = 0;
        var val:int = 0;
        var b:Number = 0;
        for(var y=0; y < MAX_Y; ++y) {
            for (var x = 0; x < MAX_X; ++x) {
                b = Math.round(Math.random()); //lookup the pixel from some kind of texture or however you expose the items
                if (b == 1) {
                    id = Math.floor((y * MAX_X + x) / 32);
                    val = _itemPixels[id];
                    var it:uint = (y * MAX_X + x) % 32;
                    b = b << it;
                    val |=  b;
                    _itemPixels[id] = val;
                }
            }
        }
    }

    public function isWalkablePixel(x, y):Boolean {
        var val:int = _itemPixels[Math.floor((y * MAX_X + x) / 32)];
        var it:uint = 1 << (y * MAX_X + x) % 32;
        return (val & it) != 0;
    }
}

答案 1 :(得分:1)

一个简单的改进是使用ByteArray代替BitmapData。这意味着每个“像素”只占用1个字节而不是4个。这仍然有点浪费,因为你只需要每像素2位而不是8位,但它比使用BitmapData少得多。如果你需要为每个像素存储4个以上的值,它还可以为你提供一些“成长空间”,而不必在以后更改任何重要内容。

ByteArray.readByte() / ByteArray.writeByte()适用于整数,因此使用起来非常方便。当然,在调用writeByte()时只写入整数的低8位。

ByteArray.position设置为您想要从下一个读取或写入开始的点(从0开始的索引)。

总结一下:将ByteArray想象成一个整数值为0-255的整数数组。

答案 2 :(得分:0)

以下是结果,顺便说一句,我使用的是导入的8位彩色.png,不确定当它转换为a时它是否会发生任何变化    的BitmapData。

内存使用情况:

  • BitmapData:100%
  • 双布尔矢量:200%
  • Int Bitshifting:12%

所以int bitshifting赢得了它,它的工作方式与十六进制颜色组件非常相似,但是在这种情况下我存储了16个组件(2位像素值)而不是4 ARGB:

var pixels:int = -1;// in binary full of 1
for (var i:int = 0; i < 16; i++)
    trace("pixel " + (i + 1) +" value : " + (pixels >> i * 2 & 3));

按预期输出: “像素值:3”