Spritesheet以编程方式切割:最佳做法

我有一个由42帧组成的大型spritesheet(3808x1632)。 我会用这些框架呈现一个动画,并使用一个线程来加载一个包含所有框架的位图阵列,同时启动屏幕等待其结束。 我没有使用SurfaceView(以及画布的绘图功能),我只是在我的主布局中的ImageView中逐帧加载。 我的方法类似于从spritesheet加载大量图像完成实际需要近15秒,不可接受。

我使用这种功能:

for (int i=0; i<TotalFramesTeapotBG; i++) {
            xStartTeapotBG = (i % framesInRowsTeapotBG) * frameWidthTeapotBG; 
            yStartTeapotBG = (i / framesInRowsTeapotBG) * frameHeightTeapotBG;
            mVectorTeapotBG.add(Bitmap.createBitmap(framesBitmapTeapotBG, xStartTeapotBG, yStartTeapotBG, frameWidthTeapotBG, frameHeightTeapotBG));
        }

framesBitmapTeapotBG是大的spritesheet。 更深入地看,我已经在logcat中读到了createBitmap函数花了很多时间,也许是因为spritesheet太大了。 我发现某处我可以在大的spritesheet上创建一个窗口,使用rect函数和画布,创建小型位图来加载数组,但它并不十分清楚。 我在谈论这个帖子:剪掉位图的一部分

我的问题是:我怎样才能加快spritesheet切割?

编辑:我试图使用这种方法,但我看不到最终的动画:

    for (int i=0; i<TotalFramesTeapotBG; i++) {
        xStartTeapotBG = (i % framesInRowsTeapotBG) * frameWidthTeapotBG; 
        yStartTeapotBG = (i / framesInRowsTeapotBG) * frameHeightTeapotBG;
        Bitmap bmFrame = Bitmap.createBitmap(frameWidthTeapotBG, frameHeightTeapotBG, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmFrame); 
        Rect src = new Rect(xStartTeapotBG, yStartTeapotBG, frameWidthTeapotBG, frameHeightTeapotBG); 
        Rect dst = new Rect(0, 0, frameWidthTeapotBG, frameHeightTeapotBG);  
        c.drawBitmap(framesBitmapTeapotBG, src, dst, null);         
        mVectorTeapotBG.add(bmFrame);
    }

可能位图bmFrame的管理不正确。


简短的回答是更好的内存管理。

你正在加载的精灵表非常庞大,然后你将它复制到一堆小的位图上。 假设精灵表不能更小,我建议采取以下两种方法之一:

  • 使用个别位图。 这会减少内存副本以及Dalvik增加堆的次数。 但是,这些好处可能会受到从文件系统而不是一个文件系统加载许多映像的需求的限制。 在普通电脑中就是这种情况,但Android系统可能会得到不同的结果,因为它们在闪存中运行。
  • 从你的精灵表中直接闪烁。 绘图时,只需使用Canvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)等直接从精灵Canvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) 。 这会将您的文件加载减少到一个大的分配,这可能只需要在活动的整个生命周期中进行一次。
  • 我认为第二种选择可能是两者中较好的一种,因为它在内存系统上会更容易,并且对于GC而言更少工作。


    感谢stevehb的建议,我终于明白了:

    for (int i = 0; i < TotalFramesTeapotBG; i++) {
        xStartTeapotBG = (i % framesInRowsTeapotBG) * frameWidthTeapotBG; 
        yStartTeapotBG = (i / framesInRowsTeapotBG) * frameHeightTeapotBG;
        Bitmap bmFrame = Bitmap.createBitmap(frameWidthTeapotBG, frameHeightTeapotBG, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmFrame);  
        Rect src = new Rect(xStartTeapotBG, yStartTeapotBG, xStartTeapotBG+frameWidthTeapotBG, yStartTeapotBG+frameHeightTeapotBG); 
        Rect dst = new Rect(0, 0, frameWidthTeapotBG, frameHeightTeapotBG);  
        c.drawBitmap(framesBitmapTeapotBG, src, dst, null);         
        mVectorTeapotBG.add(bmFrame);
    }
    

    计算时间令人难以置信! :)


    使用LevelListDrawable。 将精灵分割成单独的框架并将它们放入可绘制资源目录中。 以编程方式或通过基于xml的可绘制级别列表创建绘图。 然后使用ImageView.setImageLevel()来选择你的框架。

    链接地址: http://www.djcxy.com/p/68953.html

    上一篇: Spritesheet programmatically cutting: best practices

    下一篇: How to draw a circle with a transparent middle