使用摄像头拍摄照片

来源:互联网 发布:渡口网络破产 编辑:程序博客网 时间:2024/05/17 00:15

一、android中相机开发的两种方式

Android系统提供了两种使用手机相机资源实现拍摄功能的方法,一种是直接通过Intent调用系统相机组件,这种方法快速方便,适用于直接获得照片的场景,如上传相册,微博、朋友圈发照片等。另一种是使用相机API来定制自定义相机,这种方法适用于需要定制相机界面或者开发特殊相机功能的场景,如需要对照片做裁剪、滤镜处理,添加贴纸,表情,地点标签等。

使用intent拍摄照片

 startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE),TAKE_PICTURE); 
  1. 启动手机的相机应用拍摄照片,拍摄完成后,在onActivityResult方法中就可以通过Intent拿到照片。默认情况下拍摄的照片将作为一个缩略图返回.
  2. 要获得完整图像,必须制定一个用于存储改图像的目标文件,文件路径定义为URI,在启动Intent时使用MediaStore.EXTRA_OUTPUT extra传入URI:
File file = new File(Environment.getExternalStorageDirectory(),"test.jpg");Uri outputFileUri = Uri.fromFile(file);Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT,outputFileUri);startActivityForResult(intent,TAKE_PICTURE);

然后,相机在拍摄完图像后就会被保存到制定位置,onActivityResult中不会返回缩略图,接收到的intent的数据将会是null。

protected void onActivityResult(int requestCode,int resultCode,Intent data){    if(requestCode == TAKE_PICTURE){    //检查结果是否包含缩略图        if(){        Bitmap thumnail = data.getParcelableExtra("data");        imageView.setImageBitmap(thumbnail);        }else{            //如果没有缩略图,则说明图像存储在目标URI中            //resize the full image to fit in out image view            int width = imageView.getWidth();            int height = imageView.getHeight();            BitmapFactory.Options facotryOptions = new BitmapFactory.Options();            facotryOptons.inJustDecodebounds = true;            BitmapFacotry.decodeFile(outputFileUri.getPath(),factoryOptions);            int imageWidth = facotryOptions.outWidth;            int imageHeight = facotryOptions.outHeight;            //确定将图像缩小多少            int scaleFactor = Math.min(imageWidht/widht,imageHeight/height);            //将图像文件解码为imageView的大小            factoryOptions.inJustDecodebounds = false;            factoryOptions.inSampleSize = scaleFactor;            factoryOptions.inPurgeable = true;            Bitmap bitmap = BitmapFactory.decodeFile(outputFileUri.getPath(),factoryOptions);            imageView.setIamgeBitmap(bitmap);        }    }

二、直接控制相机

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

直接调用相机,使用到的权限。
调用相机:

Camera camera = Camera.open();

使用完,要记得释放它:

camera.release();

修改相机设置,需要使用set方法来修改Parameters参数。

Camera.Parameters parameters = camera.getParameters();
camera.setParameters(parameters);
  • [get/set]SceneMode场景模式,每个场景模式都为特定的场景优化了相机参数的设置
  • [get/set]FlashMode 设置闪光灯模式
  • [get/set]WhiteBalance 可以使用getSupportedWhiteBalance()来确认有哪些设置可用。
  • [get/set]AutoWhiteBalanceLock 启用自动白平衡锁,可以使用isAutoWhiteBalanceLockSupported()确认设备是否支持这种功能。
  • [get/set]ColorEffect 特殊颜色效果
  • [get/set]FocuMode 相机对焦方式getSupportedFocusModes()找出可以使用的模式。

为了能在自动对焦操作完成后做些操作,需要使用autofocus()启动自动对焦,传入AutoFocusCallBack实现。

Camera.Parameters parameters = camera.getParameters();if(parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)){    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);    camera.autoFocus(new AutoFocusCallback());}

获取是否支持、定义对焦区域:

camera.getMaxNumFocusAreas();camera.setFocusAreas();

获取是否支持、定义测光区域:

camera.getMaxNumMeteringAreas();camera.setMeteringAreas();

使用相机预览

不先显示一个预览,是无法使用camera对象拍照的。
相机预览的是使用SurfaceHolder显示的,必须在UI层次包含一个Surface View。需要实现一个SurfaceHolder.Callback。
示例代码:

public class CameraActivity extends Activity implements SurfaceHolder.Callback{    private static final String TAG = "CameraActivity";    private Camera camera;    @Override    public void onCreate(Bundle savedInstanceState){        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        SurfaceView surface = (SurfaceView)findViewById(R.id.surfaceView);        SurfaceHolder holder = surface.getHolder();        holder.addCallback(this);        holder.setType(surfaceHolder.SURFACE_TYPE_BUFFERS);        holder.setFixedSize(400,300);    }    public void serfaceCreated(SurfaceHolder holder){        try{            camera.setPreviewDisplay(holder);            camera.startPreview();            //todo 必要时在预览上进行绘制        }catch(IOException e){        }    }    public void surfaceChanged(SurfaceHolder holder,int format,int width,int heigh){    }    public void surffaceDestoryed(SurfaceHolder holder){        camera.stopPreview();    }    @Override    protected void onPause(){        super.onPause();        camera.release();    }    @Override    protected void onResume(){        super.onResume();        camera = camera.open();    }}

还可以分配一个PreviewCallback实现,使其在每个预览帧中出发,一遍可以实时操纵或者分析每一个预览帧。

camera.setPreviewCallback(New PreviewCallback(){    public void onPreviewFrame(byte[] data,Camera  camera){        int quality = 60;        Size previewSize = camera.getParameters().getPreviewSize();        YuvImage image = new YuvImage(data,ImageFormat.Nv21,previewSize.width,previewSize.height,null);        ByteArrayOutputStream stream = new ByteArrayOutputStream();        image.compressToJpeg(new Rect(0,0,previewSize.width,previewSize,height),quality,stream);        //todo 对预览图像执行一些操作。    }});

拍摄照片

调用Camera对象的takePicture,并传入一个ShutterCallback和两个PictureCallback实现(一个用于RAW图像,一个用于JPEG编码的图像)。
示例代码:

private void takePicture(){    camera.takePicture(shutterCallback,rawCallback,jpegCallback);}ShutterCallback shutterCallback = new ShutterCallback(){    public void onShutter(){    //todo 快门关闭时执行一些操作    }};PictureCallback rawCallback = new PictureCallback(){    public ovid onPictureTaken(byte[] data,Camera camera){    //todo 对图像的原始数据做一些处理    }};PictureCallback jpgCallback = new PictureCallback(){    public ovid onPictureTaken(byte[] data,Camera camera){    //todo 对图像的原始数据做一些处理    }};

JPEG EXIF 图像详细信息

通过将目标JPEG图像的完整文件名传入ExifInterface构造函数来创建一个新的的实例。
EXIF数据用于为照片存储各种不同的元数据,包括拍摄日期和时间、相机设置、图像设置、以及图像描述和位置。

ExifInterface exif = new ExifInterface(file.getCanonicalPath);

参考文档:
android高级编程第3版
博客:android相机开发的那些坑

0 0
原创粉丝点击