加载图像不会将它们加载到内存中

时间:2014-01-29 22:52:52

标签: actionscript-3 memory bitmap bitmapdata

我正在将一批150张高清图像加载到我的应用程序中 - 它基本上是一个对象的3D视图。一旦我使用Loader实例加载图像文件,我将加载器的第一个孩子的bitmapdata存储在Vector中。当所有的加载,我想开始“旋转”对象=意味着我只是交换图像。我拿到了Vector,我有bitmapdatas并将它们一个接一个地绘制到一个画布bitmapdata上。那里没有科学,它都按预期工作。

问题在于,一旦所有图像都被加载并存储在矢量中,并且在将它们绘制到画布之前,它们就不在内存中。这意味着我的3D对象的第一次旋转( - >所有150个绘制的图像)非常慢。第一次旋转后没有问题,一切都是流动的。我的问题是:有没有办法强制图像加载到内存而不将它们绘制到舞台上?我预计一旦加载到app,它们就会被加载到内存中(错误!)。

我尝试使用addChild()而不是将它们绘制到画布位图,结果相同。我不认为代码是必要的,但以防万一:

private var _loaders:Vector.<Loader>;
private static const NAME:String = "img_00";
private static const MIN:uint = 0;
private static const MAX:uint = 150;
private var _loaded:uint = 0;
private var _currentFrameIndex:uint = 0;
private var _canvas:Bitmap;
private var _bitmaps:Vector.<BitmapData>;
private var _destPoint:Point;

public function loadImages():void {
    var s:String;
    for(var i:int=MIN; i<=MAX; i++) {
        if(i < 10) s = "00" + i;
        else if(i < 100) s = "0" + i;
        else s = i.toString();
        var loader:Loader = new Loader();
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadHandler);
        loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadHandler);
        loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loadHandler);
        loader.load(new URLRequest("images/JPEG/"+ NAME + s + ".jpg"));
        _loaders.push(loader);
    }
}

private function loadHandler(e:Event):void {
    _loaded++;

    if(_loaded > (MAX - MIN)) {
        _bitmaps = new Vector.<BitmapData>(_loaders.length);
        for(var i:int=0; i<_loaders.length; i++) {
            var loader:Loader = _loaders[i];
            _bitmaps[i] = Bitmap(loader.getChildAt(0)).bitmapData;
            loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadHandler);
            loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, loadHandler);
            loader.contentLoaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, loadHandler);
        }
        setFrame(0);
        dispatchEvent(new Event(LOAD_COMPLETE));
    }
}

public function setFrame(frame:uint):void {
    if(frame >= 0 && frame < _bitmaps.length) {
        _currentFrameIndex = frame;
        var bmpData:BitmapData = _bitmaps[_currentFrameIndex];
        _canvas.bitmapData.copyPixels(bmpData, bmpData.rect, _destPoint);
    }
}

1 个答案:

答案 0 :(得分:0)

“不在内存中”意味着图像已加载但尚未解码,并且此解码是即时完成的,这会使您观察到的时间变慢。您可以尝试“虚拟”旋转图像,方法是将尚未添加到舞台的位图作为对矢量的每个bitmapDatas的引用。创建一个进度条,显示已经解码了多少向量,一旦发生这种情况,显示位图并为用户提供平滑的旋转。

addEventListener(Event.ENTER_FRAME,prerender);
var b:Bitmap=new Bitmap();
/* optional
    b.x=stage.stageWidth;
    b.y=stage.stageHeight;
    addChild(b);
*/
var vi:int=0;
var sh:Shape=new Shape();
sh.graphics.lineStyle(4,0,1); // a simple progress bar
sh.graphics.moveTo(0,0);
sh.graphics.lineTo(100,0);
sh.scaleX=0;
sh.x=stage.stageWidth/2-50; // centered by X
sh.y=stage.stageHeight/2;
addChild(sh);
function prerender(e:Event):void {
    if (vi==_bitmaps.length) {
        // finished prerender
        removeEventListener(Event.ENTER_FRAME, prerender);
        removeChild(sh);
        // removeChild(b); if optional enabled
        setFrame(0);
        return;
    }
    b.bitmapData=_bitmaps[vi];
    vi++;
}

此外,如果您不打算更改位图数据,最好将bitmapData属性分配给Bitmap对象。因此,您只需执行_canvas.bitmapData.copyPixels(bmpData, bmpData.rect, _destPoint); _canvas.bitmapData = bmpData;而不是destPoint,而且它会起作用。

更新:您的问题可能与最后一点有关,即分配而不是复制。如果您的Bitmap不是(0,0),那么您只需在_canvas之上创建另一个Vector.<BitmapData>对象并使用所需的偏移量,并在其中分配bitmapdatas。我记得当我第一次基于像你一样的copyPixels()制作多个动画对象,并尝试做_bitmap.bitmapData=_bitmaps[currentFrame]时,我的动画是抖动的,没有显示正确的帧,但是一旦我做了{{1}一切都变得如此顺利。