zoukankan      html  css  js  c++  java
  • Android---控制设备照相机

    本文译自:http://developer.android.com/training/camera/cameradirect.html

    本文中,我们讨论如何使用框架API来直接的控制照相机硬件。

    直接控制设备等的照相机,比从既存的照相机应用程序中获取图片或视频需要更多的编码。但是,如果你想要创建一个特殊的照相机应用程序,或者要完全与你的应用程序UI集成,那么本文会告诉你如何来做。

    打开Camera对象

    直接控制照相机的第一步时获取一个Camera对象实例。跟Android自己的Camera应用程序一样,推荐访问照相机的方法是从Activity的onCreate()回调中启动一个独立的线程来打开Camera对象。这是一种好的做法,因为打开Camera对象时需要一些时间,这可能会阻塞UI线程。打开照相机的一个更基本的实现,可延迟到onResume()回调方法中,这有助于代码重用,并保持了简单的控制流。

    如果照相机已经被其他的应用程序使用,那么调用Camera.open()方法时会抛出一个异常,因此我们要代码包在在try…catch块中。

    privatebooleansafeCameraOpen(int id){
       
    boolean qOpened = false;
     
        try{
            releaseCameraAndPreview();
            mCamera = Camera.open(id);
            qOpened = (mCamera != null);
        } catch (Exception e) {
            Log.e(getString(R.string.app_name), "failed to open Camera");
            e.printStackTrace();
        }

        return qOpened;    
    }

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

    API Level 9开始,照相机框架支持多个相机。如果你使用传统的API,并调用了没有参数的open()方法,就会获得后置的摄像头。

    创建Camera预览

    通常在点击快门拍照之前,需要预览图片。因此,你可以使用SurfaceView来描绘照相机所扑获的图像。

    创建预览类

    要显示预览图像,就需要创建一个预览类,这个类要实现android.view.SurfaceHolder.Callback接口,它用于把照相机硬件的图像数据传递给应用程序。

    classPreviewextendsViewGroupimplementsSurfaceHolder.Callback{

       
    SurfaceView mSurfaceView;
        SurfaceHolder mHolder;

        Preview(Context context) {
            super(context);

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

            // Install aSurfaceHolder.Callback so we get notified when the
            //underlying surface is created and destroyed.
            mHolder = mSurfaceView.getHolder();
            mHolder.addCallback(this);
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
    ...
    }

    这个预览类在显示预览图像之前,必须把它传递给Camera对象。

    设置和启动图像预览

    一个照相机实例和它相关的预览必须按照特定的顺序来创建,首先是创建 Camera对象。在下面的代码片段中,封装了照相机的初始化过程,这样用户无论何时改变照相机,都可以通过setCamera()方法来调用Camera.startPreviw()方法。这个预览类也必须在预览类的surfaceChanged()回调方法中被重启。

    publicvoidsetCamera(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();
            }
         
            /*
              Important: CallstartPreview() to start updating the preview surface. Preview must
              be started before you cantake a picture.
              */
            mCamera.startPreview();
        }
    }

    修改照相机设置

    照相机设置改变着照相机拍照的方式,从变焦级别到曝光度。这个例子仅改变了预览的尺寸,更多的设置可以看Camera应用程序的源代码。

    publicvoidsurfaceChanged(SurfaceHolder holder,int format,int w,int h){
       
    // Now that the size isknown, set up the camera parameters and begin
        // the preview.
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        requestLayout();
        mCamera.setParameters(parameters);

        /*
          Important: Call startPreview() to startupdating the preview surface. Preview must be
          started before you can take a picture.
        */
        mCamera.startPreview();
    }

    设置预览方向

    大多数照相机应用程序都会把显示锁定到横屏模式,因为这是照相机的自然方向。这种设置不会妨碍你拍摄纵向的照片,因为设备的方向被记录在EXIF头中。使用setCameraDisplayOrientation()方法会改变预览的显示方式,而不会影响到被记录的图像。但是,在API Level 14以前的Android版本,在改变方向之前,必须要先终止预览,然后再重启。

    拍照

    图像预览被启动之后,就可以使用Camera.takePicture()方法来拍摄照片。你可以创建Camera.PictureCallbackCamera.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;
        } // switch
        shutterBtnConfig();
    }

    终止预览并释放Camera对象

    一旦你的应用程序使用完照相机,就是清理的时机。尤其是你必须释放Camera对象,否则可能会让其他应用程序崩溃,包括你自己的应用程序的新的实例。

    在什么时候终止预览并释放Camera对象呢?图像预览类被销毁时是终止图像预览和释放Camera对象的一个相当好的时机,例如:

    publicvoidsurfaceDestroyed(SurfaceHolder holder){
       
    // Surface will bedestroyed when we return, so stop the preview.
        if (mCamera != null) {
            /*
              Call stopPreview() to stopupdating the preview surface.
            */
            mCamera.stopPreview();
        }
    }

    /**
      * When this function returns, mCamera will be null.
      */
    private void stopPreviewAndFreeCamera() {

        if (mCamera != null) {
            /*
              Call stopPreview() to stopupdating the preview surface.
            */
            mCamera.stopPreview();
       
            /*
              Important: Call release() torelease the camera for use by other applications.
              Applications should releasethe camera immediately in onPause() (and re-open() it in
              onResume()).
            */
            mCamera.release();
       
            mCamera = null;
        }
    }

  • 相关阅读:
    Eureka 集群搭建
    Eureka 基本使用操作
    服务治理 Eureka基础认识
    docker-compose命令不存在(docker-compose not found)
    用来存放下一条将要执行的指令地址的寄存器是
    从左线性文法构造有限自动机时,通常自动机状态个数比文法非终结符号数多
    现代多数实用编译程序所产生的目标代码都是一种可重定位的指令代码,在运行前必须借助于一个
    js正则表达式验证端口范围(0-65535)
    IDEA新建Spring配置文件的方法
    webpack-dev-server config.js Cannot find module
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3170389.html
Copyright © 2011-2022 走看看