1df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin/* 2df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * Copyright (C) 2014 The Android Open Source Project 3df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 4df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License"); 5df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * you may not use this file except in compliance with the License. 6df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * You may obtain a copy of the License at 7df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 8df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * http://www.apache.org/licenses/LICENSE-2.0 9df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 10df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * Unless required by applicable law or agreed to in writing, software 11df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS, 12df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * See the License for the specific language governing permissions and 14df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * limitations under the License. 15df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin */ 16df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 17df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkinpackage android.hardware.camera2.utils; 18df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 197ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkinimport android.graphics.Matrix; 20df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkinimport android.graphics.Rect; 21df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkinimport android.graphics.RectF; 2283d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkinimport android.hardware.camera2.CaptureRequest; 233e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkinimport android.util.Rational; 24df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkinimport android.util.Size; 25df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 26df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkinimport static com.android.internal.util.Preconditions.*; 27df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 28df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin/** 29df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * Various assortment of params utilities. 30df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin */ 31df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkinpublic class ParamsUtils { 32df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 333e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin /** Arbitrary denominator used to estimate floats as rationals */ 343e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin private static final int RATIONAL_DENOMINATOR = 1000000; // 1million 353e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin 36df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin /** 37df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * Create a {@link Rect} from a {@code Size} by creating a new rectangle with 38df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * left, top = {@code (0, 0)} and right, bottom = {@code (width, height)} 39df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 40df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @param size a non-{@code null} size 41df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 42df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @return a {@code non-null} rectangle 43df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 44df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @throws NullPointerException if {@code size} was {@code null} 45df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin */ 46df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin public static Rect createRect(Size size) { 47df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin checkNotNull(size, "size must not be null"); 48df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 49df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin return new Rect(/*left*/0, /*top*/0, size.getWidth(), size.getHeight()); 50df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin } 51df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 52df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin /** 53df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * Create a {@link Rect} from a {@code RectF} by creating a new rectangle with 547ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * each corner (left, top, right, bottom) rounded towards the nearest integer bounding box. 557ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * 567ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * <p>In particular (left, top) is floored, and (right, bottom) is ceiled.</p> 57df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 58df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @param size a non-{@code null} rect 59df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 60df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @return a {@code non-null} rectangle 61df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 62df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @throws NullPointerException if {@code rect} was {@code null} 63df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin */ 64df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin public static Rect createRect(RectF rect) { 65df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin checkNotNull(rect, "rect must not be null"); 66df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 67df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin Rect r = new Rect(); 687ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin rect.roundOut(r); 69df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 70df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin return r; 71df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin } 72df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 73df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin /** 747ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * Map the rectangle in {@code rect} with the transform in {@code transform} into 757ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * a new rectangle, with each corner (left, top, right, bottom) rounded towards the nearest 767ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * integer bounding box. 777ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * 787ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * <p>None of the arguments are mutated.</p> 797ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * 807ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * @param transform a non-{@code null} transformation matrix 817ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * @param rect a non-{@code null} rectangle 827ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * @return a new rectangle that was transformed by {@code transform} 837ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * 847ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * @throws NullPointerException if any of the args were {@code null} 857ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin */ 867ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin public static Rect mapRect(Matrix transform, Rect rect) { 877ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin checkNotNull(transform, "transform must not be null"); 887ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin checkNotNull(rect, "rect must not be null"); 897ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin 907ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin RectF rectF = new RectF(rect); 917ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin transform.mapRect(rectF); 927ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin return createRect(rectF); 937ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin } 947ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin 957ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin /** 96df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * Create a {@link Size} from a {@code Rect} by creating a new size whose width 97df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * and height are the same as the rectangle's width and heights. 98df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 99df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @param rect a non-{@code null} rectangle 100df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 101df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @return a {@code non-null} size 102df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 103df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @throws NullPointerException if {@code rect} was {@code null} 104df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin */ 105df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin public static Size createSize(Rect rect) { 106df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin checkNotNull(rect, "rect must not be null"); 107df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 108df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin return new Size(rect.width(), rect.height()); 109df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin } 110df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 111df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin /** 1123e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * Create a {@link Rational} value by approximating the float value as a rational. 1133e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * 1143e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * <p>Floating points too large to be represented as an integer will be converted to 1153e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * to {@link Integer#MAX_VALUE}; floating points too small to be represented as an integer 1163e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * will be converted to {@link Integer#MIN_VALUE}.</p> 1173e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * 1183e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * @param value a floating point value 1193e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * @return the rational representation of the float 1203e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin */ 1213e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin public static Rational createRational(float value) { 1223e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin if (Float.isNaN(value)) { 1233e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin return Rational.NaN; 1243e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin } else if (value == Float.POSITIVE_INFINITY) { 1253e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin return Rational.POSITIVE_INFINITY; 1263e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin } else if (value == Float.NEGATIVE_INFINITY) { 1273e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin return Rational.NEGATIVE_INFINITY; 1283e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin } else if (value == 0.0f) { 1293e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin return Rational.ZERO; 1303e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin } 1313e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin 1323e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin // normal finite value: approximate it 1333e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin 1343e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin /* 1353e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * Start out trying to approximate with denominator = 1million, 1363e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * but if the numerator doesn't fit into an Int then keep making the denominator 1373e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * smaller until it does. 1383e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin */ 1393e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin int den = RATIONAL_DENOMINATOR; 1403e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin float numF; 1413e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin do { 1423e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin numF = value * den; 1433e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin 1443e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin if ((numF > Integer.MIN_VALUE && numF < Integer.MAX_VALUE) || (den == 1)) { 1453e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin break; 1463e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin } 1473e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin 1483e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin den /= 10; 1493e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin } while (true); 1503e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin 1513e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin /* 1523e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * By float -> int narrowing conversion in JLS 5.1.3, this will automatically become 1533e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin * MIN_VALUE or MAX_VALUE if numF is too small/large to be represented by an integer 1543e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin */ 1553e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin int num = (int) numF; 1563e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin 1573e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin return new Rational(num, den); 1583e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin } 1593e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin 1603e280b4bb23be4e5e66ea6381fd63c74fdbd927eIgor Murashkin /** 1617ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * Convert an integral rectangle ({@code source}) to a floating point rectangle 162df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * ({@code destination}) in-place. 163df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 1647ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin * @param source the originating integer rectangle will be read from here 165df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @param destination the resulting floating point rectangle will be written out to here 166df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * 167df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin * @throws NullPointerException if {@code rect} was {@code null} 168df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin */ 169df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin public static void convertRectF(Rect source, RectF destination) { 170df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin checkNotNull(source, "source must not be null"); 171df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin checkNotNull(destination, "destination must not be null"); 172df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 173df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin destination.left = source.left; 174df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin destination.right = source.right; 175df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin destination.bottom = source.bottom; 176df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin destination.top = source.top; 177df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin } 178df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin 17983d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin /** 18083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * Return the value set by the key, or the {@code defaultValue} if no value was set. 18183d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * 18283d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin * @throws NullPointerException if any of the args were {@code null} 18383d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin */ 18483d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin public static <T> T getOrDefault(CaptureRequest r, CaptureRequest.Key<T> key, T defaultValue) { 18583d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin checkNotNull(r, "r must not be null"); 18683d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin checkNotNull(key, "key must not be null"); 18783d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin checkNotNull(defaultValue, "defaultValue must not be null"); 18883d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 18983d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin T value = r.get(key); 19083d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin if (value == null) { 19183d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin return defaultValue; 19283d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } else { 19383d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin return value; 19483d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } 19583d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin } 19683d8639e901a24e59c9886dd6910faf3ba7adae1Igor Murashkin 197df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin private ParamsUtils() { 198df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin throw new AssertionError(); 199df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin } 200df6242e374b81e802a38cb891477f05d3e4b3cbcIgor Murashkin} 201