使用摄像头拍摄照片
来源:互联网 发布:渡口网络破产 编辑:程序博客网 时间:2024/05/17 00:15
一、android中相机开发的两种方式
Android系统提供了两种使用手机相机资源实现拍摄功能的方法,一种是直接通过Intent调用系统相机组件,这种方法快速方便,适用于直接获得照片的场景,如上传相册,微博、朋友圈发照片等。另一种是使用相机API来定制自定义相机,这种方法适用于需要定制相机界面或者开发特殊相机功能的场景,如需要对照片做裁剪、滤镜处理,添加贴纸,表情,地点标签等。
使用intent拍摄照片
startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE),TAKE_PICTURE);
- 启动手机的相机应用拍摄照片,拍摄完成后,在onActivityResult方法中就可以通过Intent拿到照片。默认情况下拍摄的照片将作为一个缩略图返回.
- 要获得完整图像,必须制定一个用于存储改图像的目标文件,文件路径定义为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相机开发的那些坑
- 使用摄像头拍摄照片
- Android 获取摄像头拍摄的照片
- H5调用本地摄像头拍摄照片
- J2ME 摄像头拍摄照片操作集合(原创)
- 使用手机拍摄悬浮照片的教程
- Android 系列 5.5使用意图拍摄照片
- win8 metro 调用摄像头拍摄照片并将照片保存在相应的位置
- iOS 拍摄照片,使用视听媒体框架AVFoundation实现照片拍摄 —— HERO博客
- LG的Gm205黑色带有一个200万像素的摄像头拍摄照片和视频
- 如何使用现有的相机应用程序拍摄的照片
- 拍摄照片添加文字
- 如何拍摄一组照片
- 拍摄照片和视频
- opencv 拍摄照片
- opencv连接摄像头,拍摄
- 使用已有的摄像头程序获取照片
- 照片按拍摄日期管理工具
- camera拍摄照片,保存显示
- NYOJ 1099 Lan Xiang's Square(给出四点判断是否能构成正方形)
- 微信 安卓 无法支持keydown keypress keyup
- 一号互联新研发的“办公室节能应用”来袭,WiFi智能的新方案
- android 获取手机包名显示
- AangularJs动态时间例子
- 使用摄像头拍摄照片
- Facebook产品总监NB产品14个必考题
- HashMap与ConcurrentHashMap的区别
- 静态编译
- spring AOP个人理解
- 为啥UI设计师要学习产品思维?
- 文章标题
- Yii 2.0邮箱类简单应用
- <DFS> POJ 1321 棋盘问题