Home | History | Annotate | Download | only in utils
      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 android.hardware.camera2.utils;
     18 
     19 import android.graphics.Matrix;
     20 import android.graphics.Rect;
     21 import android.graphics.RectF;
     22 import android.hardware.camera2.CaptureRequest;
     23 import android.util.Rational;
     24 import android.util.Size;
     25 
     26 import static com.android.internal.util.Preconditions.*;
     27 
     28 /**
     29  * Various assortment of params utilities.
     30  */
     31 public class ParamsUtils {
     32 
     33     /** Arbitrary denominator used to estimate floats as rationals */
     34     private static final int RATIONAL_DENOMINATOR = 1000000; // 1million
     35 
     36     /**
     37      * Create a {@link Rect} from a {@code Size} by creating a new rectangle with
     38      * left, top = {@code (0, 0)} and right, bottom = {@code (width, height)}
     39      *
     40      * @param size a non-{@code null} size
     41      *
     42      * @return a {@code non-null} rectangle
     43      *
     44      * @throws NullPointerException if {@code size} was {@code null}
     45      */
     46     public static Rect createRect(Size size) {
     47         checkNotNull(size, "size must not be null");
     48 
     49         return new Rect(/*left*/0, /*top*/0, size.getWidth(), size.getHeight());
     50     }
     51 
     52     /**
     53      * Create a {@link Rect} from a {@code RectF} by creating a new rectangle with
     54      * each corner (left, top, right, bottom) rounded towards the nearest integer bounding box.
     55      *
     56      * <p>In particular (left, top) is floored, and (right, bottom) is ceiled.</p>
     57      *
     58      * @param size a non-{@code null} rect
     59      *
     60      * @return a {@code non-null} rectangle
     61      *
     62      * @throws NullPointerException if {@code rect} was {@code null}
     63      */
     64     public static Rect createRect(RectF rect) {
     65         checkNotNull(rect, "rect must not be null");
     66 
     67         Rect r = new Rect();
     68         rect.roundOut(r);
     69 
     70         return r;
     71     }
     72 
     73     /**
     74      * Map the rectangle in {@code rect} with the transform in {@code transform} into
     75      * a new rectangle, with each corner (left, top, right, bottom) rounded towards the nearest
     76      * integer bounding box.
     77      *
     78      * <p>None of the arguments are mutated.</p>
     79      *
     80      * @param transform a non-{@code null} transformation matrix
     81      * @param rect a non-{@code null} rectangle
     82      * @return a new rectangle that was transformed by {@code transform}
     83      *
     84      * @throws NullPointerException if any of the args were {@code null}
     85      */
     86     public static Rect mapRect(Matrix transform, Rect rect) {
     87         checkNotNull(transform, "transform must not be null");
     88         checkNotNull(rect, "rect must not be null");
     89 
     90         RectF rectF = new RectF(rect);
     91         transform.mapRect(rectF);
     92         return createRect(rectF);
     93     }
     94 
     95     /**
     96      * Create a {@link Size} from a {@code Rect} by creating a new size whose width
     97      * and height are the same as the rectangle's width and heights.
     98      *
     99      * @param rect a non-{@code null} rectangle
    100      *
    101      * @return a {@code non-null} size
    102      *
    103      * @throws NullPointerException if {@code rect} was {@code null}
    104      */
    105     public static Size createSize(Rect rect) {
    106         checkNotNull(rect, "rect must not be null");
    107 
    108         return new Size(rect.width(), rect.height());
    109     }
    110 
    111     /**
    112      * Create a {@link Rational} value by approximating the float value as a rational.
    113      *
    114      * <p>Floating points too large to be represented as an integer will be converted to
    115      * to {@link Integer#MAX_VALUE}; floating points too small to be represented as an integer
    116      * will be converted to {@link Integer#MIN_VALUE}.</p>
    117      *
    118      * @param value a floating point value
    119      * @return the rational representation of the float
    120      */
    121     public static Rational createRational(float value) {
    122         if (Float.isNaN(value)) {
    123             return Rational.NaN;
    124         } else if (value == Float.POSITIVE_INFINITY) {
    125             return Rational.POSITIVE_INFINITY;
    126         } else if (value == Float.NEGATIVE_INFINITY) {
    127             return Rational.NEGATIVE_INFINITY;
    128         } else if (value == 0.0f) {
    129             return Rational.ZERO;
    130         }
    131 
    132         // normal finite value: approximate it
    133 
    134         /*
    135          * Start out trying to approximate with denominator = 1million,
    136          * but if the numerator doesn't fit into an Int then keep making the denominator
    137          * smaller until it does.
    138          */
    139         int den = RATIONAL_DENOMINATOR;
    140         float numF;
    141         do {
    142             numF = value * den;
    143 
    144             if ((numF > Integer.MIN_VALUE && numF < Integer.MAX_VALUE) || (den == 1)) {
    145                 break;
    146             }
    147 
    148             den /= 10;
    149         } while (true);
    150 
    151         /*
    152          *  By float -> int narrowing conversion in JLS 5.1.3, this will automatically become
    153          *  MIN_VALUE or MAX_VALUE if numF is too small/large to be represented by an integer
    154          */
    155         int num = (int) numF;
    156 
    157         return new Rational(num, den);
    158      }
    159 
    160     /**
    161      * Convert an integral rectangle ({@code source}) to a floating point rectangle
    162      * ({@code destination}) in-place.
    163      *
    164      * @param source the originating integer rectangle will be read from here
    165      * @param destination the resulting floating point rectangle will be written out to here
    166      *
    167      * @throws NullPointerException if {@code rect} was {@code null}
    168      */
    169     public static void convertRectF(Rect source, RectF destination) {
    170         checkNotNull(source, "source must not be null");
    171         checkNotNull(destination, "destination must not be null");
    172 
    173         destination.left = source.left;
    174         destination.right = source.right;
    175         destination.bottom = source.bottom;
    176         destination.top = source.top;
    177     }
    178 
    179     /**
    180      * Return the value set by the key, or the {@code defaultValue} if no value was set.
    181      *
    182      * @throws NullPointerException if any of the args were {@code null}
    183      */
    184     public static <T> T getOrDefault(CaptureRequest r, CaptureRequest.Key<T> key, T defaultValue) {
    185         checkNotNull(r, "r must not be null");
    186         checkNotNull(key, "key must not be null");
    187         checkNotNull(defaultValue, "defaultValue must not be null");
    188 
    189         T value = r.get(key);
    190         if (value == null) {
    191             return defaultValue;
    192         } else {
    193             return value;
    194         }
    195     }
    196 
    197     private ParamsUtils() {
    198         throw new AssertionError();
    199     }
    200 }
    201