• Camera实现预览、拍照


    1.利用Intent方法实现拍照并保存

    在菜单或按钮的选择操作中调用如下代码,开启系统自带Camera APP,并传递一个拍照存储的路径给系统应用程序,具体如下:
    
    imgPath = "/sdcard/test/img.jpg";
    
    //必须确保文件夹路径存在,否则拍照后无法完成回调
    
    File vFile = new File(imgPath);
    
    if(!vFile.exists())
    
    {
    
    File vDirPath = vFile.getParentFile(); //new File(vFile.getParent());
    
    vDirPath.mkdirs();
    
    }
    
    Uri uri = Uri.fromFile(vFile);
    
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    
    intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);//
    
    startActivityForResult(intent, SystemCapture);
    
    上面我们使用的是startActivityForResult,所以最好需要重载void onActivityResult(int requestCode, int resultCode, Intent data)函数,不过因为当传入文件路径的的情况下,data返回参数是null值,只要resultCode为RESULT_OK,则上述代码中/sdcard/test/img.jpg的图片文件就是最新的照片文件。所以我们在这里只需给出如下简单的代码,将其显示到ImageView中
    
    if (resultCode == RESULT_OK) 
    
    {
    
    iViewPic.setImageURI(Uri.fromFile(new File(imgPath)));
    
    }

    假设不传参数MediaStore.EXTRA_OUTPUT的情况下,onActivityResult函数在resultCode为RESULT_OK的情况下,data返回的参数是经过实际拍摄照片经过缩放的图像数据,可以通过类似如下方法来打印缩放图像的尺寸

    if (resultCode == RESULT_OK) 
    
    {
    
    Bitmap bmp = (Bitmap)data.getExtras().get("data");
    
    Log.d("Test", "bmp " + bmp.getWidth() + ", height:" + bmp.getHeight());
    
    }
    
    另外假如仅仅是调用系统照相机拍照,不关心拍照结果,则可以简单使用如下代码
    
    Intent intent = new Intent(); //调用照相机
    
    intent.setAction("android.media.action.STILL_IMAGE_CAMERA");
    
    startActivity(intent);

    备注:上面设置MediaStore.EXTRA_OUTPUT的方法,经过手机实测除了我们设定的路径下有照片外,在手机存储卡上也会保存一份照片,默认目录为sdcard/dcim/camera下面,我曾经尝试着想如果每次返回可以取得sdcard/dcim/camera下面的路径就好了,但是目前看来没办法直接获得,可以借助MediaStroe每次去查询最后一条照片记录,应该也是可行的。

    2.利用Camera类实现浏览/拍照

    1.Camera类

    使用Camera控制拍照的几个步骤:

    1、设置打开相机的权限

    <uses-permission android:name = "android.permission.CAMERA" />
    
    <uses-feature android:name = "android.hardware.camera" />
    
    <uses-feature android:name = "android.hardware.camera.autofocus" />
    
    一般拍照和摄像的时候需要写到sd卡上,所以还有一向权限声明如下
    
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
    真做摄像功能时,需要音频录制和视频录制功能,所以又需要下面两项权限声明
    
    <uses-permission android:name="android.permission.RECORD_VIDEO"/>
    
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>

      user-feature:概述:<uses-feature>用来声明应用中需要用的硬件和软件的功能。

      硬件特性:表明您的应用需要用的硬件功能。   如果没有这种硬件,则app不被使用

    
    

    2、调用Camera的open()打开相机

        public static Camera open(int cameraId)
        在API9之后引用的,如果设备小于API9则无法使用
        打开相机
        
        public static Camera open()
        在API9之前使用的方法
    
        解析:在SDK 2.3之前,是没有参数的,2.3以后支持多摄像头,所以开启前可以通过getNumberOfCameras先获取摄像头数目,再通过getCameraInfo得到需要开启的摄像头id,
    然后传入Open函数开启摄像头,假如摄像头开启成功则返回一个Camera对象,否则就抛出异常;传入0打开默认摄像头(一般是后置)

    3、调用Camera的getParameters()获取拍照参数。该方法返回一个Camera.Paremeters对象

    4、调用Camera.Parameters对象方法设置拍照的参数(参数就是照片的长、宽、是竖还是横之类的参数)

    5、调用Camera.startPreview()方法开始预览取景,在预览取景之前需要调用Camera的setPreviewDisplay(SurfaceHolder holder)方法设置使用哪个SurfaceView来显示取景图片。(稍后介绍)

    6、调用Camera的takePicture()方法进行拍照

        public final void takePicture(Camera.ShutterCalback shutter,Camera.PictureCallback raw,Camera.PictureCallback jpeg)     

        //方法中的三个参数是三个回调接口,实现接口并传入该方法中  

        shutter 接口的意义:在相机捕获图像的时候调用  (按快门的时候)  

        raw :在原始图像数据可用的时候调用。  

        jpeg:在JEPG版本的图像可用时调用      (原始数据转换成jpeg格式时候回调)

        如果不要接口:则使用null代替

    7、结束程序时,调用Camera的stopPreview()结束取景预览,并调用release()方法释放资源 

    2、SurfaceView、SurfaceHolder与Surface

    SurfaceView:SurfaceView是视图(View)的继承类,这个视图里内嵌了一个专门用于绘制的Surface。

    Surface:定义:代表着原始数据的缓冲区。

                 Surface拥有自己的生命周期:当SurfaceView出现在屏幕上的时候,创建Surface。

                                                        当SurfaceView消失在屏幕上的时候,销毁Surface。

                 作用:将数据绘制在缓冲区中。Surface及其协同对象都不会自己绘制对象,要将内容绘制到缓冲区的对象让Surface的客户端在Surface未创建时,不能将内容绘制到其上。 所以说当Surface创建的时候开始绘制  当 Surface销毁后 让Camera对象取消绘制。

    SurfaceView与Surface的关系:  SurfaceView提供了一个可见区域,只有在这个可见区域内的Surface才能显示。(SurafaceView一般作为控件使用)

    SurfaceHolder:SurfaceHolder是控制surface的一个抽象接口。

                           1.用于控制Surface的生命周期。

                           2.让协同对象将数据流入Surface的接口。

    实例

     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //在res/activity_main中创建了SurfaceView控件
            SurfaceView surfaceView = (SurfaceView) findViewById(R.id.main_surfaceView);
            //获取SurfaceHolder类
            SurfaceHolder surfaceHolder = surfaceView.getHolder();
            //回调Surface的生命周期
            surfaceHolder.addCallback(new SurfaceHolder.Callback() {
                //当被创建的时候显示
                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                }
                //当Surface大小、格式改变的时候回调。首次显示在屏幕上调用。参数是Surface的像素格式、宽、高
                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                }
                //当Surface被销毁的时候显示
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
    
                }
            });
        }
    View Code

    总结:从SurfaceView对象中产生Surface对象,然后通过SurfaceHolder控制Surface对象,SurfaceHolder提供Callback接口控制绘制流程。

    3.Camera与Surface的关系

       mCamera将获取到的数据通过SurfaceHolder对象输入到Surface的缓冲区上。然后由Camera在SurfaceHolder提供的Callback接口决定是否开始或者停止绘制在SurfaceView上(用来预览图片)。

    详细Camera类的使用:http://www.cnblogs.com/franksunny/archive/2011/11/17/2252926.html

    详细Surface类的使用:http://blog.csdn.net/conowen/article/details/7821409

  • 相关阅读:
    4、Work-Queue
    一个简单servlet容器
    一个简单的Web服务器
    jersey实现RESTful接口PUT方法JSON数据传递
    Java数据库连接组件C3P0和DBCP
    C/S架构和B/S架构
    一些同样适用于人生的计算机原理
    网络编程初探--使用UDP协议的简易聊天室
    IO练习--按字节截取字符串
    IO包中的其他类总结
  • 原文地址:https://www.cnblogs.com/rookiechen/p/5244772.html
Copyright © 2020-2023  润新知