多媒体应用之控制相机

控制相机

打开相机

获得Camera对象是直接控制相机的第一步。对于Android自带相机应用,控制相机推荐的方法是在onCreate()中开启另外的线程打开相机,以防止阻塞UI线程。在更基本的实现中,打开相机可以在onResume()中执行,以复用代码及保持简单的控制流。
如果相机已经被其它应用占用,调用Camera.open()会抛出一个异常,所以加在try代码块中。

private boolean safeCameraOpen(int id){
    boolean qOpened = false;
    try{
        releaseCameraAndPreview();
        mCamera = Camera.open(id);
        qOpened = (mCamera != null);
    }catch(Exception e){
        Log.e(getString(R.string.app_name),"打开相机失败");
        e.printStackTrace();
    }

    return qOpened;
}

private void releaseCameraAndPreview(){
    mPreview.setCamera(null);
    if(mCamera != null){
        mCamera.release();
        mCamera = null
    }
}

API为9及以上,相机框架支持多个相机,如果使用之前版本的API调用open()不带参数,将会返回第一个后置摄相头。

创建相机预览

拍照之前一般需要看到事物的预览效果,可以使用SurfaceView画出相机传感器正在接收的预览。

Preview类

在显示预览之前,需要preview类。需要实现android.view.SurfaceHolder.Callback接口,用来传输从相机到应用的图像数据。

class Preview extends ViewGroup implements SurfaceHolder.Callback{

    SurfaceView mSurfaceView;
    SurfaceHolder mHolder;

    Preview(Context context){
        super(context);

        mSurfaceView = new SurfaceView(context);
        addView(mSurfaceView);

        //设置SurfaceHolder.Callback,当surface被创建和销毁时可以获得通知
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

    }
...

}

预览类必须在直播的图像预览开始前传递给相机对像。

设置和开始预览

一个相机对象和它相关联的预览必须以特定的顺序创建。在下面的代码片段中,相机初始化的过程被封装,当用户改变相机时,setCamera()方法会调用Camera.startPreview()方法。预览必须在预览类surfaceChanged()方法中重启。

public void setCamera(Camera camera){
    if(mCamera == camera){return;}
    stopPreviewAndFreeCamera();
    mCamera = camera;
    if(mCamera != null){
        List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
        mSupportedPreviewSizes = localSizes;
        requestLayout();

        try{
            mCamera.setPreviewDisplay(mHolder);
        }catch(IOException e){
            e.printStackTrace();
        }

        //注意:调用startPreview()开始更新预览surface。预览必须在拍照之前开启。
        mCamera.startPreview();
    }
}

修改相机设置

相机设置改变相机拍照的方式,从缩放级别到曝光补偿。这个例子只改变预览尺寸。

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h){
    //大小已经知道,设置相机参数和开始预览
    Camera.Parameters parameters = mCamera.getParameters();
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
    requestLayout();
    mCamera.setParameters(parameters);

    //注意:调用startPreview()开始更新预览surface。预览必须在拍照之前开始。
    mCamera.startPreview();
}

设置预览方向

大多数相机应用将显示锁定为横向模式,因为这是相机传感器的自然定位。这个设置并不能阴止你使用竖直模式,因为设备的方向是在EXIF头文件中记录的。setCameraDisplayOrientation()方法能改变预览显示模式并且不影响图片的记录。然而,在API级别为14之前的系统中,必须在改变方向前停止预览,然后重新打开。

拍照

一旦预览启动,就可以通过Camera.takePicture()方法拍照。可以创建Camera.pictureCallback和Camera.ShutterCallback对象,并传递给Camera.takePicture().
如果想要连续的获取图片,可以创建实现了OnPreviewFrame()的Camera.PreviewCallback。对于两者之间的,可以捕获选定的预览帧,或者设定一个延迟的动作来调用takePicture().

重启预览

拍照后,在拍下一张照片前必须重启预览。在本例中,重启是在重载快门按钮中完成的。

@Override
public void onClick(View v){
    switch(mPreviewState){
    case K_STATE_FROZEN:
        mCamera.startPreview();
        mPreviewState = K_STATE_PREVIEW;
        break;

    default:
        mCamera.takePicture(null, rawCallback, null);
        mPreviewState = K_STATE_BUSY;
    }
    shutterBtnConfig();
}

停止预览和释放相机

一旦应用使用相机结束,就该清理了。一般来说,必须释放Camera对象,否则可能会导致其它应用崩溃,包括自己应用的新对象。
当预览surface销毁就可以停止预览和释放相机了,就像之前在Preview类中显示的。

public void surfaceDestroyed(){
    //当返回时Surface会被销毁,所以要停止预览
    if(mCamera != null){
        //调用stopPreview()来停止更新预览surface
        mCamera.stopPreview();
    }
}

private void stopPreviewAndFreeCamera(){
    if(mCamera != null){
        mCamera.stopPreview();

        //注意:调用release()来释放相机以供其它应用使用。应用应该在onPause()中立即释放相机,并且在onResume()中重新打开
        mCamera.release();

        mCamera = null;
    }
}

在文单前面,这个过程也是setCamera()方法的一部分,所以初始化相面就是以停止预览开始。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值