
这些天. 我写了自己的相机的演示. 支持连续的照片和相机切换. 因为我从未接触过相关编程. 这也是一个学习过程,在此处进行记录,同时共享,并附加源代码和项目.
效果如下:
左上角的开关切换相机,右侧的快照按钮拍摄照片.
Android要拍照,您需要调用相机类android.hardware.Camera.

相反,需要预览. 您需要使用android.view.SurfaceView来显示每帧的预览图像.
实现自己的摄像机定义的一般过程是:
1. 使用addCallback设置SurfaceView的Callback接口对象,以实现三种回调方法: surfaceCreated,surfaceChanged,surfaceDestroyed.
在surfaceCreated中打开相机,获取Camera对象android 切换,并将其设置为在surfaceview上预览;
在surfaceChanged中设置相机参数;

将照相机释放在表面上. 否则,其他应用程序退出后将无法调用相机,包括系统相机.
2. 单击照片按钮时. 调用Camera对象的takePicture方法,该对象的第三个参数是PictureCallback接口对象,并且onPictureTaken回调方法参数中有一个字节数组. 存储捕获的图片数据,并将其保存在方法中的本地.
通过这种方式,可以准备具有基本预览和预览功能的自定义摄像机. 但这还不够. 因为会有各种各样的问题.
这是最大的头痛.
首先,您需要了解三个纵横比: 相机分辨率(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的宽度和高度. 在确保曲面视图的长宽比保持不变的情况下(例如,确保全屏预览). 分别找到满足要求的PictureSize和PreviewSize. 假设找不到它,则返回默认纵横比(我将其设置为4: 3)的PictureSize和PreviewSize. 同时,为确保三个长宽比一致android 切换,还应重置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;
}
}
}

因为不同的手机返回的支持分辨率不同(我手中的Lenovo从小到大排序,而nexus 4从大到小排序),所以我需要首先将列表从小到大统一. 这样,该方法可以返回满足条件长宽比的最大分辨率,从而可以确保照片的清晰度.
解决方案是监视手机的方向. 当检测到方向变化时,再次设置Camera.Parameters对象的setRotation方法(通过调用getParameters()方法获得Camera对象)以设置成像方向.
监视方法是. 在实现OrientationEventListener接口的Activity中设置一个对象. 并调用其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);
}
}
}
设置旋转角度的公式
由Google官方提供.
因为我将相机的“活动”方向设置为ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,即横向模式,所以我没有遇到此问题.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/ruanjian/article-174173-1.html
马云就是废话太多