2014-01-29 5 views
1

내 앱에 150 개의 HD 이미지를로드하고 있습니다. 기본적으로 오브젝트의 3D보기입니다. 일단 Loader 인스턴스를 사용하여 이미지 파일을로드하면 로더의 첫 번째 자식의 비트 맵 데이터를 Vector에 저장합니다. 로드가 모두 끝나면 객체를 "회전"하기를 원합니다. = 단순히 이미지를 교환하는 것입니다. 나는 Vector를 가져 와서 비트 맵 데이터를 가져 와서 캔버스 비트 맵 데이터에 하나씩 그립니다. 거기에는 과학이 없으며 모든 것이 의도 한대로 작동합니다.이미지를로드해도 메모리에로드되지 않습니다.

문제는 일단 모든 이미지가 벡터에로드되고 저장되면 캔버스에 그려지기 전에 메모리에 저장되지 않는다는 것입니다. 즉, 내 3D 오브젝트의 첫 번째 회전 (-> 150 개 이미지 모두 그려짐)이 실제로 느려진다는 것을 의미합니다. 첫 번째 회전 후에 문제가 없으며 모두 유동적입니다. 제 질문은 : 무대에 그림을 그리지 않고 이미지를 강제로 메모리에로드하는 방법이 있습니까? 나는 그들이 앱에로드되면 메모리에로드 될 것이라고 예상했다 (Wrong!).

동일한 결과를 캔버스 비트 맵에 그리는 대신 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

는 "아니 메모리에"이미지가로드, 아직 디코딩되지,이 디코딩은 즉시 수행되며,이 것을 의미 느리게 관찰하는 시간이 걸립니다. 아직 스테이지에 추가되지 않은 비트 맵을 벡터의 각 비트 맵 데이터에 대한 참조로 사용함으로써 이미지를 "가상으로"회전 할 수 있습니다. 얼마나 많은 벡터가 이미 디코드되었는지를 보여주는 진행 막대를 만들고, 이것이 발생하면 비트 맵을 표시하고 사용자에게 부드러운 회전을 제공하십시오.

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 객체를 만들고 거기에 bitmapdatas를 할당합니다. 내가 처음에 복수의 애니메이션 객체를 만들었을 때 과 비슷한 것을 시도하고 copyPixels()을 시도했을 때 내 애니메이션이 지터 롭고 적절한 프레임을 표시하지 못했지만 일단 내가 한 번 _bitmap.bitmapData=_bitmaps[currentFrame] 모든 것이 매끄러 웠습니다.

+0

나는 그것을 정확히 추측했다. 이미지는 아직 디코딩되지 않았다. (메모리 사용과 느려짐을 설명 할 것이다.) 잘, 너무 나쁘다, 나는 사용자가 조금 더 기다려야 할 것이라는 점을 짐작한다. 감사! – Fygo

+0

추신 : 렌더링 비트 맵은 표시 목록에 있어야하며 반드시 표시되어야합니다. 그렇지 않으면 작동하지 않으므로 addChild/removeChild가이 경우 선택적이 아닌 것처럼 보입니다. (그래서 그냥 주 캔버스에 렌더링 될 수 있습니다). – Fygo

+0

흥미 롭습니다. 좋아, 다행이야. – Vesper