资源描述
在Android中实现视频抓拍与照片自由裁剪的编程方法
在Android操作系统下可通过编程实现对视频图像进行抓拍并对图片的裁剪与上传功能。简单的实现方法采用Android 自带有关于照片的自由裁剪,非常适用及视频抓拍的接口功能。
一、视频抓拍
1、基本类
Android 框架通过 Camera API 或者 camer Intent 的方式,支持 捕捉图像和视频 。相关的大类主要有以下几个:
(1) Camera 摄像时候必须调用到的类;
(2)SurfaceView 提供摄像头预览。
(3)MediaRecorder 录像时候用到的类;
(4)Intent 如果不通过 Camera 对象来操控摄像头,那么用两个intent 动作 MediaStore.ACTION_IMAGE_CAPTURE or MediaStore.ACTION_VIDEO_CAPTURE 也能够实现摄影和录像。
o MediaStore.ACTION_IMAGE_CAPTURE —— 向内置摄像头程序请求图像的意图活动类型。
o MediaStore.ACTION_VIDEO_CAPTURE —— 向内置摄像头程序请求视频的意图活动类型。
2、 Manifest 声明
在使用Camera API前,必须做出使用 Camera 硬件的声明。主要有下面 点:
(1) Camera 允许:(注意,如果是通过intent 意图来操控的,则不需要下面声明)
<uses-permission android:name="android.permission.CAMERA" />
(2)Camera 特征,比如说名字
<uses-feature android:name="android.hardware.camera" />
(3)如果你要在SD卡中保存照片和视频,那么就得开启SD卡权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
(4)录音权限
<uses-permission android:name="android.permission.RECORD_AUDIO" />
(5)如果希望在照片中插入GPS当地信息,还得开启GPS
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
3、使用方法
使用摄像头的方法有两种:
一种是编写代码比较少的,快速使用摄像头的意图Intent 方法;
另外一种就是 自动外观的摄像头用户界面,要求编写更多的代码。
4、使用Intent 快速应用摄像头:使用默认配置拍摄并保存
/*
* 前置摄像头抓拍
* */
/*--------------------------摄像头程序-begin--------------------------------*/
camera_catch.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
Intent capture_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//创建一个文件来保存图片
File out = new File(capture_path);
//转换为URI地址
Uri uri = Uri.fromFile(out);
//设置图片保存
capture_intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
//图片质量为高
capture_intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY,1);
//启动拍照意图
startActivityForResult(capture_intent, CAPTURE_REQUEST_CODE);
}
});
}
/*
* 拍照,并保存数据,通过重写onActivityResult 方法去返回处理结果给主main:RFID
* */
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data)
{
//重写父类方法
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == CAPTURE_REQUEST_CODE) //判断是摄像头请求
{
if(resultCode == RESULT_OK)
{
//拍照图像显示
Bitmap capture_bm = (Bitmap) data.getExtras().get("data");
p1_image.setImageBitmap(capture_bm);
File captureFile = new File(capture_path);
try {
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(captureFile));
capture_press(Bitmap.CompressFormat.JPEG, 100, bos);
bos.flush();
bos.close();
} catch (Exception e) {
// TODO: handle exception
Toast.makeText(this, "没有找到照片文件", 1000).show();
}
}
}
}
/*--------------------------摄像头程序-end--------------------------------*/
5、自定义摄像头:预览、聚焦后才拍摄
主要步骤如下:
(1)调用 Camera 的 open() 方法打开相机,该方法默认打开后置摄像头,如果打开前置摄像头,就必须获得前置摄像头的ID,然后传入该ID ; (一般后置ID 是0 ,前置是1 ,Android 2.3 (API Level 9) 以上版本允许利用Camera.getNumberOfCameras()方法来检查设备可用摄像头的数量)
可用Camera.open()方法来访问主摄像头,并确保捕获全部的异常,示例代码如下:
/** 安全获取Camera对象实例的方法*/
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(int ID); // 试图获取Camera实例,ID 指的是摄像头ID
}
catch (Exception e){
// 摄像头不可用(正被占用或不存在)
}
return c; // 不可用则返回null
}
注意,每次使用 Camera open() 时都要检查异常,如果摄像头被占用或者不存在的话,未检查异常将会导致应用程序被系统强行关闭。
(2)调用 Camera 的getParameters() 方法获取拍照 参数,该方法返回一个Camera.Parameters 对象;
调用Camera.Parameters 对象方法设置拍照参数;可用Camera.getCameraInfo()来确定摄像头朝前还是朝后以及图像的方向。
(3)调用Camera的 takePciture()方法 进行拍照。
(4)结束程序时,调用release() 来释放资源。
camera = Camera.open(1); //打开前置摄像头
//设置图片格式
if(camera != null)
{
try {
//设置摄像头参数
Camera.Parameters parameters = camera.getParameters();
//设置图片格式
parameters.setPictureFormat(ImageFormat.JPEG);
//设置图片质量
parameters.set("jpeg-quality", 100);
} catch (Exception e) {
e.printStackTrace();// TODO: handle exception
}
}
二、图片自由裁剪
关键代码如下:
public void imageCut(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
//开启裁剪功能
intent.putExtra("crop", "true");
//设定宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
//设定裁剪图片宽高
intent.putExtra("outputX", 100);
intent.putExtra("outputY", 100);
//要求返回数据
intent.putExtra("return-data", true);
startActivityForResult(intent, 100);
}
返回数据后直接在onActivityResult 里对返回的图片数据进行显示就行了,这里由于剪切后的图片较小,个人觉得应该不用考虑OOM的问题,问题是,在调用自带的裁剪功能的时候,由于没看源码,所以不知道在调整裁剪框的时候,显示的那副图片有没有进行压缩,如果没有进行压缩,那么当图片很大的时候,加载起来就很容易出现OOM了,明显对此由于是调用官方的API,我没有方法去解决它。唯一的办法就是不用它,而是自己去写一个,就可以避免这个问题。利用如下的代码进行压缩,很好地避免OOM问题。
/*
* 压缩图片,返回的是压缩后的照片
*/
public static Bitmap revitionImage(String path,int size){
Bitmap bitmap = null;
try {
//先用图片路径打开图片文件,缓冲到一个缓存输入流中
BufferedInputStream in = new BufferedInputStream(new FileInputStream(
new File(path)));
//用参数代表变量来记录当前照片的信息,比如图片大小
BitmapFactory.Options options = new BitmapFactory.Options();
//把inJustDecodeBounds设置为true,则完全不用分配内存就可以得到给位图文件bitmap的信息,
//如此得到大小后,就可以对其进行7压缩,然后在内存中生成一个更小的bitmap,节省了内存
options.inJustDecodeBounds = true;
//译码位图文件,只为了得到原图的信息
BitmapFactory.decodeStream(in
,null,options);
//记得关闭流
in.close();
int i = 0;
while(true){
//右移i位是因为下面的pow取一半了,新生成的图片是原来的二分之一
if (((options.outWidth >> i)<=size) && ((options.outHeight >> i) <=size)) {
//这时候应取得照片了
in = new BufferedInputStream(new FileInputStream(new File(path)));
//pow是次方方法,2的i次方,inSampleSize图片均分取样值,例如
//inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels.
options.inSampleSize = (int)Math.pow(2.0, i);
//这时候的图片已经符合我们设定的256大小了,所以要在设置false,允许输出,创建图片
//真正地生成一个有像素的,经过缩放的bitmap
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeStream(in,null,options);//获得n分之一原图,小于256*256
break;
}else {
i++;
}
}
} catch (IOException e) {
Log.i(TAG, "压缩图片出错"+e.toString());
}
return bitmap;
}
展开阅读全文