RggbChannelVector.java revision 72f9f0a96e4476ef231d5001cb30521ad4ce5b1e
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 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 */
24public 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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
167    public boolean equals(final Object obj) {
168        if (obj == null) {
169            return false;
170        }
171        if (this == obj) {
172            return true;
173        }
174        if (obj instanceof RggbChannelVector) {
175            final RggbChannelVector other = (RggbChannelVector) obj;
176            return mRed == other.mRed &&
177                    mGreenEven == other.mGreenEven &&
178                    mGreenOdd == other.mGreenOdd &&
179                    mBlue == other.mBlue;
180        }
181        return false;
182    }
183
184    /**
185     * {@inheritDoc}
186     */
187    @Override
188    public int hashCode() {
189        return Float.floatToIntBits(mRed) ^
190                Float.floatToIntBits(mGreenEven) ^
191                Float.floatToIntBits(mGreenOdd) ^
192                Float.floatToIntBits(mBlue);
193    }
194
195    private final float mRed;
196    private final float mGreenEven;
197    private final float mGreenOdd;
198    private final float mBlue;
199}
200