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 */ createRect(Size size)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 */ createRect(RectF rect)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 */ mapRect(Matrix transform, Rect rect)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 */ createSize(Rect rect)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 */ createRational(float value)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 */ convertRectF(Rect source, RectF destination)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 */ getOrDefault(CaptureRequest r, CaptureRequest.Key<T> key, T defaultValue)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 ParamsUtils()197 private ParamsUtils() { 198 throw new AssertionError(); 199 } 200 } 201