ParameterUtilspublic class ParameterUtils extends Object Various utilities for dealing with camera API1 parameters. |
Fields Summary |
---|
public static final int | NORMALIZED_RECTANGLE_MINUpper/left minimal point of a normalized rectangle | public static final int | NORMALIZED_RECTANGLE_MAXLower/right maximal point of a normalized rectangle | public static final android.graphics.Rect | NORMALIZED_RECTANGLE_DEFAULTThe default normalized rectangle spans the entire size of the preview viewport | public static final android.hardware.Camera.Area | CAMERA_AREA_DEFAULTThe default normalized area uses the default normalized rectangle with a weight=1 | public static final android.graphics.Rect | RECTANGLE_EMPTYEmpty rectangle {@code 0x0+0,0} | private static final String | TAG | private static final boolean | VERBOSE | private static final int | ZOOM_RATIO_MULTIPLIERgetZoomRatios stores zoom ratios in 1/100 increments, e.x. a zoom of 3.2 is 320 |
Constructors Summary |
---|
private ParameterUtils()
throw new AssertionError();
|
Methods Summary |
---|
public static boolean | containsSize(java.util.List sizeList, int width, int height)Check if the camera API1 list of sizes contains a size with the given dimens.
checkNotNull(sizeList, "sizeList must not be null");
for (Camera.Size s : sizeList) {
if (s.height == height && s.width == width) {
return true;
}
}
return false;
| public static android.hardware.camera2.legacy.ParameterUtils$WeightedRectangle | convertCameraAreaToActiveArrayRectangle(android.graphics.Rect activeArray, android.hardware.camera2.legacy.ParameterUtils$ZoomData zoomData, android.hardware.Camera.Area area)Convert the normalized camera area from [-1000, 1000] coordinate space
into the active array-based coordinate space.
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.
Weights out of range of [0, 1000] are clipped to be within the range.
return convertCameraAreaToActiveArrayRectangle(activeArray, zoomData, area,
/*usePreviewCrop*/true);
| private static android.hardware.camera2.legacy.ParameterUtils$WeightedRectangle | convertCameraAreaToActiveArrayRectangle(android.graphics.Rect activeArray, android.hardware.camera2.legacy.ParameterUtils$ZoomData zoomData, android.hardware.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);
| private static android.graphics.Point | convertCameraPointToActiveArrayPoint(android.graphics.Rect activeArray, android.hardware.camera2.legacy.ParameterUtils$ZoomData zoomData, android.graphics.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;
| public static android.hardware.camera2.params.Face | convertFaceFromLegacy(Camera.Face face, android.graphics.Rect activeArray, android.hardware.camera2.legacy.ParameterUtils$ZoomData zoomData)Convert an api1 face into an active-array based api2 face.
Out-of-ranges scores and ids will be clipped to be within range (with a warning).
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;
| public static android.hardware.camera2.legacy.ParameterUtils$MeteringData | convertMeteringRectangleToLegacy(android.graphics.Rect activeArray, android.hardware.camera2.params.MeteringRectangle meteringRect, android.hardware.camera2.legacy.ParameterUtils$ZoomData zoomData)Calculate the actual/effective/reported normalized rectangle data from a metering
rectangle.
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}).
The metering rectangle is bound by the crop region (effective/reported respectively).
The metering {@link Camera.Area area} is bound by {@code [-1000, 1000]}.
No parameters are mutated; returns the new metering data.
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 (VERBOSE) {
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);
| public static android.hardware.camera2.legacy.ParameterUtils$ZoomData | convertScalerCropRegion(android.graphics.Rect activeArraySize, android.graphics.Rect cropRegion, android.util.Size previewSize, Camera.Parameters params)Convert the user-specified crop region into zoom data; which can be used
to set the parameters to a specific zoom index, or to report back to the user what the
actual zoom was, or for other calculations requiring the current preview crop region.
None of the parameters are mutated.
Rect activeArraySizeOnly = new Rect(
/*left*/0, /*top*/0,
activeArraySize.width(), activeArraySize.height());
Rect userCropRegion = cropRegion;
if (userCropRegion == null) {
userCropRegion = activeArraySizeOnly;
}
if (VERBOSE) {
Log.v(TAG, "convertScalerCropRegion - user crop region was " + userCropRegion);
}
final Rect reportedCropRegion = new Rect();
final Rect previewCropRegion = new Rect();
final int zoomIdx = ParameterUtils.getClosestAvailableZoomCrop(params, activeArraySizeOnly,
previewSize, userCropRegion,
/*out*/reportedCropRegion, /*out*/previewCropRegion);
if (VERBOSE) {
Log.v(TAG, "convertScalerCropRegion - zoom calculated to: " +
"zoomIndex = " + zoomIdx +
", reported crop region = " + reportedCropRegion +
", preview crop region = " + previewCropRegion);
}
return new ZoomData(zoomIdx, previewCropRegion, reportedCropRegion);
| public static android.util.Size | convertSize(Camera.Size size)Convert a camera API1 size into a util size
checkNotNull(size, "size must not be null");
return new Size(size.width, size.height);
| public static java.util.List | convertSizeList(java.util.List sizeList)Convert a camera API1 list of sizes into a util list of sizes
checkNotNull(sizeList, "sizeList must not be null");
List<Size> sizes = new ArrayList<>(sizeList.size());
for (Camera.Size s : sizeList) {
sizes.add(new Size(s.width, s.height));
}
return sizes;
| public static android.util.Size[] | convertSizeListToArray(java.util.List sizeList)Convert a camera API1 list of sizes into an array of sizes
checkNotNull(sizeList, "sizeList must not be null");
Size[] array = new Size[sizeList.size()];
int ctr = 0;
for (Camera.Size s : sizeList) {
array[ctr++] = new Size(s.width, s.height);
}
return array;
| private static java.util.List | getAvailableCropRectangles(Camera.Parameters params, android.graphics.Rect activeArray, android.util.Size streamSize)Get the available 'crop' (zoom) rectangles for this camera.
When zoom is supported, this will return a list of {@code 1 + #getMaxZoom} size,
where each crop rectangle corresponds to a zoom ratio (and is centered at the middle).
Each crop rectangle is changed to have the same aspect ratio as {@code streamSize},
by shrinking the rectangle if necessary.
To get the reported crop region when applying a zoom to the sensor, use {@code streamSize}
= {@code activeArray size}.
checkNotNull(params, "params must not be null");
checkNotNull(activeArray, "activeArray must not be null");
checkNotNull(streamSize, "streamSize must not be null");
// TODO: change all uses of Rect activeArray to Size activeArray,
// since we want the crop to be active-array relative, not pixel-array relative
Rect unzoomedStreamCrop = getPreviewCropRectangleUnzoomed(activeArray, streamSize);
if (!params.isZoomSupported()) {
// Trivial case: No zoom -> only support the full size as the crop region
return new ArrayList<>(Arrays.asList(unzoomedStreamCrop));
}
List<Rect> zoomCropRectangles = new ArrayList<>(params.getMaxZoom() + 1);
Matrix scaleMatrix = new Matrix();
RectF scaledRect = new RectF();
for (int zoom : params.getZoomRatios()) {
float shrinkRatio = ZOOM_RATIO_MULTIPLIER * 1.0f / zoom; // normalize to 1.0 and smaller
// set scaledRect to unzoomedStreamCrop
ParamsUtils.convertRectF(unzoomedStreamCrop, /*out*/scaledRect);
scaleMatrix.setScale(
shrinkRatio, shrinkRatio,
activeArray.exactCenterX(),
activeArray.exactCenterY());
scaleMatrix.mapRect(scaledRect);
Rect intRect = ParamsUtils.createRect(scaledRect);
// Round the rect corners towards the nearest integer values
zoomCropRectangles.add(intRect);
}
return zoomCropRectangles;
| public static java.util.List | getAvailablePreviewZoomCropRectangles(Camera.Parameters params, android.graphics.Rect activeArray, android.util.Size previewSize)Get the available 'crop' (zoom) rectangles for this camera.
This is the effective (real) crop that is applied by the camera api1 device
when projecting the zoom onto the intermediate preview buffer. Use this when
deciding which zoom ratio to apply.
When zoom is supported, this will return a list of {@code 1 + #getMaxZoom} size,
where each crop rectangle corresponds to a zoom ratio (and is centered at the middle).
Each crop rectangle is changed to have the same aspect ratio as {@code streamSize},
by shrinking the rectangle if necessary.
To get the reported crop region when applying a zoom to the sensor, use {@code streamSize}
= {@code activeArray size}.
checkNotNull(params, "params must not be null");
checkNotNull(activeArray, "activeArray must not be null");
checkNotNull(previewSize, "previewSize must not be null");
return getAvailableCropRectangles(params, activeArray, previewSize);
| public static java.util.List | getAvailableZoomCropRectangles(Camera.Parameters params, android.graphics.Rect activeArray)Get the available 'crop' (zoom) rectangles for this camera that will be reported
via a {@code CaptureResult} when a zoom is requested.
These crops ignores the underlying preview buffer size, and will always be reported
the same values regardless of what configuration of outputs is used.
When zoom is supported, this will return a list of {@code 1 + #getMaxZoom} size,
where each crop rectangle corresponds to a zoom ratio (and is centered at the middle).
Each crop rectangle is changed to have the same aspect ratio as {@code streamSize},
by shrinking the rectangle if necessary.
To get the reported crop region when applying a zoom to the sensor, use {@code streamSize}
= {@code activeArray size}.
checkNotNull(params, "params must not be null");
checkNotNull(activeArray, "activeArray must not be null");
return getAvailableCropRectangles(params, activeArray, ParamsUtils.createSize(activeArray));
| public static int | getClosestAvailableZoomCrop(Camera.Parameters params, android.graphics.Rect activeArray, android.util.Size streamSize, android.graphics.Rect cropRegion, android.graphics.Rect reportedCropRegion, android.graphics.Rect previewCropRegion)Calculate the closest zoom index for the user-requested crop region by rounding
up to the closest (largest or equal) possible zoom crop.
If the requested crop region exceeds the size of the active array, it is
shrunk to fit inside of the active array first.
Since all api1 camera devices only support a discrete set of zooms, we have
to translate the per-pixel-granularity requested crop region into a per-zoom-index
granularity.
Furthermore, since the zoom index and zoom levels also depends on the field-of-view
of the preview, the current preview {@code streamSize} is also used.
The calculated crop regions are then written to in-place to {@code reportedCropRegion}
and {@code previewCropRegion}, in coordinates relative to the active array.
checkNotNull(params, "params must not be null");
checkNotNull(activeArray, "activeArray must not be null");
checkNotNull(streamSize, "streamSize must not be null");
checkNotNull(reportedCropRegion, "reportedCropRegion must not be null");
checkNotNull(previewCropRegion, "previewCropRegion must not be null");
Rect actualCrop = new Rect(cropRegion);
/*
* Shrink requested crop region to fit inside of the active array size
*/
if (!actualCrop.intersect(activeArray)) {
Log.w(TAG, "getClosestAvailableZoomCrop - Crop region out of range; " +
"setting to active array size");
actualCrop.set(activeArray);
}
Rect previewCrop = getPreviewCropRectangleUnzoomed(activeArray, streamSize);
// Make the user-requested crop region the same aspect ratio as the preview stream size
Rect cropRegionAsPreview =
shrinkToSameAspectRatioCentered(previewCrop, actualCrop);
if (VERBOSE) {
Log.v(TAG, "getClosestAvailableZoomCrop - actualCrop = " + actualCrop);
Log.v(TAG,
"getClosestAvailableZoomCrop - previewCrop = " + previewCrop);
Log.v(TAG,
"getClosestAvailableZoomCrop - cropRegionAsPreview = " + cropRegionAsPreview);
}
/*
* Iterate all available zoom rectangles and find the closest zoom index
*/
Rect bestReportedCropRegion = null;
Rect bestPreviewCropRegion = null;
int bestZoomIndex = -1;
List<Rect> availableReportedCropRegions =
getAvailableZoomCropRectangles(params, activeArray);
List<Rect> availablePreviewCropRegions =
getAvailablePreviewZoomCropRectangles(params, activeArray, streamSize);
if (VERBOSE) {
Log.v(TAG,
"getClosestAvailableZoomCrop - availableReportedCropRegions = " +
ListUtils.listToString(availableReportedCropRegions));
Log.v(TAG,
"getClosestAvailableZoomCrop - availablePreviewCropRegions = " +
ListUtils.listToString(availablePreviewCropRegions));
}
if (availableReportedCropRegions.size() != availablePreviewCropRegions.size()) {
throw new AssertionError("available reported/preview crop region size mismatch");
}
for (int i = 0; i < availableReportedCropRegions.size(); ++i) {
Rect currentPreviewCropRegion = availablePreviewCropRegions.get(i);
Rect currentReportedCropRegion = availableReportedCropRegions.get(i);
boolean isBest;
if (bestZoomIndex == -1) {
isBest = true;
} else if (currentPreviewCropRegion.width() >= cropRegionAsPreview.width() &&
currentPreviewCropRegion.height() >= cropRegionAsPreview.height()) {
isBest = true;
} else {
isBest = false;
}
// Sizes are sorted largest-to-smallest, so once the available crop is too small,
// we the rest are too small. Furthermore, this is the final best crop,
// since its the largest crop that still fits the requested crop
if (isBest) {
bestPreviewCropRegion = currentPreviewCropRegion;
bestReportedCropRegion = currentReportedCropRegion;
bestZoomIndex = i;
} else {
break;
}
}
if (bestZoomIndex == -1) {
// Even in the worst case, we should always at least return 0 here
throw new AssertionError("Should've found at least one valid zoom index");
}
// Write the rectangles in-place
reportedCropRegion.set(bestReportedCropRegion);
previewCropRegion.set(bestPreviewCropRegion);
return bestZoomIndex;
| public static android.util.Size | getLargestSupportedJpegSizeByArea(Camera.Parameters params)Returns the largest supported picture size, as compared by its area.
checkNotNull(params, "params must not be null");
List<Size> supportedJpegSizes = convertSizeList(params.getSupportedPictureSizes());
return SizeAreaComparator.findLargestByArea(supportedJpegSizes);
| public static float | getMaxZoomRatio(Camera.Parameters params)Get the largest possible zoom ratio (normalized to {@code 1.0f} and higher)
that the camera can support.
If the camera does not support zoom, it always returns {@code 1.0f}.
if (!params.isZoomSupported()) {
return 1.0f; // no zoom
}
List<Integer> zoomRatios = params.getZoomRatios(); // sorted smallest->largest
int zoom = zoomRatios.get(zoomRatios.size() - 1); // largest zoom ratio
float zoomRatio = zoom * 1.0f / ZOOM_RATIO_MULTIPLIER; // normalize to 1.0 and smaller
return zoomRatio;
| private static android.graphics.Rect | getPreviewCropRectangleUnzoomed(android.graphics.Rect activeArray, android.util.Size previewSize)Calculate the effective crop rectangle for this preview viewport;
assumes the preview is centered to the sensor and scaled to fit across one of the dimensions
without skewing.
The preview size must be a subset of the active array size; the resulting
rectangle will also be a subset of the active array rectangle.
The unzoomed crop rectangle is calculated only.
if (previewSize.getWidth() > activeArray.width()) {
throw new IllegalArgumentException("previewSize must not be wider than activeArray");
} else if (previewSize.getHeight() > activeArray.height()) {
throw new IllegalArgumentException("previewSize must not be taller than activeArray");
}
float aspectRatioArray = activeArray.width() * 1.0f / activeArray.height();
float aspectRatioPreview = previewSize.getWidth() * 1.0f / previewSize.getHeight();
float cropH, cropW;
if (aspectRatioPreview < aspectRatioArray) {
// The new width must be smaller than the height, so scale the width by AR
cropH = activeArray.height();
cropW = cropH * aspectRatioPreview;
} else {
// The new height must be smaller (or equal) than the width, so scale the height by AR
cropW = activeArray.width();
cropH = cropW / aspectRatioPreview;
}
Matrix translateMatrix = new Matrix();
RectF cropRect = new RectF(/*left*/0, /*top*/0, cropW, cropH);
// Now center the crop rectangle so its center is in the center of the active array
translateMatrix.setTranslate(activeArray.exactCenterX(), activeArray.exactCenterY());
translateMatrix.postTranslate(-cropRect.centerX(), -cropRect.centerY());
translateMatrix.mapRect(/*inout*/cropRect);
// Round the rect corners towards the nearest integer values
return ParamsUtils.createRect(cropRect);
| private static android.util.SizeF | getZoomRatio(android.util.Size activeArraySize, android.util.Size cropSize)Returns the component-wise zoom ratio (each greater or equal than {@code 1.0});
largest values means more zoom.
checkNotNull(activeArraySize, "activeArraySize must not be null");
checkNotNull(cropSize, "cropSize must not be null");
checkArgumentPositive(cropSize.getWidth(), "cropSize.width must be positive");
checkArgumentPositive(cropSize.getHeight(), "cropSize.height must be positive");
float zoomRatioWidth = activeArraySize.getWidth() * 1.0f / cropSize.getWidth();
float zoomRatioHeight = activeArraySize.getHeight() * 1.0f / cropSize.getHeight();
return new SizeF(zoomRatioWidth, zoomRatioHeight);
| private static android.graphics.Rect | shrinkToSameAspectRatioCentered(android.graphics.Rect reference, android.graphics.Rect shrinkTarget)Shrink the {@code shrinkTarget} rectangle to snugly fit inside of {@code reference};
the aspect ratio of {@code shrinkTarget} will change to be the same aspect ratio as
{@code reference}.
At most a single dimension will scale (down). Both dimensions will never be scaled.
float aspectRatioReference = reference.width() * 1.0f / reference.height();
float aspectRatioShrinkTarget = shrinkTarget.width() * 1.0f / shrinkTarget.height();
float cropH, cropW;
if (aspectRatioShrinkTarget < aspectRatioReference) {
// The new width must be smaller than the height, so scale the width by AR
cropH = reference.height();
cropW = cropH * aspectRatioShrinkTarget;
} else {
// The new height must be smaller (or equal) than the width, so scale the height by AR
cropW = reference.width();
cropH = cropW / aspectRatioShrinkTarget;
}
Matrix translateMatrix = new Matrix();
RectF shrunkRect = new RectF(shrinkTarget);
// Scale the rectangle down, but keep its center in the same place as before
translateMatrix.setScale(cropW / reference.width(), cropH / reference.height(),
shrinkTarget.exactCenterX(), shrinkTarget.exactCenterY());
translateMatrix.mapRect(/*inout*/shrunkRect);
return ParamsUtils.createRect(shrunkRect);
| public static java.lang.String | stringFromArea(android.hardware.Camera.Area area)Convert a camera area into a human-readable string.
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();
}
| public static java.lang.String | stringFromAreaList(java.util.List areaList)Convert a camera area list into a human-readable string
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();
|
|