使用摄像头拍摄照片

一、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相机开发的那些坑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值