FileDocCategorySizeDatePackage
TonemapCurve.javaAPI DocAndroid 5.1 API13117Thu Mar 12 22:22:10 GMT 2015android.hardware.camera2.params

TonemapCurve

public final class TonemapCurve extends Object
Immutable class for describing a {@code 2 x M x 3} tonemap curve of floats.

This defines red, green, and blue curves that the {@link CameraDevice} will use as the tonemapping/contrast/gamma curve when {@link CaptureRequest#TONEMAP_MODE} is set to {@link CameraMetadata#TONEMAP_MODE_CONTRAST_CURVE}.

The total number of points {@code (Pin, Pout)} for each color channel can be no more than {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS}.

The coordinate system for each point is within the inclusive range [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].

see
CaptureRequest#TONEMAP_CURVE_BLUE
see
CaptureRequest#TONEMAP_CURVE_GREEN
see
CaptureRequest#TONEMAP_CURVE_RED
see
CameraMetadata#TONEMAP_MODE_CONTRAST_CURVE
see
CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS

Fields Summary
public static final float
LEVEL_BLACK
Lower bound tonemap value corresponding to pure black for a single color channel.
public static final float
LEVEL_WHITE
Upper bound tonemap value corresponding to a pure white for a single color channel.
public static final int
POINT_SIZE
Number of elements in a {@code (Pin, Pout)} point;
public static final int
CHANNEL_RED
Index of the red color channel curve.
public static final int
CHANNEL_GREEN
Index of the green color channel curve.
public static final int
CHANNEL_BLUE
Index of the blue color channel curve.
private static final int
OFFSET_POINT_IN
private static final int
OFFSET_POINT_OUT
private static final int
TONEMAP_MIN_CURVE_POINTS
private static final int
MIN_CURVE_LENGTH
private final float[]
mRed
private final float[]
mGreen
private final float[]
mBlue
private int
mHashCode
private boolean
mHashCalculated
Constructors Summary
public TonemapCurve(float[] red, float[] green, float[] blue)
Create a new immutable TonemapCurve instance.

Values are stored as a contiguous array of {@code (Pin, Pout)} points.

All parameters may have independent length but should have at most {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS} * {@value #POINT_SIZE} elements and at least 2 * {@value #POINT_SIZE} elements.

All sub-elements must be in the inclusive range of [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].

This constructor copies the array contents and does not retain ownership of the array.

param
red An array of elements whose length is divisible by {@value #POINT_SIZE}
param
green An array of elements whose length is divisible by {@value #POINT_SIZE}
param
blue An array of elements whose length is divisible by {@value #POINT_SIZE}
throws
IllegalArgumentException if any of input array length is invalid, or if any of the elements in the array are not in the range of [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}]
throws
NullPointerException if any of the parameters are {@code null}


                                                                                                                                                                                                         
           
        // TODO: maxCurvePoints check?

        checkNotNull(red, "red must not be null");
        checkNotNull(green, "green must not be null");
        checkNotNull(blue, "blue must not be null");

        checkArgumentArrayLengthDivisibleBy(red, POINT_SIZE, "red");
        checkArgumentArrayLengthDivisibleBy(green, POINT_SIZE, "green");
        checkArgumentArrayLengthDivisibleBy(blue, POINT_SIZE, "blue");

        checkArgumentArrayLengthNoLessThan(red, MIN_CURVE_LENGTH, "red");
        checkArgumentArrayLengthNoLessThan(green, MIN_CURVE_LENGTH, "green");
        checkArgumentArrayLengthNoLessThan(blue, MIN_CURVE_LENGTH, "blue");

        checkArrayElementsInRange(red, LEVEL_BLACK, LEVEL_WHITE, "red");
        checkArrayElementsInRange(green, LEVEL_BLACK, LEVEL_WHITE, "green");
        checkArrayElementsInRange(blue, LEVEL_BLACK, LEVEL_WHITE, "blue");

        mRed = Arrays.copyOf(red, red.length);
        mGreen = Arrays.copyOf(green, green.length);
        mBlue = Arrays.copyOf(blue, blue.length);
    
Methods Summary
private static voidcheckArgumentArrayLengthDivisibleBy(float[] array, int divisible, java.lang.String arrayName)

        if (array.length % divisible != 0) {
            throw new IllegalArgumentException(arrayName + " size must be divisible by "
                    + divisible);
        }
    
private static voidcheckArgumentArrayLengthNoLessThan(float[] array, int minLength, java.lang.String arrayName)

        if (array.length < minLength) {
            throw new IllegalArgumentException(arrayName + " size must be at least "
                    + minLength);
        }
    
private static intcheckArgumentColorChannel(int colorChannel)

        switch (colorChannel) {
            case CHANNEL_RED:
            case CHANNEL_GREEN:
            case CHANNEL_BLUE:
                break;
            default:
                throw new IllegalArgumentException("colorChannel out of range");
        }

        return colorChannel;
    
public voidcopyColorCurve(int colorChannel, float[] destination, int offset)
Copy the color curve for a single color channel from this tonemap curve into the destination.

Values are stored as packed {@code (Pin, Pout}) points, and there are a total of {@link #getPointCount} points for that respective channel.

All returned coordinates are between the range of [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].

param
destination an array big enough to hold at least {@link #getPointCount} {@code *} {@link #POINT_SIZE} elements after the {@code offset}
param
offset a non-negative offset into the array
throws
NullPointerException If {@code destination} was {@code null}
throws
IllegalArgumentException If offset was negative
throws
ArrayIndexOutOfBoundsException If there's not enough room to write the elements at the specified destination and offset.
see
CaptureRequest#TONEMAP_CURVE_BLUE
see
CaptureRequest#TONEMAP_CURVE_RED
see
CaptureRequest#TONEMAP_CURVE_GREEN
see
#LEVEL_BLACK
see
#LEVEL_WHITE

        checkArgumentNonnegative(offset, "offset must not be negative");
        checkNotNull(destination, "destination must not be null");

        if (destination.length + offset < getPointCount(colorChannel) * POINT_SIZE) {
            throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
        }

        float[] curve = getCurve(colorChannel);
        System.arraycopy(curve, /*srcPos*/0, destination, offset, curve.length);
    
private java.lang.StringcurveToString(int colorChannel)

        checkArgumentColorChannel(colorChannel);
        StringBuilder sb = new StringBuilder("[");
        float[] curve = getCurve(colorChannel);
        int pointCount = curve.length / POINT_SIZE;
        for (int i = 0, j = 0; i < pointCount; i++, j += 2) {
            sb.append("(");
            sb.append(curve[j]);
            sb.append(", ");
            sb.append(curve[j+1]);
            sb.append("), ");
        }
        // trim extra ", " at the end. Guaranteed to work because pointCount >= 2
        sb.setLength(sb.length() - 2);
        sb.append("]");
        return sb.toString();
    
public booleanequals(java.lang.Object obj)
Check if this TonemapCurve is equal to another TonemapCurve.

Two matrices are equal if and only if all of their elements are {@link Object#equals equal}.

return
{@code true} if the objects were equal, {@code false} otherwise

        if (obj == null) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (obj instanceof TonemapCurve) {
            final TonemapCurve other = (TonemapCurve) obj;
            return Arrays.equals(mRed, other.mRed) &&
                    Arrays.equals(mGreen, other.mGreen) &&
                    Arrays.equals(mBlue, other.mBlue);
        }
        return false;
    
private float[]getCurve(int colorChannel)

        switch (colorChannel) {
            case CHANNEL_RED:
                return mRed;
            case CHANNEL_GREEN:
                return mGreen;
            case CHANNEL_BLUE:
                return mBlue;
            default:
                throw new AssertionError("colorChannel out of range");
        }
    
public android.graphics.PointFgetPoint(int colorChannel, int index)
Get the point for a color channel at a specified index.

The index must be at least 0 but no greater than {@link #getPointCount(int)} for that {@code colorChannel}.

All returned coordinates in the point are between the range of [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].

param
colorChannel {@link #CHANNEL_RED}, {@link #CHANNEL_GREEN}, or {@link #CHANNEL_BLUE}
param
index at least 0 but no greater than {@code getPointCount(colorChannel)}
return
the {@code (Pin, Pout)} pair mapping the tone for that index
throws
IllegalArgumentException if {@code colorChannel} or {@code index} was out of range
see
#LEVEL_BLACK
see
#LEVEL_WHITE

        checkArgumentColorChannel(colorChannel);
        if (index < 0 || index >= getPointCount(colorChannel)) {
            throw new IllegalArgumentException("index out of range");
        }

        final float[] curve = getCurve(colorChannel);

        final float pIn = curve[index * POINT_SIZE + OFFSET_POINT_IN];
        final float pOut = curve[index * POINT_SIZE + OFFSET_POINT_OUT];

        return new PointF(pIn, pOut);
    
public intgetPointCount(int colorChannel)
Get the number of points stored in this tonemap curve for the specified color channel.

param
colorChannel one of {@link #CHANNEL_RED}, {@link #CHANNEL_GREEN}, {@link #CHANNEL_BLUE}
return
number of points stored in this tonemap for that color's curve (>= 0)
throws
IllegalArgumentException if {@code colorChannel} was out of range

        checkArgumentColorChannel(colorChannel);

        return getCurve(colorChannel).length / POINT_SIZE;
    
public inthashCode()
{@inheritDoc}

        if (mHashCalculated) {
            // Avoid re-calculating hash. Data is immutable so this is both legal and faster.
            return mHashCode;
        }

        mHashCode = HashCodeHelpers.hashCode(mRed, mGreen, mBlue);
        mHashCalculated = true;

        return mHashCode;
    
public java.lang.StringtoString()
Return the TonemapCurve as a string representation.

{@code "TonemapCurve{R:[(%f, %f), (%f, %f) ... (%f, %f)], G:[(%f, %f), (%f, %f) ... (%f, %f)], B:[(%f, %f), (%f, %f) ... (%f, %f)]}"}, where each {@code (%f, %f)} respectively represents one point of the corresponding tonemap curve.

return
string representation of {@link TonemapCurve}

        StringBuilder sb = new StringBuilder("TonemapCurve{");
        sb.append("R:");
        sb.append(curveToString(CHANNEL_RED));
        sb.append(", G:");
        sb.append(curveToString(CHANNEL_GREEN));
        sb.append(", B:");
        sb.append(curveToString(CHANNEL_BLUE));
        sb.append("}");
        return sb.toString();