1

我有一个使用 Android 相机的应用程序。

我想实现一个CameraManager类之类的东西,它将处理与相机、打开、关闭、相机参数和帧缓冲区有关的所有事情。

问题是,我想CameraManager从 GUI 中分离出来,但在 Android 中,摄像头似乎与 GUI 不可分离,因为您需要一个surfaceView来获得预览。

我的一个想法是,在初始化之后将CameraManagera 返回surfaceView给 GUI 管理器CameraManager,然后让 GUI 管理器处理所有事情。但是,它还不够分离,因为相机管理器仍在接触 GUI 的东西。

关于如何设法最大化这种封装的任何想法?

4

2 回答 2

1

为什么不使用建议的 Google 方法并在 XML 中实现视图。创建两个自定义表面视图(在我的例子中,一个是 GLSurfaceView,另一个是 SurfaceView)。一个视图实现相机,第二个视图可以处理带有图形和/或按钮的 GUI。关键是在 XML 中创建自定义 GLSurfaceView 和 SurfaceView,使用扩展的 SurfaceView 和 GLSurfaceView 的类名。此外,您必须使 GUI 视图透明。请注意,图形是在 MainRenderer 类中绘制的,此处未包括。请注意,下面的代码存在 OpenGL 上下文丢失问题,我正在努力修复。下面显示的代码应该足以帮助您开始工作,但如果没有 mods,它将无法单独运行......下面的大部分代码都来自 Googles OpenGl Tutorial

OpenGL ES 1.0 教程

用我自己的模组把所有东西分开。

这是 XML:

  <?xml version="1.0" encoding="utf-8"?>
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >                         
<com.zypath.opengltest.MainSurfaceView
    android:id="@+id/glSurfaceView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />                                       
<com.zypath.opengltest.CameraView
    android:id="@+id/camera"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:keepScreenOn="true" />
<LinearLayout
    android:id="@+id/status"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
         android:id="@+id/mangle"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="@string/mangle"
         android:textColor="@color/mcolor" />                       
</LinearLayout>   

主要代码的一部分:

  public class Main extends Activity {
  ...


   @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // When working with the camera, it's useful to stick to one orientation.
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

    //Set full screen
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView(R.layout.main);

    //Substantiate surfaces
    cameraView = (CameraView) findViewById(R.id.camera);
    mGLView = (MainSurfaceView) findViewById(R.id.glSurfaceView);        

    //Initialize TextViews
    txtView = (TextView) findViewById(R.id.mangle);
    txtView.setText("Angle: " + String.valueOf(mAngle)); 


}

自定义 MainSurfaceView 的一部分

  public class MainSurfaceView extends GLSurfaceView {
...

//Constructor
public MainSurfaceView(Context context, AttributeSet attrs) {       
    super(context, attrs);
    this.context = context;

    mRenderer = new MainRenderer();
    setEGLConfigChooser(8, 8, 8, 8, 16, 0); 

    setRenderer(mRenderer);
    getHolder().setFormat(PixelFormat.TRANSLUCENT);    

    setZOrderOnTop(true);

    //Render only when there is a change
    setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);         
}

//TouchEvent handler
  @Override
public boolean onTouchEvent(MotionEvent event) {

    x = event.getX();
    y = event.getY();

    .....

    return true;
}

相机代码的一部分:

  public class CameraView extends SurfaceView implements SurfaceHolder.Callback {
  ...
private Camera camera;
SurfaceHolder holder;

public CameraView(Context context, AttributeSet attrs) {
    super(context, attrs);
    // We're implementing the Callback interface and want to get notified
    // about certain surface events.
    getHolder().addCallback( this );
    // We're changing the surface to a PUSH surface, meaning we're receiving
    // all buffer data from another component - the camera, in this case.
    getHolder().setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS );
}

public void surfaceCreated( SurfaceHolder holder ) {
    // Once the surface is created, simply open a handle to the camera hardware.
    camera = Camera.open();
}

public void surfaceChanged( SurfaceHolder holder, int format, int width, int height ) {

        camera.setPreviewDisplay( holder );

    camera.startPreview();
}
于 2012-06-20T23:53:35.123 回答
0

将表面视图作为参数传递给 CameraManager 构造函数。我希望你让经理开源:)

编辑:这是我在旧项目中使用的(分享是一件好事:P)

相机视图

包 at.fhb.triangulate.gui;
导入android.content.Context;
导入android.content.res.Resources.Theme;
导入android.view.View;
导入 at.fhb.triangulate.main.TriangulateMain;


/*
 * 版权所有 (C) 2007 Android 开源项目
 *
 * 根据 Apache 许可证 2.0 版(“许可证”)获得许可;
 * 除非遵守许可,否则您不得使用此文件。
 * 您可以在以下网址获取许可证的副本
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 除非适用法律要求或书面同意,否则软件
 *根据许可分发是在“原样”基础上分发的,
 * 不提供任何明示或暗示的保证或条件。
 * 请参阅许可证以了解特定语言的管理权限和
 * 许可证下的限制。
 */

导入android.app.Activity;
导入android.content.Context;
导入android.graphics.Canvas;
导入android.hardware.Camera;
导入android.hardware.Camera.Size;
导入android.os.Bundle;
导入android.view.SurfaceHolder;
导入android.view.SurfaceView;
导入android.view.Window;

导入 java.io.IOException;
导入 java.util.List;


公共类 CameraView 扩展 SurfaceView 实现 SurfaceHolder.Callback {
    SurfaceHolder mHolder;
    相机 mCamera;

    公共CameraView(上下文上下文){
        超级(上下文);

        // 安装一个 SurfaceHolder.Callback 以便我们在
        // 创建和销毁底层表面。
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    公共无效surfaceCreated(SurfaceHolder持有人){
        // Surface 已创建,获取相机并告诉它在哪里
        // 绘制。
        mCamera = Camera.open();
        尝试 {
           mCamera.setPreviewDisplay(holder);
        } 捕捉(IOException 异常){
            mCamera.release();
            mCamera = null;
            // TODO: 在此处添加更多异常处理逻辑
        }
    }

    公共无效surfaceDestroyed(SurfaceHolder持有人){
        // 返回时 Surface 将被销毁,因此停止预览。
        // 因为CameraDevice对象不是共享资源,所以非常
        // 当活动暂停时释放它很重要。
        mCamera.stopPreview();
        mCamera = null;
    }


    公共无效surfaceChanged(SurfaceHolder持有人,int格式,int w,int h){
        // 现在知道大小,设置相机参数并开始
        // 预览。
        Camera.Parameters 参数 = mCamera.getParameters();
        参数.setPreviewSize(w, h);
       // parameters.set("orientation", "portrait");

        mCamera.setParameters(参数);
        mCamera.startPreview();
    }

}



于 2012-04-22T18:15:13.860 回答