将camera肯定是要有预览界面来配合着才有激情,不然无图无真相。那就讲的没有太大的激情。
我们对camera的使用一般是在app里面有用到设置获取图片的时候提供一个拍照功能,一般是跳转到系统的拍照界面使用camera来获取图片;有的app有需求就跳转到自己的拍照界面。我们知道系统的应用其实也是个app,无论是跳转到系统拍照界面还是自己的拍照界面其实都是一个preview,然后再“截屏”生成一个图片。我下面讲一些关于camera的基础和preview的结合使用。
首先要获取camera的属性:Camera.Parameters parameters = camera.getParameters();
camera的基本属性设置:
(1)设置预览大小 :
parameters.setPreviewSize(“宽”, “高”);
一般设置的预览大小就是手机屏幕的宽高,那么就要获取屏幕的宽高,然后再经过稍微的处理:
WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
宽:display.getWidth() 高:display.getHeight()
由于下面的介绍都会用到一个系统的实体Point,所以我这里把宽高设置到这个实体里面,然后方便使用,然后就得到下面的代码:
WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
//获取屏幕的宽高(像素值)设置到一个实体(point)里面
Point screenResolution = new Point(display.getWidth(), display.getHeight());
然后再根据屏幕的宽高做优化处理:
/*根据相机的参数和手机屏幕参数来重新设置相机的*/
public Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {
String previewSizeValueString = parameters.get("preview-size-values");
if (previewSizeValueString == null) {
previewSizeValueString = parameters.get("preview-size-value");
}
Point cameraResolution = null;
if (previewSizeValueString != null) {
cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);
}
if (cameraResolution == null) {
//没有找到最优的预览效果,那么至少也要确保相机分辨率是8的倍数(我也不知道为什么),下面的操作就是防备屏幕不是8的倍数,如果
//是8的倍数,就会在上面的寻找最优size的时候会找到的
cameraResolution = new Point(
(screenResolution.x >> 3) << 3,
(screenResolution.y >> 3) << 3);
}
return cameraResolution;
}
/*根据预览大小和手机屏幕大小来设一个比较完美的预览效果*/
public Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {
int bestX = 0;
int bestY = 0;
int diff = Integer.MAX_VALUE;//差值
for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {
previewSize = previewSize.trim();
int dimPosition = previewSize.indexOf('x');
if (dimPosition < 0) {
//这是一个很差的预览大小
continue;
}
int newX;
int newY;
try {
newX = Integer.parseInt(previewSize.substring(0, dimPosition));
newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
} catch (NumberFormatException nfe) {
//字符串转换异常,这是自己写的tryCatch,是为了安全起见
continue;
}
int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
if (newDiff == 0) {
bestX = newX;
bestY = newY;
break;
} else if (newDiff < diff) {
bestX = newX;
bestY = newY;
diff = newDiff;
}
}
if (bestY > 0 && bestX > 0) {
return new Point(bestX, bestY);
}
return null;
}
最后把优化处理之后的point的数据设置个camera的parameters:
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);//设置相机的预览size
(2)设置闪光灯:
/*设置闪光灯,本来是不用设置的,应该是直接获取,但是根据三星建议说防止黑客攻击,最好设置一下*/
private void setFlash(Camera.Parameters parameters) {
if (Build.MODEL.contains("Behold II") && Integer.parseInt(Build.VERSION.SDK) == 3) {
parameters.set("flash-value", 1);
} else {
parameters.set("flash-value", 2);
}
parameters.set("flash-mode", "off");
}
(3)设置缩放:
一般使用camera进行拍照和录制视频的时候都要支持手势识别进行缩放,原理就是把手势缩放的xy值然后进行算法转换然后动态的设置到camera的parameter上。
/*设置缩放*/
private void setZoom(Camera.Parameters parameters) {
String zoomSupportString = parameters.get("zoom-supported");
if (zoomSupportString != null && !Boolean.parseBoolean(zoomSupportString)) {
return;
}
int tenDesiredZoom = TEN_DESIRED_ZOOM;//TEN_DESIRED_ZOOM = 27
String maxZoomString = parameters.get("max-zoom");
if (maxZoomString != null) {
try {
int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));
if (tenDesiredZoom > tenMaxZoom) {
tenDesiredZoom = tenMaxZoom;
}
} catch (NumberFormatException e) {
Log.i(TAG, "获取原本的缩放最大级别转换失败");
}
String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
if (takingPictureZoomMaxString != null) {
try {
int takePicMax = Integer.parseInt(takingPictureZoomMaxString);
if (tenDesiredZoom > takePicMax) {
tenDesiredZoom = takePicMax;
}
Log.i(TAG, "拍照缩放级别被最原始级别小");
} catch (NumberFormatException nfe) {
Log.i(TAG, "拍照缩放级别转换失败");
}
}
String motZoomMaxString = parameters.get("mot-zoom-values");
if (motZoomMaxString != null) {
tenDesiredZoom = findBestMotZoomValue(motZoomMaxString, tenDesiredZoom);
}
String motZoomStepString = parameters.get("mot-zoom-step");
if (motZoomStepString != null) {
try {
double motZoomStep = Double.parseDouble(motZoomStepString.trim());
int tenZoomStep = (int) (10.0 * motZoomStep);
if (tenZoomStep > 1) {
tenDesiredZoom -= tenDesiredZoom % tenZoomStep;
}
} catch (NumberFormatException nfe) {
}
}
if (maxZoomString != null || motZoomMaxString != null) {
parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));
}
if (takingPictureZoomMaxString != null) {
parameters.set("taking-picture-zoom", tenDesiredZoom);
}
}
}
private static int findBestMotZoomValue(CharSequence stringValues, int tenDesireZoom) {
int tenBestValue = 0;
for (String stringValue : COMMA_PATTERN.split(stringValues)) {
stringValue = stringValue.trim();
double value;
try {
value = Double.parseDouble(stringValue);
} catch (NumberFormatException nfe) {
return tenDesireZoom;
}
int tenValue = (int) (10.0 * value);
if (Math.abs(tenDesireZoom - value) < Math.abs(tenDesireZoom - tenBestValue)) {
tenBestValue = tenValue;
}
}
return tenBestValue;
}
使用的时候你可以直接进行设置,parameter.set("zoom","10");来设置缩放。
最后贴一个完整测camera的配置类:
import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
public class CameraConfigurationManager {
private static final String TAG = "Cy==CameraConfigManager";
private Context mContext;
private Point screenResolution;
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
private Point cameraResolution;
private static final int TEN_DESIRED_ZOOM = 27;//设置十级缩放级别
private int previewFormat;
private String previewFormatString;
private CameraConfigurationManager() {
}
public Point getCameraResolution() {
return cameraResolution;
}
public Point getScreenResolution() {
return screenResolution;
}
public int getPreviewFormat() {
return previewFormat;
}
public String getPreviewFormatString() {
return previewFormatString;
}
private static final class Holder {
private static final CameraConfigurationManager CAMERA_CONFIGURATION_MANAGER = new CameraConfigurationManager();
}
public static CameraConfigurationManager getInstance() {
return Holder.CAMERA_CONFIGURATION_MANAGER;
}
public CameraConfigurationManager setContext(Context mContext) {
this.mContext = mContext;
return this;
}
/*获取手机的相机和手机屏幕的一些基本参数*/
public void getCameraParams(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
//获取相机预览界面格式
previewFormat = parameters.getPreviewFormat();
previewFormatString = parameters.get("preview-format");
WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
//获取屏幕的宽高(像素值)设置到一个实体(point)里面
screenResolution = new Point(display.getWidth(), display.getHeight());
//尽量获取相机最好的point
cameraResolution = getCameraResolution(parameters, screenResolution);
}
/*设置相机的预览参数(渴望设置成什么样就设置成什么样)*/
public void setDseiredCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);//设置相机的预览size
setFlash(parameters);
setZoom(parameters);
setDisplayOrientation(camera, 90);
camera.setParameters(parameters);
}
/*设置展示角度*/
private void setDisplayOrientation(Camera camera, int orientation) {
Class<? extends Camera> clazz = camera.getClass();
try {
Method displayOrientation = clazz.getMethod("setDisplayOrientation", new Class[]{int.class});
if (displayOrientation != null) {
displayOrientation.invoke(camera, new Object[]{orientation});
}
} catch (Exception e) {
e.printStackTrace();
}
}
/*设置缩放*/
private void setZoom(Camera.Parameters parameters) {
String zoomSupportString = parameters.get("zoom-supported");
if (zoomSupportString != null && !Boolean.parseBoolean(zoomSupportString)) {
return;
}
int tenDesiredZoom = TEN_DESIRED_ZOOM;//TEN_DESIRED_ZOOM = 27
String maxZoomString = parameters.get("max-zoom");
if (maxZoomString != null) {
try {
int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));
if (tenDesiredZoom > tenMaxZoom) {
tenDesiredZoom = tenMaxZoom;
}
} catch (NumberFormatException e) {
Log.i(TAG, "获取原本的缩放最大级别转换失败");
}
String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
if (takingPictureZoomMaxString != null) {
try {
int takePicMax = Integer.parseInt(takingPictureZoomMaxString);
if (tenDesiredZoom > takePicMax) {
tenDesiredZoom = takePicMax;
}
Log.i(TAG, "拍照缩放级别被最原始级别小");
} catch (NumberFormatException nfe) {
Log.i(TAG, "拍照缩放级别转换失败");
}
}
String motZoomMaxString = parameters.get("mot-zoom-values");
if (motZoomMaxString != null) {
tenDesiredZoom = findBestMotZoomValue(motZoomMaxString, tenDesiredZoom);
}
String motZoomStepString = parameters.get("mot-zoom-step");
if (motZoomStepString != null) {
try {
double motZoomStep = Double.parseDouble(motZoomStepString.trim());
int tenZoomStep = (int) (10.0 * motZoomStep);
if (tenZoomStep > 1) {
tenDesiredZoom -= tenDesiredZoom % tenZoomStep;
}
} catch (NumberFormatException nfe) {
}
}
if (maxZoomString != null || motZoomMaxString != null) {
parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));
}
if (takingPictureZoomMaxString != null) {
parameters.set("taking-picture-zoom", tenDesiredZoom);
}
}
}
private static int findBestMotZoomValue(CharSequence stringValues, int tenDesireZoom) {
int tenBestValue = 0;
for (String stringValue : COMMA_PATTERN.split(stringValues)) {
stringValue = stringValue.trim();
double value;
try {
value = Double.parseDouble(stringValue);
} catch (NumberFormatException nfe) {
return tenDesireZoom;
}
int tenValue = (int) (10.0 * value);
if (Math.abs(tenDesireZoom - value) < Math.abs(tenDesireZoom - tenBestValue)) {
tenBestValue = tenValue;
}
}
return tenBestValue;
}
/*设置闪光灯,本来是不用设置的,应该是直接获取,但是根据三星建议说防止黑客攻击,最好设置一下*/
private void setFlash(Camera.Parameters parameters) {
if (Build.MODEL.contains("Behold II") && CameraManager.SDK_INT == 3) {
parameters.set("flash-value", 1);
} else {
parameters.set("flash-value", 2);
}
parameters.set("flash-mode", "off");
}
/*根据相机的参数和手机屏幕参数来重新设置相机的*/
public Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {
String previewSizeValueString = parameters.get("preview-size-values");
if (previewSizeValueString == null) {
previewSizeValueString = parameters.get("preview-size-value");
}
Point cameraResolution = null;
if (previewSizeValueString != null) {
cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);
}
if (cameraResolution == null) {
//没有找到最优的预览效果,那么至少也要确保相机分辨率是8的倍数(我也不知道为什么),下面的操作就是防备屏幕不是8的倍数,如果
//是8的倍数,就会在上面的寻找最优size的时候会找到的
cameraResolution = new Point(
(screenResolution.x >> 3) << 3,
(screenResolution.y >> 3) << 3);
}
return cameraResolution;
}
/*根据预览大小和手机屏幕大小来设一个比较完美的预览效果*/
public Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {
int bestX = 0;
int bestY = 0;
int diff = Integer.MAX_VALUE;//差值
for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {
previewSize = previewSize.trim();
int dimPosition = previewSize.indexOf('x');
if (dimPosition < 0) {
//这是一个很差的预览大小
continue;
}
int newX;
int newY;
try {
newX = Integer.parseInt(previewSize.substring(0, dimPosition));
newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
} catch (NumberFormatException nfe) {
//字符串转换异常,这是自己写的tryCatch,是为了安全起见
continue;
}
int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
if (newDiff == 0) {
bestX = newX;
bestY = newY;
break;
} else if (newDiff < diff) {
bestX = newX;
bestY = newY;
diff = newDiff;
}
}
if (bestY > 0 && bestX > 0) {
return new Point(bestX, bestY);
}
return null;
}
}