在尝试获取相机预览的像素时,我的表现非常糟糕。
图像格式约为600x900。 在我的HTC上,预览率非常稳定30fps。
一旦我尝试获取图像的像素,帧速率就会降到5以下!
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
Bitmap bmp = mTextureView.getBitmap();
int width = bmp.getWidth();
int height = bmp.getHeight();
int[] pixels = new int[bmp.getHeight() * bmp.getWidth()];
bmp.getPixels(pixels, 0, width, 0, 0, width, height);
}
性能太慢,实际上并不可忍受。
现在我唯一的'简单'解决方案是跳帧,至少保持一些视觉表现。 但我真的希望让代码执行得更快。
我很感激任何想法和建议,也许有人已经解决了这个问题?
更新
getbitmap: 188.341ms
array: 122ms
getPixels: 12.330ms
recycle: 152ms
获取位图需要190毫秒!!这就是问题
答案 0 :(得分:3)
我挖了几个小时。
如此简短的回答:我发现无法避免使用getBitmap()并提高性能。 已知这个函数很慢,我发现了很多类似的问题而没有结果。
然而,我找到了另一种解决方案,它的速度提高了约3倍,并为我解决了问题。 我继续使用TextureView方法,我使用它,因为它为如何显示相机预览提供了更多自由(例如,我可以在我自己的宽高比的小窗口中显示相机实时预览而不会失真)
但是为了处理图像数据,我不再使用onSurefaceTextureUpdated()了。
我注册了cameraPreviewFrame的回调函数,它给出了我需要的像素数据。 所以没有getBitmap,而且速度更快。
快速,新代码:
myCamera.setPreviewCallback(preview);
Camera.PreviewCallback preview = new Camera.PreviewCallback()
{
public void onPreviewFrame(byte[] data, Camera camera)
{
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = parameters.getPreviewSize();
Image img = new Image(size.width, size.height, "Y800");
}
};
<强>慢:强>
private int[] surface_pixels=null;
private int surface_width=0;
private int surface_height=0;
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture)
{
int width,height;
Bitmap bmp= mTextureView.getBitmap();
height=barcodeBmp.getHeight();
width=barcodeBmp.getWidth();
if (surface_pixels == null)
{
surface_pixels = new int[height * width];
} else
{
if ((width != surface_width) || (height != surface_height))
{
surface_pixels = null;
surface_pixels = new int[height * width];
}
}
if ((width != surface_width) || (height != surface_height))
{
surface_height = barcodeBmp.getHeight();
surface_width = barcodeBmp.getWidth();
}
bmp.getPixels(surface_pixels, 0, width, 0, 0, width, height);
bmp.recycle();
Image img = new Image(width, height, "RGB4");
}
我希望这能帮助一些有同样问题的人。
如果有人想在onSurfaceTextureUpdated中找到快速创建位图的方法,请回复代码示例。
答案 1 :(得分:0)
请尝试:
public void OnSurfaceTextureUpdated(SurfaceTexture surface) {
if (IsBusy) {
return;
}
IsBusy = true;
DoBigWork();
IsBusy = false;
}