2014-01-29 116 views
1

我正在将一批150张HD图像加载到我的应用程序中 - 它基本上是一个对象的3D视图。一旦我使用Loader实例加载图像文件,我将加载器的第一个孩子的位图数据存储在Vector中。当所有的加载,我想开始“旋转”的对象=意味着我只是交换图像。我将矢量放在我有位图数据的位置,然后依次将它们绘制到画布位图数据上。那里没有科学,一切都按预期工作。加载图像不会将它们加载到内存中

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

我试图使用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); 
    } 
} 

回答

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对象,如果你不打算让该BitmapData改变。所以,而不是你的_canvas.bitmapData.copyPixels(bmpData, bmpData.rect, _destPoint);你只是做_canvas.bitmapData = bmpData;,它会工作。

更新:你的问题不妨指出最后一点,即分配而不是复制。如果您的destPoint不是(0,0),则只需在_canvas的顶部再制作一个Bitmap对象,并使用所需的偏移量,然后在其中分配位图数据。我记得当我第一次制作多个基于像你的单一的动画对象,并试图做copyPixels()时,我的动画抖动并且没有显示正确的帧,但是一旦我做了_bitmap.bitmapData=_bitmaps[currentFrame],一切都变得顺利。

+0

我猜测它正是这样 - 图像还没有解码(将解释内存使用情况和缓慢)。好吧,太糟糕了,我想用户将不得不等待更多。谢谢! – Fygo

+0

PS:渲染位图务必在显示列表上,它必须是可见的。否则它将无法工作,因此在这种情况下,addChild/removeChild看起来不是可选的。 (所以它可以在主画布上呈现)。 – Fygo

+0

有趣。好吧,我很高兴你有这个。 – Vesper