~转载请注明http://blog.csdn.net/u013015161/article/details/46921257

介绍

这几天。写了一个自己定义照相机的demo。支持连续拍照和摄像头切换。因为自己曾经没接触过相关的编程。也算是一个学习的过程,在这里做一下记录,同一时候也分享出来,并附上源代码和project。

效果如图:



左上角switch切换摄像头,右边snapbutton进行拍照。

一般流程

Android进行拍照,须要调用摄像头类android.hardware.Camera。

而要进行预览。则须要用android.view.SurfaceView对每一帧的预览图进行显示。

实现自己定义相机一般流程为:

1、用addCallback给SurfaceView设置Callback接口对象,实现当中三个回调方法:surfaceCreated、surfaceChanged、surfaceDestroyed。

在surfaceCreated中打开摄像头,获得Camera对象,并设置其在surfaceview上预览;

在surfaceChanged中设置摄像头的參数;

在surfaceDestroyed释放摄像头。否则会导致退出之后其它应用无法调用摄像头,包含系统相机。

2、点击拍照button时。调用Camera对象的takePicture方法,其第三个參数为PictureCallback接口对象,当中的onPictureTaken回调方法參数中有一个byte数组。存储了拍摄到的图片数据,在方法中保存到本地就可以。

这样,一个基本可用、带预览的自己定义相机就做好了。但这样还远远不够。因为会出现各种各样的问题。

主要问题

预览变形

这个是最头疼的问题。

首先要知道3个宽高比:摄像头分辨率(PictureSize)宽高比、预览分辨率(PreviewSize)宽高比以及用作预览的SurfaceView的宽高比。

假设要让预览不变形,这三个宽高比须要保持一致。这样的一致性的保持在设置摄像头參数时进行。代码例如以下:

public void setCameraAndDisplay(int width, int height)
{
Camera.Parameters parameters = camera.getParameters();
/*获取摄像头支持的PictureSize列表*/
List<Camera.Size> pictureSizeList = parameters.getSupportedPictureSizes();
/*从列表中选取合适的分辨率*/
Size picSize = CameraUtils.getProperSize(pictureSizeList, ((float)width)/height);
if(null != picSize)
{
parameters.setPictureSize(picSize.width, picSize.height);
}
else
{
picSize = parameters.getPictureSize();
}
/*获取摄像头支持的PreviewSize列表*/
List<Camera.Size> previewSizeList = parameters.getSupportedPreviewSizes();
Size preSize = CameraUtils.getProperSize(previewSizeList, ((float)width)/height);
if(null != preSize)
{Log.v("TestCameraActivityTag", preSize.width + "," + preSize.height);
parameters.setPreviewSize(preSize.width, preSize.height);
} /*依据选出的PictureSize又一次设置SurfaceView大小*/
float w = picSize.width;
float h = picSize.height;
surfaceView.setLayoutParams(new RelativeLayout.LayoutParams( (int)(height*(w/h)), height)); parameters.setJpegQuality(100); // 设置照片质量
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
{
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} camera.cancelAutoFocus();//仅仅有加上了这一句,才会自己主动对焦。
camera.setDisplayOrientation(0);
camera.setParameters(parameters);
}

方法里传进去的參数为SurfaceView如今的宽高。在保证surfaceview宽高比不变的情况下(比方为了保证全屏预览)。分别去寻找符合条件的PictureSize和PreviewSize。假设找不到,就返回默认宽高比(我设置为4:3)的PictureSize和PreviewSize, 同一时候为保证3个宽高比一致,surfaceView的宽高比也要重设。

提供寻找合适的PictureSize和PreviewSize方法的类例如以下:

public class CameraUtils {

