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.params; 18 19 import static com.android.internal.util.Preconditions.*; 20 21 /** 22 * Immutable class to store a 4-element vector of floats indexable by a bayer RAW 2x2 pixel block. 23 */ 24 public final class RggbChannelVector { 25 /** 26 * The number of color channels in this vector. 27 */ 28 public static final int COUNT = 4; 29 30 /** Red color channel in a bayer Raw pattern. */ 31 public static final int RED = 0; 32 33 /** Green color channel in a bayer Raw pattern used by the even rows. */ 34 public static final int GREEN_EVEN = 1; 35 36 /** Green color channel in a bayer Raw pattern used by the odd rows. */ 37 public static final int GREEN_ODD = 2; 38 39 /** Blue color channel in a bayer Raw pattern. */ 40 public static final int BLUE = 3; 41 42 /** 43 * Create a new {@link RggbChannelVector} from an RGGB 2x2 pixel. 44 * 45 * <p>All pixel values are considered normalized within {@code [0.0f, 1.0f]} 46 * (i.e. {@code 1.0f} could be linearized to {@code 255} if converting to a 47 * non-floating point pixel representation).</p> 48 * 49 * <p>All arguments must be finite; NaN and infinity is not allowed.</p> 50 * 51 * @param red red pixel 52 * @param greenEven green pixel (even row) 53 * @param greenOdd green pixel (odd row) 54 * @param blue blue pixel 55 * 56 * @throws IllegalArgumentException if any of the arguments were not finite 57 */ RggbChannelVector(final float red, final float greenEven, final float greenOdd, final float blue)58 public RggbChannelVector(final float red, final float greenEven, final float greenOdd, 59 final float blue) { 60 mRed = checkArgumentFinite(red, "red"); 61 mGreenEven = checkArgumentFinite(greenEven, "greenEven"); 62 mGreenOdd = checkArgumentFinite(greenOdd, "greenOdd"); 63 mBlue = checkArgumentFinite(blue, "blue"); 64 } 65 66 /** 67 * Get the red component. 68 * 69 * @return a floating point value (guaranteed to be finite) 70 */ getRed()71 public final float getRed() { 72 return mRed; 73 } 74 75 /** 76 * Get the green (even rows) component. 77 * 78 * @return a floating point value (guaranteed to be finite) 79 */ getGreenEven()80 public float getGreenEven() { 81 return mGreenEven; 82 } 83 84 /** 85 * Get the green (odd rows) component. 86 * 87 * @return a floating point value (guaranteed to be finite) 88 */ getGreenOdd()89 public float getGreenOdd() { 90 return mGreenOdd; 91 } 92 93 /** 94 * Get the blue component. 95 * 96 * @return a floating point value (guaranteed to be finite) 97 */ getBlue()98 public float getBlue() { 99 return mBlue; 100 } 101 102 /** 103 * Get the component by the color channel index. 104 * 105 * <p>{@code colorChannel} must be one of {@link #RED}, {@link #GREEN_EVEN}, {@link #GREEN_ODD}, 106 * {@link #BLUE}.</p> 107 * 108 * @param colorChannel greater or equal to {@code 0} and less than {@link #COUNT} 109 * @return a floating point value (guaranteed to be finite) 110 * 111 * @throws IllegalArgumentException if {@code colorChannel} was out of range 112 */ getComponent(final int colorChannel)113 public float getComponent(final int colorChannel) { 114 if (colorChannel < 0 || colorChannel >= COUNT) { 115 throw new IllegalArgumentException("Color channel out of range"); 116 } 117 118 switch (colorChannel) { 119 case RED: 120 return mRed; 121 case GREEN_EVEN: 122 return mGreenEven; 123 case GREEN_ODD: 124 return mGreenOdd; 125 case BLUE: 126 return mBlue; 127 default: 128 throw new AssertionError("Unhandled case " + colorChannel); 129 } 130 } 131 132 /** 133 * Copy the vector into the destination in the order {@code [R, Geven, Godd, B]}. 134 * 135 * @param destination 136 * an array big enough to hold at least {@value #COUNT} elements after the 137 * {@code offset} 138 * @param offset 139 * a non-negative offset into the array 140 * 141 * @throws NullPointerException 142 * If {@code destination} was {@code null} 143 * @throws ArrayIndexOutOfBoundsException 144 * If there's not enough room to write the elements at the specified destination and 145 * offset. 146 */ copyTo(final float[] destination, final int offset)147 public void copyTo(final float[] destination, final int offset) { 148 checkNotNull(destination, "destination must not be null"); 149 if (destination.length - offset < COUNT) { 150 throw new ArrayIndexOutOfBoundsException("destination too small to fit elements"); 151 } 152 153 destination[offset + RED] = mRed; 154 destination[offset + GREEN_EVEN] = mGreenEven; 155 destination[offset + GREEN_ODD] = mGreenOdd; 156 destination[offset + BLUE] = mBlue; 157 } 158 159 /** 160 * Check if this {@link RggbChannelVector} is equal to another {@link RggbChannelVector}. 161 * 162 * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p> 163 * 164 * @return {@code true} if the objects were equal, {@code false} otherwise 165 */ 166 @Override equals(final Object obj)167 public boolean equals(final Object obj) { 168 if (obj == null) { 169 return false; 170 } else if (this == obj) { 171 return true; 172 } else if (obj instanceof RggbChannelVector) { 173 final RggbChannelVector other = (RggbChannelVector) obj; 174 return mRed == other.mRed && 175 mGreenEven == other.mGreenEven && 176 mGreenOdd == other.mGreenOdd && 177 mBlue == other.mBlue; 178 } 179 return false; 180 } 181 182 /** 183 * {@inheritDoc} 184 */ 185 @Override hashCode()186 public int hashCode() { 187 return Float.floatToIntBits(mRed) ^ 188 Float.floatToIntBits(mGreenEven) ^ 189 Float.floatToIntBits(mGreenOdd) ^ 190 Float.floatToIntBits(mBlue); 191 } 192 193 /** 194 * Return the RggbChannelVector as a string representation. 195 * 196 * <p> {@code "RggbChannelVector{R:%f, G_even:%f, G_odd:%f, B:%f}"}, where each 197 * {@code %f} respectively represents one of the the four color channels. </p> 198 * 199 * @return string representation of {@link RggbChannelVector} 200 */ 201 @Override toString()202 public String toString() { 203 return String.format("RggbChannelVector%s", toShortString()); 204 } 205 206 /** 207 * Return the RggbChannelVector as a string in compact form. 208 * 209 * <p> {@code "{R:%f, G_even:%f, G_odd:%f, B:%f}"}, where each {@code %f} 210 * respectively represents one of the the four color channels. </p> 211 * 212 * @return compact string representation of {@link RggbChannelVector} 213 */ toShortString()214 private String toShortString() { 215 return String.format("{R:%f, G_even:%f, G_odd:%f, B:%f}", 216 mRed, mGreenEven, mGreenOdd, mBlue); 217 } 218 219 private final float mRed; 220 private final float mGreenEven; 221 private final float mGreenOdd; 222 private final float mBlue; 223 } 224