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