    public static Size getProperSize(List<Size> sizeList, float displayRatio)
{
//先对传进来的size列表进行排序
Collections.sort(sizeList, new SizeComparator()); Size result = null;
for(Size size: sizeList)
{
float curRatio = ((float)size.width) / size.height;
if(curRatio - displayRatio == 0)
{
result = size;
}
}
if(null == result)
{
for(Size size: sizeList)
{
float curRatio = ((float)size.width) / size.height;
if(curRatio == 3f/4)
{
result = size;
}
}
}
return result;
} static class SizeComparator implements Comparator<Size>
{ @Override
public int compare(Size lhs, Size rhs) {
// TODO Auto-generated method stub
Size size1 = lhs;
Size size2 = rhs;
if(size1.width < size2.width
|| size1.width == size2.width && size1.height < size2.height)
{
return -1;
}
else if(!(size1.width == size2.width && size1.height == size2.height))
{
return 1;
}
return 0;
} }
}

因为不同的手机返回的支持分辨率的排序不一样(我手中一款联想从小到大排序,而还有一部nexus 4从大到小排序),所以须要先对列表统一进行从小到大排序。这样,方法返回的就是符合条件宽高比的最大分辨率,能够保证照片的清晰度。

照片方向错误

解决方法是监听手机方向的改变。监听到方向发生变化,就调用Camera.Parameters 对象(Camera对象调用getParameters()方法获得)的setRotation方法又一次设置成像方向。

监听的方法是。在Activity设置一个实现了OrientationEventListener接口 的对象。并调用其enable()方法激活。

IOrientationEventListener iOriListener;
... ...
iOriListener.enalbe();

实现OrientationEventListener接口的类:

public class IOrientationEventListener extends OrientationEventListener{

        public IOrientationEventListener(Context context) {
super(context);
// TODO Auto-generated constructor stub
} @Override
public void onOrientationChanged(int orientation) {
// TODO Auto-generated method stub
if(ORIENTATION_UNKNOWN == orientation)
{
return;
}
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(camera_id, info);
orientation = (orientation + 45) / 90 * 90;
int rotation = 0;
if(info.facing == CameraInfo.CAMERA_FACING_FRONT)
{
rotation = (info.orientation - orientation + 360) % 360;
}
else
{
rotation = (info.orientation + orientation) % 360;
}
if(null != camera)
{
Camera.Parameters parameters = camera.getParameters();
parameters.setRotation(rotation);
camera.setParameters(parameters);
} } }

当中设置rotation的公式由google官方提供。

预览方向错误

因为我设置了相机的Activity的方向为ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,即横屏模式,所以没有遇到这个问题。

只是上一篇我转载的博文里,有提到相关问题的解决。相关代码摘录出来。供大家參考。

下面代码放在surfaceview的callback中surfaceChanged方法里执行:

if(this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)

{

//假设是竖屏

parameters.set(“orientation”, “portrait”);

//在2.2以上能够使用

//camera.setDisplayOrientation(90);

}

else

{

parameters.set(“orientation”, “landscape”);

//在2.2以上能够使用

//camera.setDisplayOrientation(0);

}

连续对焦

通过连续对焦,能够拍出清晰的照片。代码在上面的代码段里出现过

