我正在尝试将我用java编写的模拟器移植到android。事情进展顺利,我能够通过微小的更改移植我的大部分代码,但由于仿真的工作方式,我需要在像素级别渲染图像。
对于桌面java,我使用
int[] pixelsA = ((DataBufferInt) src.getRaster().getDataBuffer()).getData();
允许我获取像素缓冲区的引用并动态更新(最小化对象创建)
目前这是我的Android模拟器为每一帧做的
@Override
public void onDraw(Canvas canvas)
{
buffer = Bitmap.createBitmap(pixelsA, 256, 192, Bitmap.Config.RGB_565);
canvas.drawBitmap(buffer, 0, 0, null);
}
pixelsA是一个数组int [],pixelsA包含所有颜色信息,因此每个帧都必须通过
创建一个位图对象buffer = Bitmap.createBitmap(pixelsA, 256, 192, Bitmap.Config.RGB_565);
我相信这是非常昂贵和缓慢的。
有没有办法用画布有效地绘制像素?
答案 0 :(得分:10)
一种非常低级的方法,但对我来说工作正常(使用本机代码):
创建Bitmap
对象,与可见屏幕一样大。
还要创建一个View
对象并实现onDraw
方法。
然后在本机代码中,您将加载libjnigraphics.so本机库,查找函数AndroidBitmap_lockPixels
和AndroidBitmap_unlockPixels
。
这些函数在bitmap.h中的Android源代码中定义。
然后你会在位图上调用锁定/解锁,接收原始像素的地址。您必须根据实际情况(16位565或32位8888)解释RGB格式的像素。
更改位图的内容后,您希望在屏幕上显示此内容。
在View.invalidate()
上致电View
。在onDraw
中,将您的位图blit到给定的Canvas
。
这种方法水平很低,取决于Android的实际实现,但是速度非常快,你可能会得到60fps没问题。
bitmap.h是Android NDK自平台版本8以来的一部分,因此这是从Android 2.2执行此操作的官方方式。
答案 1 :(得分:4)
您可以使用drawBitmap method来避免每次创建位图,或者甚至作为最后的手段,使用drawPoint逐个绘制像素。
答案 2 :(得分:0)
不要每次都重新创建位图。尝试这样的事情:
Bitmap buffer = null;
@Override
public void onDraw(Canvas canvas)
{
if(buffer == null) buffer = Bitmap.createBitmap(256, 192, Bitmap.Config.RGB_565);
buffer.copyPixelsFromBuffer(pixelsA);
canvas.drawBitmap(buffer, 0, 0, null);
}
编辑:正如所指出的,您需要更新像素缓冲区。并且位图必须是可变的才能实现。
答案 3 :(得分:0)
如果pixelsA已经是一个像素数组(这是我在你关于包含颜色的说法中推断出的那样)那么你可以直接渲染它们而不用转换为:
canvas.drawBitmap(pixelsA, 0, 256, 0, 0, 256, 192, false, null);