MeteringRectangle.java revision 97f1c854993a65b2c700426a1e3a83b23ea65337
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 17package android.hardware.camera2.params; 18 19import android.util.Size; 20import static com.android.internal.util.Preconditions.*; 21 22import android.graphics.Point; 23import android.graphics.Rect; 24import android.hardware.camera2.CameraCharacteristics; 25import android.hardware.camera2.CaptureRequest; 26import android.hardware.camera2.utils.HashCodeHelpers; 27 28/** 29 * An immutable class to represent a rectangle {@code (x, y, width, height)} with an additional 30 * weight component. 31 * <p> 32 * The rectangle is defined to be inclusive of the specified coordinates. 33 * </p> 34 * <p> 35 * When used with a {@link CaptureRequest}, the coordinate system is based on the active pixel 36 * array, with {@code (0,0)} being the top-left pixel in the 37 * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE active pixel array}, and 38 * {@code (android.sensor.info.activeArraySize.width - 1, 39 * android.sensor.info.activeArraySize.height - 1)} being the bottom-right pixel in the active pixel 40 * array. 41 * </p> 42 * <p> 43 * The weight must range from {@value #METERING_WEIGHT_MIN} to {@value #METERING_WEIGHT_MAX} 44 * inclusively, and represents a weight for every pixel in the area. This means that a large 45 * metering area with the same weight as a smaller area will have more effect in the metering 46 * result. Metering areas can partially overlap and the camera device will add the weights in the 47 * overlap rectangle. 48 * </p> 49 * <p> 50 * If all rectangles have 0 weight, then no specific metering area needs to be used by the camera 51 * device. If the metering rectangle is outside the used android.scaler.cropRegion returned in 52 * capture result metadata, the camera device will ignore the sections outside the rectangle and 53 * output the used sections in the result metadata. 54 * </p> 55 */ 56public final class MeteringRectangle { 57 /** 58 * The minimum value of valid metering weight. 59 */ 60 public static final int METERING_WEIGHT_MIN = 0; 61 62 /** 63 * The maximum value of valid metering weight. 64 */ 65 public static final int METERING_WEIGHT_MAX = 1000; 66 67 /** 68 * Weights set to this value will cause the camera device to ignore this rectangle. 69 * If all metering rectangles are weighed with 0, the camera device will choose its own metering 70 * rectangles. 71 */ 72 public static final int METERING_WEIGHT_DONT_CARE = 0; 73 74 private final int mX; 75 private final int mY; 76 private final int mWidth; 77 private final int mHeight; 78 private final int mWeight; 79 80 /** 81 * Create a new metering rectangle. 82 * 83 * @param x coordinate >= 0 84 * @param y coordinate >= 0 85 * @param width width >= 0 86 * @param height height >= 0 87 * @param meteringWeight weight between {@value #METERING_WEIGHT_MIN} and 88 * {@value #METERING_WEIGHT_MAX} inclusively 89 * @throws IllegalArgumentException if any of the parameters were negative 90 */ 91 public MeteringRectangle(int x, int y, int width, int height, int meteringWeight) { 92 mX = checkArgumentNonnegative(x, "x must be nonnegative"); 93 mY = checkArgumentNonnegative(y, "y must be nonnegative"); 94 mWidth = checkArgumentNonnegative(width, "width must be nonnegative"); 95 mHeight = checkArgumentNonnegative(height, "height must be nonnegative"); 96 mWeight = checkArgumentInRange( 97 meteringWeight, METERING_WEIGHT_MIN, METERING_WEIGHT_MAX, "meteringWeight"); 98 } 99 100 /** 101 * Create a new metering rectangle. 102 * 103 * @param xy a non-{@code null} {@link Point} with both x,y >= 0 104 * @param dimensions a non-{@code null} {@link android.util.Size Size} with width, height >= 0 105 * @param meteringWeight weight >= 0 106 * 107 * @throws IllegalArgumentException if any of the parameters were negative 108 * @throws NullPointerException if any of the arguments were null 109 */ 110 public MeteringRectangle(Point xy, Size dimensions, int meteringWeight) { 111 checkNotNull(xy, "xy must not be null"); 112 checkNotNull(dimensions, "dimensions must not be null"); 113 114 mX = checkArgumentNonnegative(xy.x, "x must be nonnegative"); 115 mY = checkArgumentNonnegative(xy.y, "y must be nonnegative"); 116 mWidth = checkArgumentNonnegative(dimensions.getWidth(), "width must be nonnegative"); 117 mHeight = checkArgumentNonnegative(dimensions.getHeight(), "height must be nonnegative"); 118 mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative"); 119 } 120 121 /** 122 * Create a new metering rectangle. 123 * 124 * @param rect a non-{@code null} rectangle with all x,y,w,h dimensions >= 0 125 * @param meteringWeight weight >= 0 126 * 127 * @throws IllegalArgumentException if any of the parameters were negative 128 * @throws NullPointerException if any of the arguments were null 129 */ 130 public MeteringRectangle(Rect rect, int meteringWeight) { 131 checkNotNull(rect, "rect must not be null"); 132 133 mX = checkArgumentNonnegative(rect.left, "rect.left must be nonnegative"); 134 mY = checkArgumentNonnegative(rect.top, "rect.top must be nonnegative"); 135 mWidth = checkArgumentNonnegative(rect.width(), "rect.width must be nonnegative"); 136 mHeight = checkArgumentNonnegative(rect.height(), "rect.height must be nonnegative"); 137 mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative"); 138 } 139 140 /** 141 * Return the X coordinate of the left side of the rectangle. 142 * 143 * @return x coordinate >= 0 144 */ 145 public int getX() { 146 return mX; 147 } 148 149 /** 150 * Return the Y coordinate of the upper side of the rectangle. 151 * 152 * @return y coordinate >= 0 153 */ 154 public int getY() { 155 return mY; 156 } 157 158 /** 159 * Return the width of the rectangle. 160 * 161 * @return width >= 0 162 */ 163 public int getWidth() { 164 return mWidth; 165 } 166 167 /** 168 * Return the height of the rectangle. 169 * 170 * @return height >= 0 171 */ 172 public int getHeight() { 173 return mHeight; 174 } 175 176 /** 177 * Return the metering weight of the rectangle. 178 * 179 * @return weight >= 0 180 */ 181 public int getMeteringWeight() { 182 return mWeight; 183 } 184 185 /** 186 * Convenience method to create the upper-left (X,Y) coordinate as a {@link Point}. 187 * 188 * @return {@code (x,y)} point with both x,y >= 0 189 */ 190 public Point getUpperLeftPoint() { 191 return new Point(mX, mY); 192 } 193 194 /** 195 * Convenience method to create the size from this metering rectangle. 196 * 197 * <p>This strips away the X,Y,weight from the rectangle.</p> 198 * 199 * @return a Size with non-negative width and height 200 */ 201 public Size getSize() { 202 return new Size(mWidth, mHeight); 203 } 204 205 /** 206 * Convenience method to create a {@link Rect} from this metering rectangle. 207 * 208 * <p>This strips away the weight from the rectangle.</p> 209 * 210 * @return a {@link Rect} with non-negative x1, y1, x2, y2 211 */ 212 public Rect getRect() { 213 return new Rect(mX, mY, mX + mWidth, mY + mHeight); 214 } 215 216 /** 217 * {@inheritDoc} 218 */ 219 @Override 220 public boolean equals(final Object other) { 221 return other instanceof MeteringRectangle && equals((MeteringRectangle)other); 222 } 223 224 /** 225 * Compare two metering rectangles to see if they are equal. 226 * 227 * Two weighted rectangles are only considered equal if each of their components 228 * (x, y, width, height, weight) is respectively equal. 229 * 230 * @param other Another MeteringRectangle 231 * 232 * @return {@code true} if the metering rectangles are equal, {@code false} otherwise 233 */ 234 public boolean equals(final MeteringRectangle other) { 235 if (other == null) { 236 return false; 237 } 238 239 return (mX == other.mX 240 && mY == other.mY 241 && mWidth == other.mWidth 242 && mHeight == other.mHeight 243 && mWeight == other.mWeight); 244 } 245 246 /** 247 * {@inheritDoc} 248 */ 249 @Override 250 public int hashCode() { 251 return HashCodeHelpers.hashCode(mX, mY, mWidth, mHeight, mWeight); 252 } 253} 254