blob: e08ec55db9bcdc1bf2e85ff6e8eefd9b2481a0bd [file] [log] [blame]
/*
* 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.
*
* <p>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).</p>
*
* <p>All arguments must be finite; NaN and infinity is not allowed.</p>
*
* @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.
*
* <p>{@code colorChannel} must be one of {@link #RED}, {@link #GREEN_EVEN}, {@link #GREEN_ODD},
* {@link #BLUE}.</p>
*
* @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}.
*
* <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
*
* @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.
*
* <p> {@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. </p>
*
* @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.
*
* <p> {@code "{R:%f, G_even:%f, G_odd:%f, B:%f}"}, where each {@code %f}
* respectively represents one of the the four color channels. </p>
*
* @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;
}