2011-09-29 90 views
8

我试图移植一个模拟器,我已经写在java到android。事情一直很好,我能够移植我的大部分代码,但由于模拟的工作原因,我需要在像素级渲染图像。android快速像素访问和操作

至于桌面Java我使用

int[] pixelsA = ((DataBufferInt) src.getRaster().getDataBuffer()).getData(); 

这让我获得参考像素缓冲区和更新上飞(最小化对象的创建)

目前,这是我的什么模拟器机器人确实对于每一帧

@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

真,createBitmap是缓慢的,它是内存拷贝,甚至是像素格式在你的情况下的转换! –

回答

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); 
} 

编辑:如指出,你需要更新像素缓冲区。位图必须是可变的才能发生。

+0

这不起作用。位图在createBitmap中初始化其自己的像素缓冲区,而不调用它将不会更新位图的像素。 –

10

一个相当低的水平的方法,但做工精细,我(本机代码):

创建Bitmap对象,大如你的可视屏幕。 也创建一个View对象并实现onDraw方法。

然后在本机代码中,您将加载libjnigraphics.so本机库,查找函数AndroidBitmap_lockPixelsAndroidBitmap_unlockPixels。 这些函数在Android源代码中是在bitmap.h中定义的。

然后,你会调用位图上的锁定/解锁,接收原始像素的地址。您必须相应地将RGB像素格式解释为它的真实含义(16位565或32位8888)。

更改位图的内容后,您希望在屏幕上显示此内容。 致电View.invalidate()在您的View。在其onDraw中,将您的位图分成给定的Canvas

这种方法是非常低的水平和依赖于Android的实际实施,但它非常快,你可能会得到60fps没有问题。

bitmap.h是自平台版本8以来的Android NDK的一部分,所以这是官方的方式来从Android 2.2做到这一点。

4

您可以使用drawBitmap method避免每次创建一个位图,或甚至作为最后的手段,与drawPoint一个接一个地绘制像素。

+0

我尝试了以int []作为参数的drawBitmap方法,它在位图对象创建时提供了很好的性能提升。这似乎是唯一的方法(我认为)在不诉诸本地代码的情况下达到可接受的性能。 – afro100

+1

很高兴知道它的工作。就像你说的那样,没有什么东西像原生的一样快,但它要复杂得多。 –

0

如果pixelsA已经是像素阵列(这是我想从你的陈述推断出含有色),那么你可以使它们的情况下直接与转换:

canvas.drawBitmap(pixelsA, 0, 256, 0, 0, 256, 192, false, null);