Home | History | Annotate | Download | only in autofocus
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.camera.one.v2.autofocus;
     18 
     19 import android.graphics.PointF;
     20 import android.graphics.Rect;
     21 import android.hardware.camera2.CaptureRequest;
     22 import android.hardware.camera2.params.MeteringRectangle;
     23 
     24 import com.android.camera.one.Settings3A;
     25 import com.google.common.base.Preconditions;
     26 
     27 final class PointMeteringParameters implements MeteringParameters {
     28     private final PointF mAFPoint;
     29     private final PointF mAEPoint;
     30     private final int mSensorOrientation;
     31     private final Settings3A mSettings3A;
     32 
     33     private PointMeteringParameters(PointF afPoint, PointF aePoint, int sensorOrientation,
     34             Settings3A settings3A) {
     35         mAFPoint = afPoint;
     36         mAEPoint = aePoint;
     37         mSensorOrientation = sensorOrientation;
     38         mSettings3A = settings3A;
     39     }
     40 
     41     /**
     42      * Constructs new MeteringParameters.
     43      *
     44      * @param afPoint The center of the desired AF metering region, in
     45      *            normalized portrait coordinates such that (0, 0) is top left
     46      *            and (1, 1) is bottom right.
     47      * @param aePoint The center of the desired AE metering region, in
     48      *            normalized portrait coordinates such that (0, 0) is top left
     49      *            and (1, 1) is bottom right.
     50      * @param sensorOrientation sensor orientation as defined by
     51      *            CameraCharacteristics
     52      *            .get(CameraCharacteristics.SENSOR_ORIENTATION).
     53      * @param settings3A 3A settings.
     54      */
     55     public static PointMeteringParameters createForNormalizedCoordinates(
     56             PointF afPoint,
     57             PointF aePoint,
     58             int sensorOrientation,
     59             Settings3A settings3A) {
     60         Preconditions.checkArgument(sensorOrientation % 90 == 0, "sensorOrientation must be a " +
     61                 "multiple of 90");
     62         Preconditions.checkArgument(sensorOrientation >= 0, "sensorOrientation must not be " +
     63                 "negative");
     64         sensorOrientation %= 360;
     65 
     66         return new PointMeteringParameters(afPoint, aePoint, sensorOrientation,
     67                 settings3A);
     68     }
     69 
     70     /**
     71      * @param cropRegion The current crop region, see
     72      *            {@link CaptureRequest#SCALER_CROP_REGION}.
     73      */
     74     @Override
     75     public MeteringRectangle[] getAERegions(Rect cropRegion) {
     76         return new MeteringRectangle[] {
     77                 regionForNormalizedCoord(mAEPoint, cropRegion)
     78         };
     79     }
     80 
     81     /**
     82      * @param cropRegion The current crop region, see
     83      *            {@link CaptureRequest#SCALER_CROP_REGION}.
     84      */
     85     @Override
     86     public MeteringRectangle[] getAFRegions(Rect cropRegion) {
     87         return new MeteringRectangle[] {
     88                 regionForNormalizedCoord(mAFPoint, cropRegion)
     89         };
     90     }
     91 
     92     private MeteringRectangle regionForNormalizedCoord(PointF point,
     93             Rect cropRegion) {
     94         // Compute half side length in pixels.
     95         int minCropEdge = Math.min(cropRegion.width(), cropRegion.height());
     96         int halfSideLength = (int) (0.5f * mSettings3A.getMeteringRegionFraction() * minCropEdge);
     97 
     98         // Compute the output MeteringRectangle in sensor space.
     99         // point is normalized to the screen.
    100         // Crop region itself is specified in sensor coordinates (see
    101         // CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE).
    102 
    103         // Normalized coordinates, now rotated into sensor space.
    104         PointF nsc = transformPortraitCoordinatesToSensorCoordinates(point);
    105 
    106         int xCenterSensor = (int) (cropRegion.left + nsc.x * cropRegion.width());
    107         int yCenterSensor = (int) (cropRegion.top + nsc.y * cropRegion.height());
    108 
    109         Rect meteringRegion = new Rect(xCenterSensor - halfSideLength,
    110                 yCenterSensor - halfSideLength,
    111                 xCenterSensor + halfSideLength,
    112                 yCenterSensor + halfSideLength);
    113 
    114         // Clamp meteringRegion to cropRegion.
    115         meteringRegion.left = clamp(meteringRegion.left, cropRegion.left,
    116                 cropRegion.right);
    117         meteringRegion.top = clamp(meteringRegion.top, cropRegion.top, cropRegion.bottom);
    118         meteringRegion.right = clamp(meteringRegion.right, cropRegion.left,
    119                 cropRegion.right);
    120         meteringRegion.bottom = clamp(meteringRegion.bottom, cropRegion.top,
    121                 cropRegion.bottom);
    122 
    123         return new MeteringRectangle(meteringRegion, mSettings3A.getMeteringWeight());
    124     }
    125 
    126     /**
    127      * Given (nx, ny) \in [0, 1]^2, in the display's portrait coordinate system,
    128      * returns normalized sensor coordinates \in [0, 1]^2 depending on how the
    129      * sensor's orientation \in {0, 90, 180, 270}.
    130      */
    131     private PointF transformPortraitCoordinatesToSensorCoordinates(
    132             PointF point) {
    133         switch (mSensorOrientation) {
    134             case 0:
    135                 return point;
    136             case 90:
    137                 return new PointF(point.y, 1.0f - point.x);
    138             case 180:
    139                 return new PointF(1.0f - point.x, 1.0f - point.y);
    140             case 270:
    141                 return new PointF(1.0f - point.y, point.x);
    142             default:
    143                 // Impossible exception.
    144                 throw new IllegalArgumentException("Unsupported Sensor Orientation");
    145         }
    146     }
    147 
    148     private int clamp(int value, int min, int max) {
    149         return Math.min(Math.max(value, min), max);
    150     }
    151 }
    152