使用位图高效onDraw,硬件加速复杂剪辑

时间:2013-03-04 19:09:48

标签: java android memory 2d

我正在寻找有关动画内容的最佳渲染(以及可能的缓存)的建议,动画内容的性质是在运行时确定的,无法预先计算。

我正在开发我的第一个Android应用程序,并决定采用相对较短的字母数字代码并将其转换为图像和动画的(当前)“玩具”项目。 (SourceForge项目位于http://sourceforge.net/projects/picturecode,设计文档位于https://docs.google.com/file/d/0B-yO-2scTVuRSkk2NDdiZ3YzTDg/edit?usp=sharing

我正处于这样一个阶段:我正在设计在其他代码中嵌套预定义和用户定义代码的操作,以允许甚至更短代码的更复杂图像。我还试图设计相关的操作,这些操作将有助于使用相对简单的代码表示的类似复杂但有趣的图像。

因此,我认为有用的操作之一是能够使用预定义或用户定义的代码作为掩码来剪辑其他绘图操作。在我发现硬件加速视图中不支持clipPath并强制视图基于软件后,我能够正常工作。 (我的渲染器会检查我们是否处于定义“剪切路径”的模式,并将操作添加到路径而不是在画布上绘制它们,但这样做很乏味,并且不支持所有操作。)

我正在考虑切换回硬件加速模式的替代方案。我想到的是创建一个ALPHA_888位图并绘制到它,而不是在我处于剪切模式时创建剪切路径。这可能具有的一个优点是支持任意操作会更直接;当我处于剪辑模式时,我只是在那个位图而不是主画布上绘制它们。一旦我有了位图,我就假设我可以使用带有适当PorterDuff模式的Paint以drawBitmap(进入另一个中间位图)以某种方式使用它。

我希望有一天我(或任何人,因为项目在SourceForge上)可能会在一个更大的项目中重用这个组件,作为表示可以纯文本传输但短/优化的图形的轻量级方式格式。我认为它是一个动画GIF,但创建更简单,传输更小。

我的问题是:

  1. 硬件加速一般有多重要?这是保留的重要特征还是我应该赞成其他功能? (如果其他人打算使用此功能,我认为他们经常希望组件与硬件加速兼容。)
  2. 屏蔽了一个强大/重要的操作,还是有更好的东西我可以使用(比如纯粹的porter-duff-filtered绘图直接到画布上)?
  3. 我是否正在考虑实施复杂的掩蔽?
  4. 最后最重要

    • 如果有的话,我应该如何使用和管理位图(例如,掩码位图)?当我启动项目时,我注意到在OnDraw期间分配任何新对象是不可取的。所以我预先分配了所有可能的东西 - 一个Paint,一个PointF,一个RectF,一个Path和一些其他的东西,以便我可以在onDraw期间使用它们。目前,我仍然直接绘制画布,但我想知道是否应该在单独的线程上渲染某种缓冲区(如位图),然后在onDraw期间将缓冲区绘制到屏幕上。这是否会破坏硬件加速的目的(并且首先不必关闭视图本身的硬件加速)?更重要的是,如何/何时可以安全地分配这些位图而不会冒犯lint和经验丰富的Android开发人员,他们知道在onDraw期间分配内存很糟糕?如果我在单独的绘图线程上分配位图,我可能必须为每个包含/嵌入图片的每个帧分配一次,因为这些图片可以是动画。或者我可能只想为当前帧分配一个位图,以帮助剪切或合成图像的多个部分。

    很难将其缩小到一个非常具体的问题。我所拥有的是介于一堆问题和一些关于我可能甚至不知道的特征或想法的一般建议的请求之间。我对Java和Android开发相对较新,但对C#,2D图形和游戏开发非常熟悉。我的问题是否指出了我对2D动画在Android上如何运作的理解中的任何明显漏洞?

1 个答案:

答案 0 :(得分:0)

在阅读article about Android hardware acceleration时,我偶然发现了对Canvas的saveLayer函数的引用,我相信这是我在这里遗漏的确切部分。

更新:我已经确认saveLayer就是我所追求的。我没有应用基于路径的复杂剪切区域,而是绘制到那里,而是调用saveLayer创建一个将应用绘图操作的离屏缓冲区,绘制一个图像,将Xfermode切换为SRC_IN,然后绘制第二张图片。这产生两个图像的交叉,第二个图像是可见内容。当我调用恢复时,我基本上会得到第一个图像内容剪切的第二个图像,这比我最初想要完成的更好。