private static List<Camera.Area> convertMeteringRegionsToLegacy( Rect activeArray, ParameterUtils.ZoomData zoomData, MeteringRectangle[] meteringRegions, int maxNumMeteringAreas, String regionName) { if (meteringRegions == null || maxNumMeteringAreas <= 0) { if (maxNumMeteringAreas > 0) { return Arrays.asList(ParameterUtils.CAMERA_AREA_DEFAULT); } else { return null; } } // Add all non-zero weight regions to the list List<MeteringRectangle> meteringRectangleList = new ArrayList<>(); for (MeteringRectangle rect : meteringRegions) { if (rect.getMeteringWeight() != MeteringRectangle.METERING_WEIGHT_DONT_CARE) { meteringRectangleList.add(rect); } } if (meteringRectangleList.size() == 0) { Log.w(TAG, "Only received metering rectangles with weight 0."); return Arrays.asList(ParameterUtils.CAMERA_AREA_DEFAULT); } // Ignore any regions beyond our maximum supported count int countMeteringAreas = Math.min(maxNumMeteringAreas, meteringRectangleList.size()); List<Camera.Area> meteringAreaList = new ArrayList<>(countMeteringAreas); for (int i = 0; i < countMeteringAreas; ++i) { MeteringRectangle rect = meteringRectangleList.get(i); ParameterUtils.MeteringData meteringData = ParameterUtils.convertMeteringRectangleToLegacy(activeArray, rect, zoomData); meteringAreaList.add(meteringData.meteringArea); } if (maxNumMeteringAreas < meteringRectangleList.size()) { Log.w( TAG, "convertMeteringRegionsToLegacy - Too many requested " + regionName + " regions, ignoring all beyond the first " + maxNumMeteringAreas); } if (VERBOSE) { Log.v( TAG, "convertMeteringRegionsToLegacy - " + regionName + " areas = " + ParameterUtils.stringFromAreaList(meteringAreaList)); } return meteringAreaList; }
/** * 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. * * <p>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. * * <p>The unzoomed crop rectangle is calculated only. * * @param activeArray active array dimensions, in sensor space * @param previewSize size of the preview buffer render target, in pixels (not in sensor space) * @return a rectangle which serves as the preview stream's effective crop region (unzoomed), in * sensor space * @throws NullPointerException if any of the args were {@code null} * @throws IllegalArgumentException if {@code previewSize} is wider or taller than {@code * activeArray} */ private static Rect getPreviewCropRectangleUnzoomed(Rect activeArray, Size previewSize) { 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 (Math.abs(aspectRatioPreview - aspectRatioArray) < ASPECT_RATIO_TOLERANCE) { cropH = activeArray.height(); cropW = activeArray.width(); } else 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); }