下面列出了怎么用android.hardware.Camera.Area的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Convert a camera area into a human-readable string.
*/
public static String stringFromArea(Camera.Area area) {
if (area == null) {
return null;
} else {
StringBuilder sb = new StringBuilder();
Rect r = area.rect;
sb.setLength(0);
sb.append("(["); sb.append(r.left); sb.append(',');
sb.append(r.top); sb.append("]["); sb.append(r.right);
sb.append(','); sb.append(r.bottom); sb.append(']');
sb.append(',');
sb.append(area.weight);
sb.append(')');
return sb.toString();
}
}
/**
* Convert a camera area list into a human-readable string
* @param areaList a list of areas (null is ok)
*/
public static String stringFromAreaList(List<Camera.Area> areaList) {
StringBuilder sb = new StringBuilder();
if (areaList == null) {
return null;
}
int i = 0;
for (Camera.Area area : areaList) {
if (area == null) {
sb.append("null");
} else {
sb.append(stringFromArea(area));
}
if (i != areaList.size() - 1) {
sb.append(", ");
}
i++;
}
return sb.toString();
}
public static void configureFocusArea(@NonNull final Parameters parameters,
@NonNull final Rect area, final int width, final int height, final int orientation) {
final List<Area> areas = new ArrayList<>(1);
final Rect rotatedArea =
area.rotate(-orientation, width / 2f, height / 2f).bound(0, 0, width, height);
areas.add(new Area(new android.graphics.Rect(mapCoordinate(rotatedArea.getLeft(), width),
mapCoordinate(rotatedArea.getTop(), height),
mapCoordinate(rotatedArea.getRight(), width),
mapCoordinate(rotatedArea.getBottom(), height)), 1000));
if (parameters.getMaxNumFocusAreas() > 0) {
parameters.setFocusAreas(areas);
}
if (parameters.getMaxNumMeteringAreas() > 0) {
parameters.setMeteringAreas(areas);
}
}
/**
* Convert an api1 face into an active-array based api2 face.
*
* <p>Out-of-ranges scores and ids will be clipped to be within range (with a warning).</p>
*
* @param face a non-{@code null} api1 face
* @param activeArraySize active array size of the sensor (e.g. max jpeg size)
* @param zoomData the calculated zoom data corresponding to this request
*
* @return a non-{@code null} api2 face
*
* @throws NullPointerException if the {@code face} was {@code null}
*/
public static Face convertFaceFromLegacy(Camera.Face face, Rect activeArray,
ZoomData zoomData) {
checkNotNull(face, "face must not be null");
Face api2Face;
Camera.Area fakeArea = new Camera.Area(face.rect, /*weight*/1);
WeightedRectangle faceRect =
convertCameraAreaToActiveArrayRectangle(activeArray, zoomData, fakeArea);
Point leftEye = face.leftEye, rightEye = face.rightEye, mouth = face.mouth;
if (leftEye != null && rightEye != null && mouth != null && leftEye.x != -2000 &&
leftEye.y != -2000 && rightEye.x != -2000 && rightEye.y != -2000 &&
mouth.x != -2000 && mouth.y != -2000) {
leftEye = convertCameraPointToActiveArrayPoint(activeArray, zoomData,
leftEye, /*usePreviewCrop*/true);
rightEye = convertCameraPointToActiveArrayPoint(activeArray, zoomData,
leftEye, /*usePreviewCrop*/true);
mouth = convertCameraPointToActiveArrayPoint(activeArray, zoomData,
leftEye, /*usePreviewCrop*/true);
api2Face = faceRect.toFace(face.id, leftEye, rightEye, mouth);
} else {
api2Face = faceRect.toFace();
}
return api2Face;
}
private static Point convertCameraPointToActiveArrayPoint(
Rect activeArray, ZoomData zoomData, Point point, boolean usePreviewCrop) {
Rect pointedRect = new Rect(point.x, point.y, point.x, point.y);
Camera.Area pointedArea = new Area(pointedRect, /*weight*/1);
WeightedRectangle adjustedRect =
convertCameraAreaToActiveArrayRectangle(activeArray,
zoomData, pointedArea, usePreviewCrop);
Point transformedPoint = new Point(adjustedRect.rect.left, adjustedRect.rect.top);
return transformedPoint;
}
private void initializeFocusAreas(int x, int y)
{
if (mFocusArea == null)
{
mFocusArea = new ArrayList<Area>();
mFocusArea.add(new Area(new Rect(), 1));
}
// Convert the coordinates to driver format.
mFocusArea.get(0).rect = computeCameraRectFromPreviewCoordinates(x, y, getAFRegionSizePx());
}
private void initializeMeteringAreas(int x, int y)
{
if (mMeteringArea == null)
{
mMeteringArea = new ArrayList<Area>();
mMeteringArea.add(new Area(new Rect(), 1));
}
// Convert the coordinates to driver format.
mMeteringArea.get(0).rect = computeCameraRectFromPreviewCoordinates(x, y, getAERegionSizePx());
}
/**
* 手动对焦
*
* @param focusAreas 对焦区域
* @return
*/
@SuppressLint("NewApi")
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public boolean manualFocus(AutoFocusCallback cb, List<Area> focusAreas) {
if (camera != null && focusAreas != null && mParameters != null && DeviceUtils.hasICS()) {
try {
camera.cancelAutoFocus();
// getMaxNumFocusAreas检测设备是否支持
if (mParameters.getMaxNumFocusAreas() > 0) {
// mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);//
// Macro(close-up) focus mode
mParameters.setFocusAreas(focusAreas);
}
if (mParameters.getMaxNumMeteringAreas() > 0)
mParameters.setMeteringAreas(focusAreas);
mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);
camera.setParameters(mParameters);
camera.autoFocus(cb);
return true;
} catch (Exception e) {
if (mOnErrorListener != null) {
mOnErrorListener.onVideoError(MEDIA_ERROR_CAMERA_AUTO_FOCUS, 0);
}
if (e != null)
Log.e("Yixia", "autoFocus", e);
}
}
return false;
}
/**
* 手动聚焦
* @param point 触屏坐标
*/
protected void onFocus(Point point,AutoFocusCallback callback){
Parameters parameters=mCamera.getParameters();
//不支持设置自定义聚焦,则使用自动聚焦,返回
if (parameters.getMaxNumFocusAreas()<=0) {
mCamera.autoFocus(callback);
return;
}
List<Area> areas=new ArrayList<Area>();
int left=point.x-300;
int top=point.y-300;
int right=point.x+300;
int bottom=point.y+300;
left=left<-1000?-1000:left;
top=top<-1000?-1000:top;
right=right>1000?1000:right;
bottom=bottom>1000?1000:bottom;
areas.add(new Area(new Rect(left,top,right,bottom), 100));
parameters.setFocusAreas(areas);
try {
//本人使用的小米手机在设置聚焦区域的时候经常会出异常,看日志发现是框架层的字符串转int的时候出错了,
//目测是小米修改了框架层代码导致,在此try掉,对实际聚焦效果没影响
mCamera.setParameters(parameters);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
mCamera.autoFocus(callback);
}
public MeteringData(Area meteringArea, Rect previewMetering, Rect reportedMetering) {
this.meteringArea = meteringArea;
this.previewMetering = previewMetering;
this.reportedMetering = reportedMetering;
}
/**
* Calculate the actual/effective/reported normalized rectangle data from a metering
* rectangle.
*
* <p>If any of the rectangles are out-of-range of their intended bounding box,
* the {@link #RECTANGLE_EMPTY empty rectangle} is substituted instead
* (with a weight of {@code 0}).</p>
*
* <p>The metering rectangle is bound by the crop region (effective/reported respectively).
* The metering {@link Camera.Area area} is bound by {@code [-1000, 1000]}.</p>
*
* <p>No parameters are mutated; returns the new metering data.</p>
*
* @param activeArraySize active array size of the sensor (e.g. max jpeg size)
* @param meteringRect the user-specified metering rectangle
* @param zoomData the calculated zoom data corresponding to this request
*
* @return the metering area, the reported/effective metering rectangles
*/
public static MeteringData convertMeteringRectangleToLegacy(
Rect activeArray, MeteringRectangle meteringRect, ZoomData zoomData) {
Rect previewCrop = zoomData.previewCrop;
float scaleW = (NORMALIZED_RECTANGLE_MAX - NORMALIZED_RECTANGLE_MIN) * 1.0f /
previewCrop.width();
float scaleH = (NORMALIZED_RECTANGLE_MAX - NORMALIZED_RECTANGLE_MIN) * 1.0f /
previewCrop.height();
Matrix transform = new Matrix();
// Move the preview crop so that top,left is at (0,0), otherwise after scaling
// the corner bounds will be outside of [-1000, 1000]
transform.setTranslate(-previewCrop.left, -previewCrop.top);
// Scale into [0, 2000] range about the center of the preview
transform.postScale(scaleW, scaleH);
// Move so that top left of a typical rect is at [-1000, -1000]
transform.postTranslate(/*dx*/NORMALIZED_RECTANGLE_MIN, /*dy*/NORMALIZED_RECTANGLE_MIN);
/*
* Calculate the preview metering region (effective), and the camera1 api
* normalized metering region.
*/
Rect normalizedRegionUnbounded = ParamsUtils.mapRect(transform, meteringRect.getRect());
/*
* Try to intersect normalized area with [-1000, 1000] rectangle; otherwise
* it's completely out of range
*/
Rect normalizedIntersected = new Rect(normalizedRegionUnbounded);
Camera.Area meteringArea;
if (!normalizedIntersected.intersect(NORMALIZED_RECTANGLE_DEFAULT)) {
Log.w(TAG,
"convertMeteringRectangleToLegacy - metering rectangle too small, " +
"no metering will be done");
normalizedIntersected.set(RECTANGLE_EMPTY);
meteringArea = new Camera.Area(RECTANGLE_EMPTY,
MeteringRectangle.METERING_WEIGHT_DONT_CARE);
} else {
meteringArea = new Camera.Area(normalizedIntersected,
meteringRect.getMeteringWeight());
}
/*
* Calculate effective preview metering region
*/
Rect previewMetering = meteringRect.getRect();
if (!previewMetering.intersect(previewCrop)) {
previewMetering.set(RECTANGLE_EMPTY);
}
/*
* Calculate effective reported metering region
* - Transform the calculated metering area back into active array space
* - Clip it to be a subset of the reported crop region
*/
Rect reportedMetering;
{
Camera.Area normalizedAreaUnbounded = new Camera.Area(
normalizedRegionUnbounded, meteringRect.getMeteringWeight());
WeightedRectangle reportedMeteringRect = convertCameraAreaToActiveArrayRectangle(
activeArray, zoomData, normalizedAreaUnbounded, /*usePreviewCrop*/false);
reportedMetering = reportedMeteringRect.rect;
}
if (DEBUG) {
Log.v(TAG, String.format(
"convertMeteringRectangleToLegacy - activeArray = %s, meteringRect = %s, " +
"previewCrop = %s, meteringArea = %s, previewMetering = %s, " +
"reportedMetering = %s, normalizedRegionUnbounded = %s",
activeArray, meteringRect,
previewCrop, stringFromArea(meteringArea), previewMetering,
reportedMetering, normalizedRegionUnbounded));
}
return new MeteringData(meteringArea, previewMetering, reportedMetering);
}
private static WeightedRectangle convertCameraAreaToActiveArrayRectangle(
Rect activeArray, ZoomData zoomData, Camera.Area area, boolean usePreviewCrop) {
Rect previewCrop = zoomData.previewCrop;
Rect reportedCrop = zoomData.reportedCrop;
float scaleW = previewCrop.width() * 1.0f /
(NORMALIZED_RECTANGLE_MAX - NORMALIZED_RECTANGLE_MIN);
float scaleH = previewCrop.height() * 1.0f /
(NORMALIZED_RECTANGLE_MAX - NORMALIZED_RECTANGLE_MIN);
/*
* Calculate the reported metering region from the non-intersected normalized region
* by scaling and translating back into active array-relative coordinates.
*/
Matrix transform = new Matrix();
// Move top left from (-1000, -1000) to (0, 0)
transform.setTranslate(/*dx*/NORMALIZED_RECTANGLE_MAX, /*dy*/NORMALIZED_RECTANGLE_MAX);
// Scale from [0, 2000] back into the preview rectangle
transform.postScale(scaleW, scaleH);
// Move the rect so that the [-1000,-1000] point ends up at the preview [left, top]
transform.postTranslate(previewCrop.left, previewCrop.top);
Rect cropToIntersectAgainst = usePreviewCrop ? previewCrop : reportedCrop;
// Now apply the transformation backwards to get the reported metering region
Rect reportedMetering = ParamsUtils.mapRect(transform, area.rect);
// Intersect it with the crop region, to avoid reporting out-of-bounds
// metering regions
if (!reportedMetering.intersect(cropToIntersectAgainst)) {
reportedMetering.set(RECTANGLE_EMPTY);
}
int weight = area.weight;
if (weight < MeteringRectangle.METERING_WEIGHT_MIN) {
Log.w(TAG,
"convertCameraAreaToMeteringRectangle - rectangle "
+ stringFromArea(area) + " has too small weight, clip to 0");
weight = 0;
}
return new WeightedRectangle(reportedMetering, area.weight);
}
public List<Area> getFocusAreas()
{
return mFocusArea;
}
public List<Area> getMeteringAreas()
{
return mMeteringArea;
}
/**
* Convert the normalized camera area from [-1000, 1000] coordinate space
* into the active array-based coordinate space.
*
* <p>Values out of range are clipped to be within the resulting (reported) crop
* region. It is possible to have values larger than the preview crop.</p>
*
* <p>Weights out of range of [0, 1000] are clipped to be within the range.</p>
*
* @param activeArraySize active array size of the sensor (e.g. max jpeg size)
* @param zoomData the calculated zoom data corresponding to this request
* @param area the normalized camera area
*
* @return the weighed rectangle in active array coordinate space, with the weight
*/
public static WeightedRectangle convertCameraAreaToActiveArrayRectangle(
Rect activeArray, ZoomData zoomData, Camera.Area area) {
return convertCameraAreaToActiveArrayRectangle(activeArray, zoomData, area,
/*usePreviewCrop*/true);
}