Android,manpulate相机预览帧

Ale*_*dis 6 android preview android-camera

我想制作一个使用相机的Android应用程序,并在预览帧上应用图像处理过滤器.

package alex.filter;

import java.io.IOException;

import android.content.Context;
import android.graphics.Canvas;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

class Preview extends SurfaceView implements SurfaceHolder.Callback {

    SurfaceHolder mHolder;
    public Camera camera;

    Preview(Context context) {
        super(context);
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {        
        camera = Camera.open();        

        try {
            camera.setPreviewDisplay(holder);

            camera.setPreviewCallback(new PreviewCallback() {
                public void onPreviewFrame(byte[] data, Camera arg1) {                    
                    for( int i = 0 ; i < data.length ; i ++ ){
                        data[ i] = 0; // or some sirius filter
                    }                                                            
                    Preview.this.invalidate();
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        }

    public void surfaceDestroyed(SurfaceHolder holder) {        
        camera.stopPreview();        
        camera = null;
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {        
        Camera.Parameters parameters = camera.getParameters();
        parameters.setPreviewSize(w, h);
        camera.setParameters(parameters);
        camera.startPreview();
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);        
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,无论我在onPreviewFrame方法中做什么,我都看不到模拟器中的任何变化.

blu*_*con 1

那是因为您在回调中获得的预览缓冲区只是预览缓冲区的副本,因此您所做的任何修改都不会显示,因为您获得的缓冲区是您的副本。这里在android sdk中提到

我不知道该怎么做,但我一直在考虑如何去做,这是我认为应该做的 -

  • 注册预览缓冲区
  • 禁用默认预览显示
    • 如果您没有将预览显示设置为表面,那么您不应该得到任何显示(但我不确定它是否会起作用 - 已在某些论坛中阅读过它,无法回忆起来源)
    • 如果上述方法不起作用,那么我们将不得不隐藏视图(我知道效率很低,但我想不出其他任何东西..)
  • 降低预览的帧速率,这样我们就不会被缓冲区淹没
  • 现在要显示缓冲区,我们可以使用默认的位图绘制功能或使用 opengl 来显示缓冲区。但我到目前为止都没有使用过,所以甚至不知道它是否可行,有什么想法吗?

更新重新
访问 SDK 文档我发现了这个 API -setPreviewTexture这个 API 允许我们 - “从图像流中捕获帧作为 OpenGL ES 纹理”。一旦获得应用了纹理的图像,您就可以使用 OpenGL 来显示帧。(看看@Stephan 发布的关于如何执行此操作的答案。)

注意 -setPreviewTexture从 API 级别 11 开始可用!SDK链接

  • 我想我可能已经破解了这个 - 再次浏览相机文档并发现这个 `setPreviewTexture` 这允许我们“从图像流中捕获帧作为 OpenGL ES 纹理”,我认为这个 OpenGL ES 纹理是去。完成后,我们可以再次使用 opengl 来显示帧。[SurfaceTexture](http://developer.android.com/reference/android/graphics/Sur​​faceTexture.html) (2认同)