Android多媒体—拍照Camera

来源:互联网 发布:iwatch软件 编辑:程序博客网 时间:2024/05/18 02:10

完成一个拍照功能需要完成两个部分,一个是预览(preview),一个是拍照。

1.预览功能

我们使用SurfaceView在屏幕上渲染出一片区域,然后将摄像头捕捉到的画面显示在该区域内。Surface的设置有以下5个步骤:
1. 创建一个SurfaceView
2. 获得操作对象
3. 获得SurfaceHolder对象
4. 实现SurfaceHolder.CallBack接口,并传递给SurfaceHolder
5. 设置SurfaceHolder类型

(1)在xml文件中创建SurfaceView

 <SurfaceView             android:id="@+id/surfaceView1"            android:layout_width="320px"            android:layout_height="240px"/>

(2)获得对象SurfaceView sv=(SurfaceView) findViewById(R.id.surfaceView1);
(3)holder=sv.getHolder(); //获得holder对象
(4)回调接口

public void surfaceChanged(SurfaceHolder arg0,int arg1,int arg2,int arg3)    {        if(camera!=null){        camera.release();        }    }    public void surfaceCreated(SurfaceHolder arg0)    {    }    public void surfaceDestroyed(SurfaceHolder arg0)    {        if(camera!=null){            camera.release();            camera=null;        }    }

之后使用holder.addCallback(this); 便实现了将参数传递给了SurfaceHolder
(5)设置类型

2.配置Camera预览参数

有以下5个步骤:
1. 获得Camera对象
2. 获得相机参数
3. 设置预览大小
4. 绑定SurfaceView
5. 开始预览

3.拍摄功能

Camera.takePicture(ShutterCalback shutter,PictureCallback raw,
PictureCallback jpeg),可以只实现第三个回调函数实现拍照功能。
实现PictureCallback jpeg接口:
在该接口中要实现方法:
public void onPictureTaken(byte[] data, Camera camera)
第一个参数是照片原始数据,用位图表示
Bitmap bm=BitmapFactory.decodeByteArray(data, 0, data.length);
之后可以保存为文件了
bm.compress(CompressFormat format, int quality, OutputStream stream);


实现简易相机

首先要在注册文件中获得相应权限:

<uses-permission android:name="android.permission.CAMERA"></uses-permission><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus"/>

实现代码:

public class MainActivity extends Activity implements SurfaceHolder.Callback {//实现callback接口    SurfaceView sv;    SurfaceHolder holder;    Button preview_btn;    Button take_btn;    ImageView iv;    Camera camera;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);    //  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//横向屏幕        initView();        preview_btn.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                // TODO 自动生成的方法存根                preview();//开始预览                //camera.autoFocus(afc);//可实现自动对焦功能            }        });        take_btn.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                // TODO 自动生成的方法存根                takePicture();            }        });    }private AutoFocusCallback afc=new Camera.AutoFocusCallback() {//自动对焦的接口,对焦完毕则拍照        @Override        public void onAutoFocus(boolean success, Camera camera) {            // TODO 自动生成的方法存根            if(success)            {                takePicture();            //  camera.cancelAutoFocus();            }        }    };    private void initView() {        // TODO 自动生成的方法存根        sv=(SurfaceView) findViewById(R.id.surfaceView1);        iv=(ImageView)findViewById(R.id.imageView1);        preview_btn=(Button)findViewById(R.id.button1);        take_btn=(Button)findViewById(R.id.button2);        holder=sv.getHolder(); //获得holder对象        holder.addCallback(this); //添加回调函数接口        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型    }//预览函数    protected void preview() {        // TODO 自动生成的方法存根        camera=Camera.open();//打开相机,获得相机对象        try        {            Camera.Parameters param=camera.getParameters();//获得支持的一些参数            //获得支持的预览大小,设置不支持的大小会出现异常            List<Camera.Size> preSizes=param.getSupportedPreviewSizes();            for(Camera.Size s:preSizes){                Log.i("SupportedPreviewSize:", s.height+"X"+s.width);            }//可以在日志中看到支持的预览大小,从而根据数值设置正确的预览大小            //设置支持的照片大小,设置不支持的大小会出现异常            List<Camera.Size> picSizes=param.getSupportedPictureSizes();            for(Camera.Size s:picSizes){                Log.i("SupportedPictureSize:", s.height+"X"+s.width);            }//可以在日志中看到支持的预览大小            param.setPreviewSize(320, 240);  //设置预览大小            param.setPictureFormat(PixelFormat.JPEG);//设置照片格式            param.setPictureSize(800, 480);//设置照片大小            param.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);            camera.setParameters(param);//参数传递给相机对象            camera.setPreviewDisplay(holder);//相机预览显示在SurfaceView上            camera.startPreview();        }        catch(IOException e)        {            e.printStackTrace();        }    }    protected void takePicture() {        // TODO 自动生成的方法存根        if(camera!=null)        camera.takePicture(null, null, jpeg);    }    //jpg格式的照片处理接口,作为一个参数传递给takePicture()函数    PictureCallback jpeg = new PictureCallback() {        //第一个参数是照片的字节数组数据,强转为位图类型        @Override        public void onPictureTaken(byte[] data, Camera camera) {            // TODO 自动生成的方法存根            Bitmap bm=BitmapFactory.decodeByteArray(data, 0, data.length);            String path="/sdcard/camera.jpg";            File file=new File(path);            try            {                FileOutputStream fos=new FileOutputStream(file);                BufferedOutputStream bos=new BufferedOutputStream(fos);//流对象                bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);//保存图片                bos.flush();                bos.close();//关闭流                iv.setImageBitmap(bm);//显示照片                camera.stopPreview();                camera.release();            }            catch(Exception e){                e.printStackTrace();            }        }    };    //SurfaceHolder的3个回调接口    public void surfaceChanged(SurfaceHolder arg0,int arg1,int arg2,int arg3)    {        if(camera!=null){        camera.release();        }    }    public void surfaceCreated(SurfaceHolder arg0)    {    }    public void surfaceDestroyed(SurfaceHolder arg0)    {        if(camera!=null){            camera.release();            camera=null;        }    }}

特别注意:Activity要实现SurfaceHolder.callback的回调接口。
另外,照片预览的大小设置必须设置正确,不同机型可能会有差异,在日志中查看正确值。
自动对焦功能,可在preview后自动对焦,并拍照。但此处运用的效果不是很好。

0 0
原创粉丝点击