从大型BitmapData调用copyPixels有时需要200-300ms

时间:2015-01-08 16:50:20

标签: performance actionscript-3 flash

我尝试使用BitmapData方法从大型BitmapData(约2000x4000)获得小copyPixels(约500x500)。在每个帧期间,我将获得一个带有copyPixels调用的小型BitmapData。

在一帧中,滞后变得非常高。使用Adobe Scout CC,我发现" UnCompress Image"耗资200-300毫秒,但在其他一些框架。因为当我用小源BitmapData调用copyPixels时没有发生,我想原因是源BitmapData太大了?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

嗯,这不是你问题的答案。这是为了说明copyPixels()没有明显的问题。这是一个简单的独立测试,您可以将其复制并粘贴到新项目中,看看会发生什么(只需将有问题的图像放入输出文件夹)。除了copyPixels()之外,我删除了任何耗时的测试。

似乎问题出在其他地方,需要更多关于问题的信息。

package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.events.Event;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.net.URLRequest;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.utils.getTimer;

    [SWF(backgroundColor="0xFFFFFF", width="1024", height="768", frameRate="60")]
    public class StackCopyPixels extends Sprite
    {
        private var sourceImage:BitmapData;
        private var loader:Loader;
        private var targetImage:BitmapData;
        private var timeLabel:TextField;
        private var log:String = "";
        private var count:int = 0;
        private var sizeLimit:int;
        private var sourceRect:Rectangle;
        private var destPoint:Point;

        public function StackCopyPixels()
        {
            stage.align = StageAlign.TOP_LEFT;
            loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
            // in my case the image is 3450x720, so it's bigger than BitmapData limit of 2880 px
            // (which I figured could be the source of the problem)
            loader.load(new URLRequest("image.png"));

            targetImage = new BitmapData(500, 500, true, 0);
            addChild(new Bitmap(targetImage));

            timeLabel = new TextField();
            timeLabel.autoSize = TextFieldAutoSize.LEFT;
            timeLabel.background = true;
            timeLabel.multiline = true;
            timeLabel.wordWrap = false;
            addChild(timeLabel);
        }

        protected function onImageLoaded(event:Event):void
        {
            var image:Bitmap = loader.content as Bitmap;
            sourceImage = image.bitmapData;
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
            sizeLimit = Math.floor(sourceImage.width/targetImage.width);
            sourceRect = targetImage.rect;
            destPoint = new Point();
        }

        protected function onEnterFrame(event:Event):void
        {
            var s:int = getTimer();

            sourceRect.x = (count%sizeLimit)*500;
            sourceRect.y = Math.floor(Math.random()*(sourceImage.height-sourceRect.height));
            targetImage.copyPixels(sourceImage, sourceRect, destPoint);

            var elapsed:int = getTimer()-s;
            if (elapsed > (1000/60*2)) {
                log += "\nslow at "+count+" (position "+(count%sizeLimit)+"): "+elapsed;
            }
            timeLabel.text = elapsed.toString()+log;

            count++;
        }
    }
}

答案 1 :(得分:0)

我不知道这是否是解决方案(很难说我们没有其他信息,但请考虑一下:

每次使用'图像时,都需要解压缩。即使你维护它的bitmapData。听起来很有趣。因此,我们假设您要显示(甚至访问图像)刚加载的图像。 Flash将拍摄图像,对其进行解压缩(很可能是您正在经历的击中)并显示它或在其上调用方法bitmapData。解码内容需要不同的时间,具体取决于位图的大小。

在许多情况下这是不可接受的,因此您可以在此处查看解决方法:Keeping Bitmaps Decompressed。这个想法只是简单地“ping”bitmapData或者每隔X秒就对它执行一些方法,这样Flash运行时就不会从内存中释放它(只有当图像没有显示在显示列表的某个地方时才释放它),否则它将不得不再次解压缩。或者你可以只在显示列表上显示图像......在这种情况下它肯定是解压缩的。

我自己遇到了同样的问题(按序列显示150个高清图像) - 第一次运行总是不稳定,如果动画没有停止因为停止将连续运行从内存中清除,则连续运行正常。访问位图中像素的方法运行得很完美(即使我实现的方式有点不同;我还没读过那篇文章)。