/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware.camera2.params; import static com.android.internal.util.Preconditions.*; /** * Immutable class to store a 4-element vector of floats indexable by a bayer RAW 2x2 pixel block. */ public final class RggbChannelVector { /** * The number of color channels in this vector. */ public static final int COUNT = 4; /** Red color channel in a bayer Raw pattern. */ public static final int RED = 0; /** Green color channel in a bayer Raw pattern used by the even rows. */ public static final int GREEN_EVEN = 1; /** Green color channel in a bayer Raw pattern used by the odd rows. */ public static final int GREEN_ODD = 2; /** Blue color channel in a bayer Raw pattern. */ public static final int BLUE = 3; /** * Create a new {@link RggbChannelVector} from an RGGB 2x2 pixel. * *

All pixel values are considered normalized within {@code [0.0f, 1.0f]} * (i.e. {@code 1.0f} could be linearized to {@code 255} if converting to a * non-floating point pixel representation).

* *

All arguments must be finite; NaN and infinity is not allowed.

* * @param red red pixel * @param greenEven green pixel (even row) * @param greenOdd green pixel (odd row) * @param blue blue pixel * * @throws IllegalArgumentException if any of the arguments were not finite */ public RggbChannelVector(final float red, final float greenEven, final float greenOdd, final float blue) { mRed = checkArgumentFinite(red, "red"); mGreenEven = checkArgumentFinite(greenEven, "greenEven"); mGreenOdd = checkArgumentFinite(greenOdd, "greenOdd"); mBlue = checkArgumentFinite(blue, "blue"); } /** * Get the red component. * * @return a floating point value (guaranteed to be finite) */ public final float getRed() { return mRed; } /** * Get the green (even rows) component. * * @return a floating point value (guaranteed to be finite) */ public float getGreenEven() { return mGreenEven; } /** * Get the green (odd rows) component. * * @return a floating point value (guaranteed to be finite) */ public float getGreenOdd() { return mGreenOdd; } /** * Get the blue component. * * @return a floating point value (guaranteed to be finite) */ public float getBlue() { return mBlue; } /** * Get the component by the color channel index. * *

{@code colorChannel} must be one of {@link #RED}, {@link #GREEN_EVEN}, {@link #GREEN_ODD}, * {@link #BLUE}.

* * @param colorChannel greater or equal to {@code 0} and less than {@link #COUNT} * @return a floating point value (guaranteed to be finite) * * @throws IllegalArgumentException if {@code colorChannel} was out of range */ public float getComponent(final int colorChannel) { if (colorChannel < 0 || colorChannel >= COUNT) { throw new IllegalArgumentException("Color channel out of range"); } switch (colorChannel) { case RED: return mRed; case GREEN_EVEN: return mGreenEven; case GREEN_ODD: return mGreenOdd; case BLUE: return mBlue; default: throw new AssertionError("Unhandled case " + colorChannel); } } /** * Copy the vector into the destination in the order {@code [R, Geven, Godd, B]}. * * @param destination * an array big enough to hold at least {@value #COUNT} elements after the * {@code offset} * @param offset * a non-negative offset into the array * * @throws NullPointerException * If {@code destination} was {@code null} * @throws ArrayIndexOutOfBoundsException * If there's not enough room to write the elements at the specified destination and * offset. */ public void copyTo(final float[] destination, final int offset) { checkNotNull(destination, "destination must not be null"); if (destination.length - offset < COUNT) { throw new ArrayIndexOutOfBoundsException("destination too small to fit elements"); } destination[offset + RED] = mRed; destination[offset + GREEN_EVEN] = mGreenEven; destination[offset + GREEN_ODD] = mGreenOdd; destination[offset + BLUE] = mBlue; } /** * Check if this {@link RggbChannelVector} is equal to another {@link RggbChannelVector}. * *

Two vectors are only equal if and only if each of the respective elements is equal.

* * @return {@code true} if the objects were equal, {@code false} otherwise */ @Override public boolean equals(final Object obj) { if (obj == null) { return false; } else if (this == obj) { return true; } else if (obj instanceof RggbChannelVector) { final RggbChannelVector other = (RggbChannelVector) obj; return mRed == other.mRed && mGreenEven == other.mGreenEven && mGreenOdd == other.mGreenOdd && mBlue == other.mBlue; } return false; } /** * {@inheritDoc} */ @Override public int hashCode() { return Float.floatToIntBits(mRed) ^ Float.floatToIntBits(mGreenEven) ^ Float.floatToIntBits(mGreenOdd) ^ Float.floatToIntBits(mBlue); } /** * Return the RggbChannelVector as a string representation. * *

{@code "RggbChannelVector{R:%f, G_even:%f, G_odd:%f, B:%f}"}, where each * {@code %f} respectively represents one of the the four color channels.

* * @return string representation of {@link RggbChannelVector} */ @Override public String toString() { return String.format("RggbChannelVector%s", toShortString()); } /** * Return the RggbChannelVector as a string in compact form. * *

{@code "{R:%f, G_even:%f, G_odd:%f, B:%f}"}, where each {@code %f} * respectively represents one of the the four color channels.

* * @return compact string representation of {@link RggbChannelVector} */ private String toShortString() { return String.format("{R:%f, G_even:%f, G_odd:%f, B:%f}", mRed, mGreenEven, mGreenOdd, mBlue); } private final float mRed; private final float mGreenEven; private final float mGreenOdd; private final float mBlue; }