/*先推断是否支持,否则可能报错*/
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
{
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
camera.cancelAutoFocus();//仅仅有加上了这一句,才会自己主动对焦。

照相机Activity的代码就不全贴了,更详细的能够參考demoproject。

project下载

点此下载自己定义相机demoproject

如过上面那句话点击无效 ,说明资源还在审核。。。

能够去百度云盘下载:

http://pan.baidu.com/s/1c077rDA

因为本人手中測试机型仅仅有两台,执行了上述demo的朋友方便的话能够 告知下执行效果。

【Android】自己定义相机的实现(支持连续拍照、前后摄像头切换、连续对焦)的更多相关文章

  1. Android 手把手带你玩转自己定义相机

    本文已授权微信公众号<鸿洋>原创首发,转载请务必注明出处. 概述 相机差点儿是每一个APP都要用到的功能,万一老板让你定制相机方不方?反正我是有点方. 关于相机的两天奋斗总结免费送给你. ...

  2. Android调用系统相机、自己定义相机、处理大图片

    Android调用系统相机和自己定义相机实例 本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,而且因为涉及到要把拍到的照片显示出来,该样例也会涉及到Android载入大图片时候的处 ...

  3. android开发——自己定义相机(Camera)开发总结

    近期这段时间我一直在开发自己定义相机.谷歌了些网上的demo.发现有非常多各种各样的问题.终于还是从API的camera类開始学习,进行改进. 以下对之前的实现进行一些总结. 官方camera API ...

  4. AIDL —— Android接口定义语言

    AIDL:Android Interface Definition Language,即Android接口定义语言,是Android进程间通信比较常用的一种方式.翻译一下,就是为了让某个Service ...

  5. ANDROID自己定义视图——onLayout源代码 流程 思路具体解释

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 简单介绍: 在自己定义view的时候.事实上非常easy.仅仅须要知道3步骤: 1.測量- ...

  6. Android自己定义控件系列二:自己定义开关button(一)

    这一次我们将会实现一个完整纯粹的自己定义控件,而不是像之前的组合控件一样.拿系统的控件来实现.计划分为三部分:自己定义控件的基本部分,自己定义控件的触摸事件的处理和自己定义控件的自己定义属性: 以下就 ...

  7. Android调用系统相机、自定义相机、处理大图片

    Android调用系统相机和自定义相机实例 本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显示出来,该例子也会涉及到Android加载大图片时候的处理 ...

  8. 【Java/Android性能优 4】PreloadDataCache支持预取的数据缓存,使用简单,支持多种缓存算法,支持不同网络类型,扩展性强

    本文转自:http://www.trinea.cn/android/preloaddatacache/ 本文主要介绍一个支持自动向前或向后获取新数据的缓存的使用及功能.Android图片内存缓存可见I ...

  9. Android 自己定义控件实现刮刮卡效果 真的就仅仅是刮刮卡么

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40162163 , 本文出自:[张鸿洋的博客] 非常久以前也过一个html5的刮刮 ...

随机推荐

  1. ExecuteNonQuery和ExecuteScalar的区别

    ExecuteNonQuery   针对 Connection 执行 SQL 语句并返回受影响的行数. 返回值 受影响的行数. 备注 您可以使用 ExecuteNonQuery 来执行目录操作(例如查 ...

  2. MyBatis增删改查模板

    1. 首先,和Spring整合一下 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=& ...

  3. git error Another git process seems to be running in this repository

    How to fix error Another git process seems to be running in this repository When you use Git, you se ...

  4. 第二百四十九节,Bootstrap附加导航插件

    第二百四十九节,Bootstrap附加导航插件 学习要点: 1.附加导航插件 本节课我们主要学习一下 Bootstrap 中的附加导航插件 一.附加导航 注意:此插件要使用 bootstrap3.0. ...

  5. a标签点击后,给a标签添加样式

    window.onload=function(){ var a = document.getElementById("cate").getElementsByTagName(&qu ...

  6. 学习《深入理解C#》—— 数据类型、排序和过滤 (第一章1.1---1.2)

    引言 在开始看这本书之前看过一些技术博客,填补自己对于一些知识点的不足.无意中发现了<深入理解C#>这本书,本书主要探讨C# 2.C# 3和C# 4的细节与特性,所以做了一下阅读笔记,欢迎 ...

  7. leetcode -- Maximal Rectangle TODO O(N)

    Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and ...

  8. hdu1024(最大m串子序列)

    m的范围没给,很坑爹 Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ( ...

  9. Jenkins publish over ssh 上传 文件夹 配置方式

    需要把编译后 目录下的 lib文件夹下的jar包都上传到服务器上 1.配置 2.完成截图 3.服务器截图 注意:  真实脚本 建议写 全路径 注意:多条命令时  添加 英文分号

  10. 【BZOJ1005/1211】[HNOI2008]明明的烦恼/[HNOI2004]树的计数 Prufer序列+高精度

    [BZOJ1005][HNOI2008]明明的烦恼 Description 自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可 ...