
在过去的几天中,我编写了一个自定义相机的演示,该相机支持连续拍照和相机切换. 由于我以前没有接触过相关编程,所以这是一个学习过程. 在此处记录并与源代码和工程共享.
效果如下:
左上角的开关切换相机,右侧的快照按钮拍摄照片.
Android需要调用相机类android.hardware.Camera进行拍照. 要进行预览,您需要使用android.view.SurfaceView来显示每帧的预览图像.
实现自定义相机的一般过程是:

1. 使用addCallback设置SurfaceView的Callback接口对象,并实现三种回调方法: surfaceCreated,surfaceChanged,surfaceDestroyed.
在surfaceCreated中打开相机,获取Camera对象,并将其设置为在surfaceview上预览;
在surfaceChanged中设置相机参数;
在销毁表面后释放摄像机,否则将导致其他应用程序退出后无法调用摄像机,包括系统摄像机.
2. 单击相机按钮时,将调用相机对象的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. 同时,为确保三个长宽比一致,还应该重置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从大到小排序),因此您需要首先统一列表Sort. 这样,该方法可以返回满足条件长宽比的最大分辨率android 切换,从而可以确保照片的清晰度.

解决方案是监视手机方向的变化. 当检测到方向改变时,使用Camera.Parameters对象的setRotation方法(通过调用getParameters()方法获得Camera对象)来重置成像方向.
监视方法是在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);
}
}
}
设置轮换的公式由Google官员提供.

由于我将相机的“活动”方向设置为ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,这表示横向模式,所以我没有遇到此问题.
但是android 切换,在我转载的上一篇博客文章中,我提到了相关问题的解决方案. 提取相关代码供您参考. 在surfaceview的回调中的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();//只有加上了这一句,才会自动对焦。
“相机活动”的代码未完全发布. 有关更多详细信息,请参阅演示项目.
点击此处下载自定义相机演示项目
如果上一个句子单击无效,则该资源仍在审核中. . . 您可以去百度云盘下载:
.
由于我手中只有两个测试模型,运行上述演示的朋友可以告诉操作效果是否方便.
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-252596-1.html
嫖娼
你就不能说让国产手机淘汰美国苹果吗
你以为是小学的数学题