am 051dd983: camera2: Add camera-specific data types used for metadata key/value
* commit '051dd9832b0c6c483f2d162154f67a31ef097598': camera2: Add camera-specific data types used for metadata key/value
This commit is contained in:
@@ -12237,6 +12237,16 @@ package android.hardware.camera2 {
|
||||
field public static final int SCORE_MIN = 1; // 0x1
|
||||
}
|
||||
|
||||
public final class LensShadingMap {
|
||||
method public void copyGainFactors(float[], int);
|
||||
method public int getColumnCount();
|
||||
method public float getGainFactor(int, int, int);
|
||||
method public int getGainFactorCount();
|
||||
method public android.hardware.camera2.RggbChannelVector getGainFactorVector(int, int);
|
||||
method public int getRowCount();
|
||||
field public static final float MINIMUM_GAIN_FACTOR = 1.0f;
|
||||
}
|
||||
|
||||
public final class MeteringRectangle {
|
||||
ctor public MeteringRectangle(int, int, int, int, int);
|
||||
ctor public MeteringRectangle(android.graphics.Point, android.util.Size, int);
|
||||
@@ -12258,12 +12268,52 @@ package android.hardware.camera2 {
|
||||
method public int getNumerator();
|
||||
}
|
||||
|
||||
public final class RggbChannelVector {
|
||||
ctor public RggbChannelVector(float, float, float, float);
|
||||
method public void copyTo(float[], int);
|
||||
method public float getBlue();
|
||||
method public float getComponent(int);
|
||||
method public float getGreenEven();
|
||||
method public float getGreenOdd();
|
||||
method public final float getRed();
|
||||
field public static final int BLUE = 3; // 0x3
|
||||
field public static final int COUNT = 4; // 0x4
|
||||
field public static final int GREEN_EVEN = 1; // 0x1
|
||||
field public static final int GREEN_ODD = 2; // 0x2
|
||||
field public static final int RED = 0; // 0x0
|
||||
}
|
||||
|
||||
public final class Size {
|
||||
ctor public Size(int, int);
|
||||
method public final int getHeight();
|
||||
method public final int getWidth();
|
||||
}
|
||||
|
||||
public final class StreamConfigurationMap {
|
||||
method public final int[] getOutputFormats();
|
||||
method public long getOutputMinFrameDuration(int, android.util.Size);
|
||||
method public long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
|
||||
method public android.util.Size[] getOutputSizes(java.lang.Class<T>);
|
||||
method public android.util.Size[] getOutputSizes(int);
|
||||
method public long getOutputStallDuration(int, android.util.Size);
|
||||
method public long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
|
||||
method public boolean isOutputSupportedFor(int);
|
||||
method public static boolean isOutputSupportedFor(java.lang.Class<T>);
|
||||
method public boolean isOutputSupportedFor(android.view.Surface);
|
||||
}
|
||||
|
||||
public final class TonemapCurve {
|
||||
method public void copyColorCurve(int, float[], int);
|
||||
method public android.graphics.PointF getPoint(int, int);
|
||||
method public int getPointCount(int);
|
||||
field public static final int CHANNEL_BLUE = 2; // 0x2
|
||||
field public static final int CHANNEL_GREEN = 1; // 0x1
|
||||
field public static final int CHANNEL_RED = 0; // 0x0
|
||||
field public static final float LEVEL_BLACK = 0.0f;
|
||||
field public static final float LEVEL_WHITE = 1.0f;
|
||||
field public static final int POINT_SIZE = 2; // 0x2
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.hardware.display {
|
||||
|
||||
@@ -192,8 +192,9 @@ public interface CameraDevice extends AutoCloseable {
|
||||
*
|
||||
* <p>The camera device will query each Surface's size and formats upon this
|
||||
* call, so they must be set to a valid setting at this time (in particular:
|
||||
* if the format is user-visible, it must be one of android.scaler.availableFormats;
|
||||
* and the size must be one of android.scaler.available[Processed|Jpeg]Sizes).</p>
|
||||
* if the format is user-visible, it must be one of
|
||||
* {@link StreamConfigurationMap#getOutputFormats}; and the size must be one of
|
||||
* {@link StreamConfigurationMap#getOutputSizes(int)}).</p>
|
||||
*
|
||||
* <p>When this method is called with valid Surfaces, the device will transition to the {@link
|
||||
* StateListener#onBusy busy state}. Once configuration is complete, the device will transition
|
||||
@@ -239,6 +240,9 @@ public interface CameraDevice extends AutoCloseable {
|
||||
* @see StateListener#onUnconfigured
|
||||
* @see #stopRepeating
|
||||
* @see #flush
|
||||
* @see StreamConfigurationMap#getOutputFormats()
|
||||
* @see StreamConfigurationMap#getOutputSizes(int)
|
||||
* @see StreamConfigurationMap#getOutputSizes(Class)
|
||||
*/
|
||||
public void configureOutputs(List<Surface> outputs) throws CameraAccessException;
|
||||
|
||||
|
||||
243
core/java/android/hardware/camera2/LensShadingMap.java
Normal file
243
core/java/android/hardware/camera2/LensShadingMap.java
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static com.android.internal.util.Preconditions.*;
|
||||
import static android.hardware.camera2.RggbChannelVector.*;
|
||||
|
||||
import android.hardware.camera2.impl.HashCodeHelpers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Immutable class for describing a {@code 4 x N x M} lens shading map of floats.
|
||||
*
|
||||
* @see CameraCharacteristics#LENS_SHADING_MAP
|
||||
*/
|
||||
public final class LensShadingMap {
|
||||
|
||||
/**
|
||||
* The smallest gain factor in this map.
|
||||
*
|
||||
* <p>All values in this map will be at least this large.</p>
|
||||
*/
|
||||
public static final float MINIMUM_GAIN_FACTOR = 1.0f;
|
||||
|
||||
/**
|
||||
* Create a new immutable LensShadingMap instance.
|
||||
*
|
||||
* <p>The elements must be stored in a row-major order (fully packed).</p>
|
||||
*
|
||||
* <p>This constructor takes over the array; do not write to the array afterwards.</p>
|
||||
*
|
||||
* @param elements
|
||||
* An array of elements whose length is
|
||||
* {@code RggbChannelVector.COUNT * rows * columns}
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if the {@code elements} array length is invalid,
|
||||
* if any of the subelems are not finite or less than {@value #MINIMUM_GAIN_FACTOR},
|
||||
* or if rows or columns is not positive
|
||||
* @throws NullPointerException
|
||||
* if {@code elements} is {@code null}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public LensShadingMap(final float[] elements, final int rows, final int columns) {
|
||||
|
||||
mRows = checkArgumentPositive(rows, "rows must be positive");
|
||||
mColumns = checkArgumentPositive(rows, "columns must be positive");
|
||||
mElements = checkNotNull(elements, "elements must not be null");
|
||||
|
||||
if (elements.length != getGainFactorCount()) {
|
||||
throw new IllegalArgumentException("elements must be " + getGainFactorCount() +
|
||||
" length");
|
||||
}
|
||||
|
||||
// Every element must be finite and >= 1.0f
|
||||
checkArrayElementsInRange(elements, MINIMUM_GAIN_FACTOR, Float.MAX_VALUE, "elements");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of rows in this map.
|
||||
*/
|
||||
public int getRowCount() {
|
||||
return mRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of columns in this map.
|
||||
*/
|
||||
public int getColumnCount() {
|
||||
return mColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of gain factors in this map.
|
||||
*
|
||||
* <p>A single gain factor contains exactly one color channel.
|
||||
* Use with {@link #copyGainFactors} to allocate a large-enough array.</p>
|
||||
*/
|
||||
public int getGainFactorCount() {
|
||||
return mRows * mColumns * COUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single color channel gain factor from this lens shading map by its row and column.
|
||||
*
|
||||
* <p>The rows must be within the range [0, {@link #getRowCount}),
|
||||
* the column must be within the range [0, {@link #getColumnCount}),
|
||||
* and the color channel must be within the range [0, {@value RggbChannelVector#COUNT}).</p>
|
||||
*
|
||||
* <p>The channel order is {@code [R, Geven, Godd, B]}, where
|
||||
* {@code Geven} is the green channel for the even rows of a Bayer pattern, and
|
||||
* {@code Godd} is the odd rows.
|
||||
* </p>
|
||||
*
|
||||
* @param colorChannel color channel from {@code [R, Geven, Godd, B]}
|
||||
* @param column within the range [0, {@link #getColumnCount})
|
||||
* @param row within the range [0, {@link #getRowCount})
|
||||
*
|
||||
* @return a gain factor >= {@value #MINIMUM_GAIN_FACTOR}
|
||||
*
|
||||
* @throws IllegalArgumentException if any of the parameters was out of range
|
||||
*
|
||||
* @see #RED
|
||||
* @see #GREEN_EVEN
|
||||
* @see #GREEN_ODD
|
||||
* @see #BLUE
|
||||
* @see #getRowCount
|
||||
* @see #getColumnCount
|
||||
*/
|
||||
public float getGainFactor(final int colorChannel, final int column, final int row) {
|
||||
if (colorChannel < 0 || colorChannel > COUNT) {
|
||||
throw new IllegalArgumentException("colorChannel out of range");
|
||||
} else if (column < 0 || column >= mColumns) {
|
||||
throw new IllegalArgumentException("column out of range");
|
||||
} else if (row < 0 || row >= mRows) {
|
||||
throw new IllegalArgumentException("row out of range");
|
||||
}
|
||||
|
||||
return mElements[colorChannel + (row * mColumns + column) * COUNT ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a gain factor vector from this lens shading map by its row and column.
|
||||
*
|
||||
* <p>The rows must be within the range [0, {@link #getRowCount}),
|
||||
* the column must be within the range [0, {@link #getColumnCount}).</p>
|
||||
*
|
||||
* @param column within the range [0, {@link #getColumnCount})
|
||||
* @param row within the range [0, {@link #getRowCount})
|
||||
*
|
||||
* @return an {@link RggbChannelVector} where each gain factor >= {@value #MINIMUM_GAIN_FACTOR}
|
||||
*
|
||||
* @throws IllegalArgumentException if any of the parameters was out of range
|
||||
*
|
||||
* @see #getRowCount
|
||||
* @see #getColumnCount
|
||||
*/
|
||||
public RggbChannelVector getGainFactorVector(final int column, final int row) {
|
||||
if (column < 0 || column >= mColumns) {
|
||||
throw new IllegalArgumentException("column out of range");
|
||||
} else if (row < 0 || row >= mRows) {
|
||||
throw new IllegalArgumentException("row out of range");
|
||||
}
|
||||
|
||||
final int offset = (row * mColumns + column) * COUNT;
|
||||
|
||||
final float red =
|
||||
mElements[RED + offset];
|
||||
final float greenEven =
|
||||
mElements[GREEN_EVEN + offset];
|
||||
final float greenOdd =
|
||||
mElements[GREEN_ODD + offset];
|
||||
final float blue =
|
||||
mElements[BLUE + offset];
|
||||
|
||||
return new RggbChannelVector(red, greenEven, greenOdd, blue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all gain factors in row-major order from this lens shading map into the destination.
|
||||
*
|
||||
* <p>Each gain factor will be >= {@link #MINIMUM_GAIN_FACTOR}.</p>
|
||||
*
|
||||
* @param destination
|
||||
* an array big enough to hold at least {@link RggbChannelVector#COUNT}
|
||||
* 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 CaptureResult#STATISTICS_LENS_SHADING_MAP
|
||||
*/
|
||||
public void copyGainFactors(final float[] destination, final int offset) {
|
||||
checkArgumentNonnegative(offset, "offset must not be negative");
|
||||
checkNotNull(destination, "destination must not be null");
|
||||
if (destination.length + offset < getGainFactorCount()) {
|
||||
throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
|
||||
}
|
||||
|
||||
System.arraycopy(mElements, /*srcPos*/0, destination, offset, getGainFactorCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this LensShadingMap is equal to another LensShadingMap.
|
||||
*
|
||||
* <p>Two lens shading maps are equal if and only if they have the same rows/columns,
|
||||
* and all of their elements are {@link Object#equals 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;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof LensShadingMap) {
|
||||
final LensShadingMap other = (LensShadingMap) obj;
|
||||
return mRows == other.mRows
|
||||
&& mColumns == other.mColumns
|
||||
&& Arrays.equals(mElements, other.mElements);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int elemsHash = HashCodeHelpers.hashCode(mElements);
|
||||
return HashCodeHelpers.hashCode(mRows, mColumns, elemsHash);
|
||||
}
|
||||
|
||||
|
||||
private final int mRows;
|
||||
private final int mColumns;
|
||||
private final float[] mElements;
|
||||
};
|
||||
258
core/java/android/hardware/camera2/ReprocessFormatsMap.java
Normal file
258
core/java/android/hardware/camera2/ReprocessFormatsMap.java
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static com.android.internal.util.Preconditions.*;
|
||||
|
||||
import android.hardware.camera2.impl.HashCodeHelpers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Immutable class to store the input to output formats
|
||||
* {@link CameraCharacteristics#SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP map} to be used for with
|
||||
* camera image reprocessing.
|
||||
*
|
||||
* <p>
|
||||
* The mapping of image formats that are supported by this camera device for input streams,
|
||||
* to their corresponding output formats.</p>
|
||||
*
|
||||
* <p>
|
||||
* Attempting to configure an input stream with output streams not listed as available in this map
|
||||
* is not valid.
|
||||
* </p>
|
||||
*
|
||||
* @see CameraCharacteristics#SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP
|
||||
* @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
|
||||
*
|
||||
* <!-- hide this until we expose input streams through public API -->
|
||||
* @hide
|
||||
*/
|
||||
public final class ReprocessFormatsMap {
|
||||
/**
|
||||
* Create a new {@link ReprocessFormatsMap}
|
||||
*
|
||||
* <p>This value is encoded as a variable-size array-of-arrays.
|
||||
* The inner array always contains {@code [format, length, ...]} where ... has length elements.
|
||||
* An inner array is followed by another inner array if the total metadata entry size hasn't
|
||||
* yet been exceeded.</p>
|
||||
*
|
||||
* <p>Entry must not be {@code null}. Empty array is acceptable.</p>
|
||||
*
|
||||
* <p>The entry array ownership is passed to this instance after construction; do not
|
||||
* write to it afterwards.</p>
|
||||
*
|
||||
* @param entry Array of ints, not yet deserialized (not-null)
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if the data was poorly formatted
|
||||
* (missing output format length or too few output formats)
|
||||
* @throws NullPointerException
|
||||
* if entry was null
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public ReprocessFormatsMap(final int[] entry) {
|
||||
checkNotNull(entry, "entry must not be null");
|
||||
|
||||
int numInputs = 0;
|
||||
int left = entry.length;
|
||||
for (int i = 0; i < entry.length; ) {
|
||||
final int format = entry[i];
|
||||
|
||||
left--;
|
||||
i++;
|
||||
|
||||
if (left < 1) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Input %x had no output format length listed", format));
|
||||
}
|
||||
|
||||
final int length = entry[i];
|
||||
left--;
|
||||
i++;
|
||||
|
||||
if (length > 0) {
|
||||
if (left < length) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Input %x had too few output formats listed (actual: %d, " +
|
||||
"expected: %d)", format, left, length));
|
||||
}
|
||||
|
||||
i += length;
|
||||
left -= length;
|
||||
}
|
||||
|
||||
numInputs++;
|
||||
}
|
||||
|
||||
mEntry = entry;
|
||||
mInputCount = numInputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all input image formats that can be used to reprocess an input
|
||||
* stream into an output stream.
|
||||
*
|
||||
* <p>Use this input format to look up the available output formats with {@link #getOutputs}.
|
||||
* </p>
|
||||
*
|
||||
* @return an array of inputs (possibly empty, but never {@code null})
|
||||
*
|
||||
* @see ImageFormat
|
||||
* @see #getOutputs
|
||||
*/
|
||||
public int[] getInputs() {
|
||||
final int[] inputs = new int[mInputCount];
|
||||
|
||||
int left = mEntry.length;
|
||||
for (int i = 0, j = 0; i < mEntry.length; j++) {
|
||||
final int format = mEntry[i];
|
||||
|
||||
left--;
|
||||
i++;
|
||||
|
||||
if (left < 1) {
|
||||
throw new AssertionError(
|
||||
String.format("Input %x had no output format length listed", format));
|
||||
}
|
||||
// TODO: check format is a valid input format
|
||||
|
||||
final int length = mEntry[i];
|
||||
left--;
|
||||
i++;
|
||||
|
||||
if (length > 0) {
|
||||
if (left < length) {
|
||||
throw new AssertionError(
|
||||
String.format(
|
||||
"Input %x had too few output formats listed (actual: %d, " +
|
||||
"expected: %d)", format, left, length));
|
||||
}
|
||||
|
||||
i += length;
|
||||
left -= length;
|
||||
}
|
||||
|
||||
// TODO: check output format is a valid output format
|
||||
|
||||
inputs[j] = format;
|
||||
}
|
||||
|
||||
return inputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of output formats that can be reprocessed into from the input {@code format}.
|
||||
*
|
||||
* <p>The input {@code format} must be one of the formats returned by {@link #getInputs}.</p>
|
||||
*
|
||||
* @param format an input format
|
||||
*
|
||||
* @return list of output image formats
|
||||
*
|
||||
* @see ImageFormat
|
||||
* @see #getInputs
|
||||
*/
|
||||
public int[] getOutputs(final int format) {
|
||||
|
||||
int left = mEntry.length;
|
||||
for (int i = 0; i < mEntry.length; ) {
|
||||
final int inputFormat = mEntry[i];
|
||||
|
||||
left--;
|
||||
i++;
|
||||
|
||||
if (left < 1) {
|
||||
throw new AssertionError(
|
||||
String.format("Input %x had no output format length listed", format));
|
||||
}
|
||||
|
||||
final int length = mEntry[i];
|
||||
left--;
|
||||
i++;
|
||||
|
||||
if (length > 0) {
|
||||
if (left < length) {
|
||||
throw new AssertionError(
|
||||
String.format(
|
||||
"Input %x had too few output formats listed (actual: %d, " +
|
||||
"expected: %d)", format, left, length));
|
||||
}
|
||||
}
|
||||
|
||||
if (inputFormat == format) {
|
||||
int[] outputs = new int[length];
|
||||
|
||||
// Copying manually faster than System.arraycopy for small arrays
|
||||
for (int k = 0; k < length; ++k) {
|
||||
outputs[k] = mEntry[i + k];
|
||||
}
|
||||
|
||||
return outputs;
|
||||
}
|
||||
|
||||
i += length;
|
||||
left -= length;
|
||||
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Input format %x was not one in #getInputs", format));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this {@link ReprocessFormatsMap} is equal to another
|
||||
* {@link ReprocessFormatsMap}.
|
||||
*
|
||||
* <p>These two objects 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;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof ReprocessFormatsMap) {
|
||||
final ReprocessFormatsMap other = (ReprocessFormatsMap) obj;
|
||||
// Do not compare anything besides mEntry, since the rest of the values are derived
|
||||
return Arrays.equals(mEntry, other.mEntry);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Do not hash anything besides mEntry since the rest of the values are derived
|
||||
return HashCodeHelpers.hashCode(mEntry);
|
||||
}
|
||||
|
||||
private final int[] mEntry;
|
||||
/*
|
||||
* Dependent fields: values are derived from mEntry
|
||||
*/
|
||||
private final int mInputCount;
|
||||
}
|
||||
199
core/java/android/hardware/camera2/RggbChannelVector.java
Normal file
199
core/java/android/hardware/camera2/RggbChannelVector.java
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
private final float mRed;
|
||||
private final float mGreenEven;
|
||||
private final float mGreenOdd;
|
||||
private final float mBlue;
|
||||
}
|
||||
166
core/java/android/hardware/camera2/StreamConfiguration.java
Normal file
166
core/java/android/hardware/camera2/StreamConfiguration.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static com.android.internal.util.Preconditions.*;
|
||||
import static android.hardware.camera2.StreamConfigurationMap.checkArgumentFormatInternal;
|
||||
|
||||
import android.graphics.ImageFormat;
|
||||
import android.hardware.camera2.impl.HashCodeHelpers;
|
||||
import android.util.Size;
|
||||
|
||||
/**
|
||||
* Immutable class to store the available stream
|
||||
* {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS configurations} to be used
|
||||
* when configuring streams with {@link CameraDevice#configureOutputs}.
|
||||
* <!-- TODO: link to input stream configuration -->
|
||||
*
|
||||
* <p>This is the authoritative list for all input/output formats (and sizes respectively
|
||||
* for that format) that are supported by a camera device.</p>
|
||||
*
|
||||
* @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class StreamConfiguration {
|
||||
|
||||
/**
|
||||
* Create a new {@link StreamConfiguration}.
|
||||
*
|
||||
* @param format image format
|
||||
* @param width image width, in pixels (positive)
|
||||
* @param height image height, in pixels (positive)
|
||||
* @param input true if this is an input configuration, false for output configurations
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if width/height were not positive
|
||||
* or if the format was not user-defined in ImageFormat/PixelFormat
|
||||
* (IMPL_DEFINED is ok)
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public StreamConfiguration(
|
||||
final int format, final int width, final int height, final boolean input) {
|
||||
mFormat = checkArgumentFormatInternal(format);
|
||||
mWidth = checkArgumentPositive(width, "width must be positive");
|
||||
mHeight = checkArgumentPositive(width, "height must be positive");
|
||||
mInput = input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image {@code format} in this stream configuration.
|
||||
*
|
||||
* @return an integer format
|
||||
*
|
||||
* @see ImageFormat
|
||||
*/
|
||||
public final int getFormat() {
|
||||
return mFormat;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the width of the stream configuration.
|
||||
*
|
||||
* @return width > 0
|
||||
*/
|
||||
public int getWidth() {
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the height of the stream configuration.
|
||||
*
|
||||
* @return height > 0
|
||||
*/
|
||||
public int getHeight() {
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to return the size of this stream configuration.
|
||||
*
|
||||
* @return a Size with positive width and height
|
||||
*/
|
||||
public Size getSize() {
|
||||
return new Size(mWidth, mHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if this configuration is usable for input streams.
|
||||
*
|
||||
* <p>Input and output stream configurations are not interchangeable;
|
||||
* input stream configurations must be used when configuring inputs.</p>
|
||||
*
|
||||
* @return {@code true} if input configuration, {@code false} otherwise
|
||||
*/
|
||||
public boolean isInput() {
|
||||
return mInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if this configuration is usable for output streams.
|
||||
*
|
||||
* <p>Input and output stream configurations are not interchangeable;
|
||||
* out stream configurations must be used when configuring outputs.</p>
|
||||
*
|
||||
* @return {@code true} if output configuration, {@code false} otherwise
|
||||
*
|
||||
* @see CameraDevice#configureOutputs
|
||||
*/
|
||||
public boolean isOutput() {
|
||||
return !mInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this {@link StreamConfiguration} is equal to another {@link StreamConfiguration}.
|
||||
*
|
||||
* <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;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof StreamConfiguration) {
|
||||
final StreamConfiguration other = (StreamConfiguration) obj;
|
||||
return mFormat == other.mFormat &&
|
||||
mWidth == other.mWidth &&
|
||||
mHeight == other.mHeight &&
|
||||
mInput == other.mInput;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight, mInput ? 1 : 0);
|
||||
}
|
||||
|
||||
private final int mFormat;
|
||||
private final int mWidth;
|
||||
private final int mHeight;
|
||||
private final boolean mInput;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static com.android.internal.util.Preconditions.*;
|
||||
import static android.hardware.camera2.StreamConfigurationMap.checkArgumentFormatInternal;
|
||||
|
||||
import android.graphics.ImageFormat;
|
||||
import android.hardware.camera2.impl.HashCodeHelpers;
|
||||
import android.util.Size;
|
||||
|
||||
/**
|
||||
* Immutable class to store a time duration for any given format/size combination.
|
||||
*
|
||||
* @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
|
||||
* @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
|
||||
* @see CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class StreamConfigurationDuration {
|
||||
|
||||
/**
|
||||
* Create a new {@link StreamConfigurationDuration}.
|
||||
*
|
||||
* @param format image format
|
||||
* @param width image width, in pixels (positive)
|
||||
* @param height image height, in pixels (positive)
|
||||
* @param durationNs duration in nanoseconds (non-negative)
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if width/height were not positive, or durationNs was negative
|
||||
* or if the format was not user-defined in ImageFormat/PixelFormat
|
||||
* (IMPL_DEFINED is OK)
|
||||
*
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public StreamConfigurationDuration(
|
||||
final int format, final int width, final int height, final long durationNs) {
|
||||
mFormat = checkArgumentFormatInternal(format);
|
||||
mWidth = checkArgumentPositive(width, "width must be positive");
|
||||
mHeight = checkArgumentPositive(width, "height must be positive");
|
||||
mDurationNs = checkArgumentNonnegative(durationNs, "durationNs must be non-negative");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image {@code format} in this stream configuration duration
|
||||
*
|
||||
* @return an integer format
|
||||
*
|
||||
* @see ImageFormat
|
||||
*/
|
||||
public final int getFormat() {
|
||||
return mFormat;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the width of the stream configuration duration.
|
||||
*
|
||||
* @return width > 0
|
||||
*/
|
||||
public int getWidth() {
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the height of the stream configuration duration
|
||||
*
|
||||
* @return height > 0
|
||||
*/
|
||||
public int getHeight() {
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to return the size of this stream configuration duration.
|
||||
*
|
||||
* @return a Size with positive width and height
|
||||
*/
|
||||
public Size getSize() {
|
||||
return new Size(mWidth, mHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time duration (in nanoseconds).
|
||||
*
|
||||
* @return long >= 0
|
||||
*/
|
||||
public long getDuration() {
|
||||
return mDurationNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this {@link StreamConfigurationDuration} is equal to another
|
||||
* {@link StreamConfigurationDuration}.
|
||||
*
|
||||
* <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;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof StreamConfigurationDuration) {
|
||||
final StreamConfigurationDuration other = (StreamConfigurationDuration) obj;
|
||||
return mFormat == other.mFormat &&
|
||||
mWidth == other.mWidth &&
|
||||
mHeight == other.mHeight &&
|
||||
mDurationNs == other.mDurationNs;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight,
|
||||
(int) mDurationNs, (int)(mDurationNs >>> Integer.SIZE));
|
||||
}
|
||||
|
||||
private final int mFormat;
|
||||
private final int mWidth;
|
||||
private final int mHeight;
|
||||
private final long mDurationNs;
|
||||
}
|
||||
508
core/java/android/hardware/camera2/StreamConfigurationMap.java
Normal file
508
core/java/android/hardware/camera2/StreamConfigurationMap.java
Normal file
@@ -0,0 +1,508 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.hardware.camera2.impl.HashCodeHelpers;
|
||||
import android.view.Surface;
|
||||
import android.util.Size;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static com.android.internal.util.Preconditions.*;
|
||||
|
||||
/**
|
||||
* Immutable class to store the available stream
|
||||
* {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS configurations} to be used
|
||||
* when configuring streams with {@link CameraDevice#configureOutputs}.
|
||||
* <!-- TODO: link to input stream configuration -->
|
||||
*
|
||||
* <p>This is the authoritative list for all <!-- input/ -->output formats (and sizes respectively
|
||||
* for that format) that are supported by a camera device.</p>
|
||||
*
|
||||
* <p>This also contains the minimum frame durations and stall durations for each format/size
|
||||
* combination that can be used to calculate effective frame rate when submitting multiple captures.
|
||||
* </p>
|
||||
*
|
||||
* <p>An instance of this object is available from {@link CameraCharacteristics} using
|
||||
* the {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS} key and the
|
||||
* {@link CameraCharacteristics#get} method.</p.
|
||||
*
|
||||
* <pre>{@code
|
||||
* CameraCharacteristics characteristics = ...;
|
||||
* StreamConfigurationMap configs = characteristics.get(
|
||||
* CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
|
||||
* }</pre>
|
||||
*
|
||||
* @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
|
||||
* @see CameraDevice#configureOutputs
|
||||
*/
|
||||
public final class StreamConfigurationMap {
|
||||
|
||||
/**
|
||||
* Create a new {@link StreamConfigurationMap}.
|
||||
*
|
||||
* <p>The array parameters ownership is passed to this object after creation; do not
|
||||
* write to them after this constructor is invoked.</p>
|
||||
*
|
||||
* @param configurations a non-{@code null} array of {@link StreamConfiguration}
|
||||
* @param durations a non-{@code null} array of {@link StreamConfigurationDuration}
|
||||
*
|
||||
* @throws NullPointerException if any of the arguments or subelements were {@code null}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public StreamConfigurationMap(
|
||||
StreamConfiguration[] configurations,
|
||||
StreamConfigurationDuration[] durations) {
|
||||
// TODO: format check against ImageFormat/PixelFormat ?
|
||||
|
||||
mConfigurations = checkArrayElementsNotNull(configurations, "configurations");
|
||||
mDurations = checkArrayElementsNotNull(durations, "durations");
|
||||
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image {@code format} output formats in this stream configuration.
|
||||
*
|
||||
* <p>All image formats returned by this function will be defined in either {@link ImageFormat}
|
||||
* or in {@link PixelFormat} (and there is no possibility of collision).</p>
|
||||
*
|
||||
* <p>Formats listed in this array are guaranteed to return true if queried with
|
||||
* {@link #isOutputSupportedFor(int).</p>
|
||||
*
|
||||
* @return an array of integer format
|
||||
*
|
||||
* @see ImageFormat
|
||||
* @see PixelFormat
|
||||
*/
|
||||
public final int[] getOutputFormats() {
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image {@code format} input formats in this stream configuration.
|
||||
*
|
||||
* <p>All image formats returned by this function will be defined in either {@link ImageFormat}
|
||||
* or in {@link PixelFormat} (and there is no possibility of collision).</p>
|
||||
*
|
||||
* @return an array of integer format
|
||||
*
|
||||
* @see ImageFormat
|
||||
* @see PixelFormat
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final int[] getInputFormats() {
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the supported input sizes for this input format.
|
||||
*
|
||||
* <p>The format must have come from {@link #getInputFormats}; otherwise
|
||||
* {@code null} is returned.</p>
|
||||
*
|
||||
* @param format a format from {@link #getInputFormats}
|
||||
* @return a non-empty array of sizes, or {@code null} if the format was not available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public Size[] getInputSizes(final int format) {
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether or not output streams can be
|
||||
* {@link CameraDevice#configureOutputs configured} with a particular user-defined format.
|
||||
*
|
||||
* <p>This method determines that the output {@code format} is supported by the camera device;
|
||||
* each output {@code surface} target may or may not itself support that {@code format}.
|
||||
* Refer to the class which provides the surface for additional documentation.</p>
|
||||
*
|
||||
* <p>Formats for which this returns {@code true} are guaranteed to exist in the result
|
||||
* returned by {@link #getOutputSizes}.</p>
|
||||
*
|
||||
* @param format an image format from either {@link ImageFormat} or {@link PixelFormat}
|
||||
* @return
|
||||
* {@code true} iff using a {@code surface} with this {@code format} will be
|
||||
* supported with {@link CameraDevice#configureOutputs}
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if the image format was not a defined named constant
|
||||
* from either {@link ImageFormat} or {@link PixelFormat}
|
||||
*
|
||||
* @see ImageFormat
|
||||
* @see PixelFormat
|
||||
* @see CameraDevice#configureOutputs
|
||||
*/
|
||||
public boolean isOutputSupportedFor(int format) {
|
||||
checkArgumentFormat(format);
|
||||
|
||||
final int[] formats = getOutputFormats();
|
||||
for (int i = 0; i < formats.length; ++i) {
|
||||
if (format == formats[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether or not output streams can be configured with a particular class
|
||||
* as a consumer.
|
||||
*
|
||||
* <p>The following list is generally usable for outputs:
|
||||
* <ul>
|
||||
* <li>{@link android.media.ImageReader} -
|
||||
* Recommended for image processing or streaming to external resources (such as a file or
|
||||
* network)
|
||||
* <li>{@link android.media.MediaRecorder} -
|
||||
* Recommended for recording video (simple to use)
|
||||
* <li>{@link android.media.MediaCodec} -
|
||||
* Recommended for recording video (more complicated to use, with more flexibility)
|
||||
* <li>{@link android.renderscript.Allocation} -
|
||||
* Recommended for image processing with {@link android.renderscript RenderScript}
|
||||
* <li>{@link android.view.SurfaceHolder} -
|
||||
* Recommended for low-power camera preview with {@link android.view.SurfaceView}
|
||||
* <li>{@link android.graphics.SurfaceTexture} -
|
||||
* Recommended for OpenGL-accelerated preview processing or compositing with
|
||||
* {@link android.view.TextureView}
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* <p>Generally speaking this means that creating a {@link Surface} from that class <i>may</i>
|
||||
* provide a producer endpoint that is suitable to be used with
|
||||
* {@link CameraDevice#configureOutputs}.</p>
|
||||
*
|
||||
* <p>Since not all of the above classes support output of all format and size combinations,
|
||||
* the particular combination should be queried with {@link #isOutputSupportedFor(Surface)}.</p>
|
||||
*
|
||||
* @param klass a non-{@code null} {@link Class} object reference
|
||||
* @return {@code true} if this class is supported as an output, {@code false} otherwise
|
||||
*
|
||||
* @throws NullPointerException if {@code klass} was {@code null}
|
||||
*
|
||||
* @see CameraDevice#configureOutputs
|
||||
* @see #isOutputSupportedFor(Surface)
|
||||
*/
|
||||
public static <T> boolean isOutputSupportedFor(final Class<T> klass) {
|
||||
checkNotNull(klass, "klass must not be null");
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether or not the {@code surface} in its current state is suitable to be
|
||||
* {@link CameraDevice#configureOutputs configured} as an output.
|
||||
*
|
||||
* <p>Not all surfaces are usable with the {@link CameraDevice}, and not all configurations
|
||||
* of that {@code surface} are compatible. Some classes that provide the {@code surface} are
|
||||
* compatible with the {@link CameraDevice} in general
|
||||
* (see {@link #isOutputSupportedFor(Class)}, but it is the caller's responsibility to put the
|
||||
* {@code surface} into a state that will be compatible with the {@link CameraDevice}.</p>
|
||||
*
|
||||
* <p>Reasons for a {@code surface} being specifically incompatible might be:
|
||||
* <ul>
|
||||
* <li>Using a format that's not listed by {@link #getOutputFormats}
|
||||
* <li>Using a format/size combination that's not listed by {@link #getOutputSizes}
|
||||
* <li>The {@code surface} itself is not in a state where it can service a new producer.</p>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* This is not an exhaustive list; see the particular class's documentation for further
|
||||
* possible reasons of incompatibility.</p>
|
||||
*
|
||||
* @param surface a non-{@code null} {@link Surface} object reference
|
||||
* @return {@code true} if this is supported, {@code false} otherwise
|
||||
*
|
||||
* @throws NullPointerException if {@code surface} was {@code null}
|
||||
*
|
||||
* @see CameraDevice#configureOutputs
|
||||
* @see #isOutputSupportedFor(Class)
|
||||
*/
|
||||
public boolean isOutputSupportedFor(final Surface surface) {
|
||||
checkNotNull(surface, "surface must not be null");
|
||||
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of sizes compatible with {@code klass} to use as an output.
|
||||
*
|
||||
* <p>Since some of the supported classes may support additional formats beyond
|
||||
* an opaque/implementation-defined (under-the-hood) format; this function only returns
|
||||
* sizes for the implementation-defined format.</p>
|
||||
*
|
||||
* <p>Some classes such as {@link android.media.ImageReader} may only support user-defined
|
||||
* formats; in particular {@link #isOutputSupportedFor(Class)} will return {@code true} for
|
||||
* that class and this method will return an empty array (but not {@code null}).</p>
|
||||
*
|
||||
* <p>If a well-defined format such as {@code NV21} is required, use
|
||||
* {@link #getOutputSizes(int)} instead.</p>
|
||||
*
|
||||
* <p>The {@code klass} should be a supported output, that querying
|
||||
* {@code #isOutputSupportedFor(Class)} should return {@code true}.</p>
|
||||
*
|
||||
* @param klass
|
||||
* a non-{@code null} {@link Class} object reference
|
||||
* @return
|
||||
* an array of supported sizes for implementation-defined formats,
|
||||
* or {@code null} iff the {@code klass} is not a supported output
|
||||
*
|
||||
* @throws NullPointerException if {@code klass} was {@code null}
|
||||
*
|
||||
* @see #isOutputSupportedFor(Class)
|
||||
*/
|
||||
public <T> Size[] getOutputSizes(final Class<T> klass) {
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of sizes compatible with the requested image {@code format}.
|
||||
*
|
||||
* <p>The {@code format} should be a supported format (one of the formats returned by
|
||||
* {@link #getOutputFormats}).</p>
|
||||
*
|
||||
* @param format an image format from {@link ImageFormat} or {@link PixelFormat}
|
||||
* @return
|
||||
* an array of supported sizes,
|
||||
* or {@code null} if the {@code format} is not a supported output
|
||||
*
|
||||
* @see ImageFormat
|
||||
* @see PixelFormat
|
||||
* @see #getOutputFormats
|
||||
*/
|
||||
public Size[] getOutputSizes(final int format) {
|
||||
try {
|
||||
checkArgumentFormatSupported(format, /*output*/true);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
|
||||
* for the format/size combination (in nanoseconds).
|
||||
*
|
||||
* <p>{@code format} should be one of the ones returned by {@link #getOutputFormats()}.</p>
|
||||
* <p>{@code size} should be one of the ones returned by
|
||||
* {@link #getOutputSizes(int)}.</p>
|
||||
*
|
||||
* @param format an image format from {@link ImageFormat} or {@link PixelFormat}
|
||||
* @param size an output-compatible size
|
||||
* @return a minimum frame duration {@code >=} 0 in nanoseconds
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code format} or {@code size} was not supported
|
||||
* @throws NullPointerException if {@code size} was {@code null}
|
||||
*
|
||||
* @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
|
||||
* @see CaptureRequest#SENSOR_FRAME_DURATION
|
||||
* @see ImageFormat
|
||||
* @see PixelFormat
|
||||
*/
|
||||
public long getOutputMinFrameDuration(final int format, final Size size) {
|
||||
checkArgumentFormatSupported(format, /*output*/true);
|
||||
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
|
||||
* for the class/size combination (in nanoseconds).
|
||||
*
|
||||
* <p>This assumes a the {@code klass} is set up to use an implementation-defined format.
|
||||
* For user-defined formats, use {@link #getOutputMinFrameDuration(int, Size)}.</p>
|
||||
*
|
||||
* <p>{@code klass} should be one of the ones which is supported by
|
||||
* {@link #isOutputSupportedFor(Class)}.</p>
|
||||
*
|
||||
* <p>{@code size} should be one of the ones returned by
|
||||
* {@link #getOutputSizes(int)}.</p>
|
||||
*
|
||||
* @param klass
|
||||
* a class which is supported by {@link #isOutputSupportedFor(Class)} and has a
|
||||
* non-empty array returned by {@link #getOutputSizes(Class)}
|
||||
* @param size an output-compatible size
|
||||
* @return a minimum frame duration {@code >=} 0 in nanoseconds
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
|
||||
* @throws NullPointerException if {@code size} or {@code klass} was {@code null}
|
||||
*
|
||||
* @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
|
||||
* @see CaptureRequest#SENSOR_FRAME_DURATION
|
||||
* @see ImageFormat
|
||||
* @see PixelFormat
|
||||
*/
|
||||
public <T> long getOutputMinFrameDuration(final Class<T> klass, final Size size) {
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS stall duration}
|
||||
* for the format/size combination (in nanoseconds).
|
||||
*
|
||||
* <p>{@code format} should be one of the ones returned by {@link #getOutputFormats()}.</p>
|
||||
* <p>{@code size} should be one of the ones returned by
|
||||
* {@link #getOutputSizes(int)}.</p>
|
||||
*
|
||||
* @param format an image format from {@link ImageFormat} or {@link PixelFormat}
|
||||
* @param size an output-compatible size
|
||||
* @return a stall duration {@code >=} 0 in nanoseconds
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code format} or {@code size} was not supported
|
||||
* @throws NullPointerException if {@code size} was {@code null}
|
||||
*
|
||||
* @see CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS
|
||||
* @see ImageFormat
|
||||
* @see PixelFormat
|
||||
*/
|
||||
public long getOutputStallDuration(final int format, final Size size) {
|
||||
checkArgumentFormatSupported(format, /*output*/true);
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS stall duration}
|
||||
* for the class/size combination (in nanoseconds).
|
||||
*
|
||||
* <p>This assumes a the {@code klass} is set up to use an implementation-defined format.
|
||||
* For user-defined formats, use {@link #getOutputMinFrameDuration(int, Size)}.</p>
|
||||
*
|
||||
* <p>{@code klass} should be one of the ones with a non-empty array returned by
|
||||
* {@link #getOutputSizes(Class)}.</p>
|
||||
*
|
||||
* <p>{@code size} should be one of the ones returned by
|
||||
* {@link #getOutputSizes(Class)}.</p>
|
||||
*
|
||||
* @param klass
|
||||
* a class which is supported by {@link #isOutputSupportedFor(Class)} and has a
|
||||
* non-empty array returned by {@link #getOutputSizes(Class)}
|
||||
* @param size an output-compatible size
|
||||
* @return a minimum frame duration {@code >=} 0 in nanoseconds
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
|
||||
* @throws NullPointerException if {@code size} or {@code klass} was {@code null}
|
||||
*
|
||||
* @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
|
||||
* @see CaptureRequest#SENSOR_FRAME_DURATION
|
||||
* @see ImageFormat
|
||||
* @see PixelFormat
|
||||
*/
|
||||
public <T> long getOutputStallDuration(final Class<T> klass, final Size size) {
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this {@link StreamConfigurationMap} is equal to another
|
||||
* {@link StreamConfigurationMap}.
|
||||
*
|
||||
* <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;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof StreamConfigurationMap) {
|
||||
final StreamConfigurationMap other = (StreamConfigurationMap) obj;
|
||||
// TODO: do we care about order?
|
||||
return Arrays.equals(mConfigurations, other.mConfigurations) &&
|
||||
Arrays.equals(mDurations, other.mDurations);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// TODO: do we care about order?
|
||||
return HashCodeHelpers.hashCode(mConfigurations) ^ HashCodeHelpers.hashCode(mDurations);
|
||||
}
|
||||
|
||||
// Check that the argument is supported by #getOutputFormats or #getInputFormats
|
||||
private int checkArgumentFormatSupported(int format, boolean output) {
|
||||
checkArgumentFormat(format);
|
||||
|
||||
int[] formats = output ? getOutputFormats() : getInputFormats();
|
||||
for (int i = 0; i < formats.length; ++i) {
|
||||
if (format == formats[i]) {
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"format %x is not supported by this stream configuration map", format));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the format is either user-defined or implementation defined.
|
||||
*
|
||||
* <p>Any invalid/undefined formats will raise an exception.</p>
|
||||
*
|
||||
* @param format image format
|
||||
* @return the format
|
||||
*
|
||||
* @throws IllegalArgumentException if the format was invalid
|
||||
*/
|
||||
static int checkArgumentFormatInternal(int format) {
|
||||
if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
|
||||
return format;
|
||||
}
|
||||
|
||||
return checkArgumentFormat(format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the format is user-defined in either ImageFormat or PixelFormat.
|
||||
*
|
||||
* <p>Any invalid/undefined formats will raise an exception, including implementation-defined.
|
||||
* </p>
|
||||
*
|
||||
* <p>Note that {@code @hide} and deprecated formats will not pass this check.</p>
|
||||
*
|
||||
* @param format image format
|
||||
* @return the format
|
||||
*
|
||||
* @throws IllegalArgumentException if the format was not user-defined
|
||||
*/
|
||||
static int checkArgumentFormat(int format) {
|
||||
if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"format %x was not defined in either ImageFormat or PixelFormat", format));
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
|
||||
|
||||
private final StreamConfiguration[] mConfigurations;
|
||||
private final StreamConfigurationDuration[] mDurations;
|
||||
|
||||
}
|
||||
290
core/java/android/hardware/camera2/TonemapCurve.java
Normal file
290
core/java/android/hardware/camera2/TonemapCurve.java
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static com.android.internal.util.Preconditions.*;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.hardware.camera2.impl.HashCodeHelpers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Immutable class for describing a {@code 2 x M x 3} tonemap curve of floats.
|
||||
*
|
||||
* <p>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}.</p>
|
||||
*
|
||||
* <p>The total number of points {@code (Pin, Pout)} for each color channel can be no more than
|
||||
* {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS}.</p>
|
||||
*
|
||||
* <p>The coordinate system for each point is within the inclusive range
|
||||
* [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public final class TonemapCurve {
|
||||
/**
|
||||
* Lower bound tonemap value corresponding to pure black for a single color channel.
|
||||
*/
|
||||
public static final float LEVEL_BLACK = 0.0f;
|
||||
|
||||
/**
|
||||
* Upper bound tonemap value corresponding to a pure white for a single color channel.
|
||||
*/
|
||||
public static final float LEVEL_WHITE = 1.0f;
|
||||
|
||||
/**
|
||||
* Number of elements in a {@code (Pin, Pout)} point;
|
||||
*/
|
||||
public static final int POINT_SIZE = 2;
|
||||
|
||||
/**
|
||||
* Index of the red color channel curve.
|
||||
*/
|
||||
public static final int CHANNEL_RED = 0;
|
||||
/**
|
||||
* Index of the green color channel curve.
|
||||
*/
|
||||
public static final int CHANNEL_GREEN = 1;
|
||||
/**
|
||||
* Index of the blue color channel curve.
|
||||
*/
|
||||
public static final int CHANNEL_BLUE = 2;
|
||||
|
||||
/**
|
||||
* Create a new immutable TonemapCurve instance.
|
||||
*
|
||||
* <p>Values are stored as a contiguous {@code (Pin, Pout}) point.</p>
|
||||
*
|
||||
* <p>All parameters may have independent length but should have at most
|
||||
* {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS} * {@value #POINT_SIZE} elements.</p>
|
||||
*
|
||||
* <p>All sub-elements must be in the inclusive range of
|
||||
* [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
|
||||
*
|
||||
* <p>This constructor copies the array contents and does not retain ownership of the array.</p>
|
||||
*
|
||||
* @param elements An array of elements whose length is {@code CHANNEL_COUNT * rows * columns}
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if the {@code elements} array length is invalid,
|
||||
* if any of the subelems are not finite
|
||||
* @throws NullPointerException
|
||||
* if any of the parameters is {@code null}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public TonemapCurve(float[] red, float[] green, float[] blue) {
|
||||
// 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");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private static void checkArgumentArrayLengthDivisibleBy(float[] array,
|
||||
int divisible, String arrayName) {
|
||||
if (array.length % divisible != 0) {
|
||||
throw new IllegalArgumentException(arrayName + " size must be divisible by "
|
||||
+ divisible);
|
||||
}
|
||||
}
|
||||
|
||||
private static int checkArgumentColorChannel(int colorChannel) {
|
||||
switch (colorChannel) {
|
||||
case CHANNEL_RED:
|
||||
case CHANNEL_GREEN:
|
||||
case CHANNEL_BLUE:
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("colorChannel out of range");
|
||||
}
|
||||
|
||||
return 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
|
||||
*/
|
||||
public int getPointCount(int colorChannel) {
|
||||
checkArgumentColorChannel(colorChannel);
|
||||
|
||||
return getCurve(colorChannel).length / POINT_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the point for a color channel at a specified index.
|
||||
*
|
||||
* <p>The index must be at least 0 but no greater than {@link #getPointCount(int)} for
|
||||
* that {@code colorChannel}.</p>
|
||||
*
|
||||
* <p>All returned coordinates in the point are between the range of
|
||||
* [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public PointF getPoint(int colorChannel, int index) {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the color curve for a single color channel from this tonemap curve into the destination.
|
||||
*
|
||||
* <p>
|
||||
* <!--The output is encoded the same as in the constructor -->
|
||||
* Values are stored as packed {@code (Pin, Pout}) points, and there are a total of
|
||||
* {@link #getPointCount} points for that respective channel.</p>
|
||||
*
|
||||
* <p>All returned coordinates are between the range of
|
||||
* [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public void copyColorCurve(int colorChannel, float[] destination,
|
||||
int offset) {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this TonemapCurve is equal to another TonemapCurve.
|
||||
*
|
||||
* <p>Two matrices are equal if and only if all of their elements are
|
||||
* {@link Object#equals equal}.</p>
|
||||
*
|
||||
* @return {@code true} if the objects were equal, {@code false} otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
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;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
private final static int OFFSET_POINT_IN = 0;
|
||||
private final static int OFFSET_POINT_OUT = 1;
|
||||
|
||||
private final float[] mRed;
|
||||
private final float[] mGreen;
|
||||
private final float[] mBlue;
|
||||
|
||||
private int mHashCode;
|
||||
private boolean mHashCalculated = false;
|
||||
};
|
||||
@@ -253,4 +253,31 @@ public class ImageFormat {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether or not this is a public-visible {@code format}.
|
||||
*
|
||||
* <p>In particular, {@code @hide} formats will return {@code false}.</p>
|
||||
*
|
||||
* <p>Any other formats (including UNKNOWN) will return {@code false}.</p>
|
||||
*
|
||||
* @param format an integer format
|
||||
* @return a boolean
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static boolean isPublicFormat(int format) {
|
||||
switch (format) {
|
||||
case RGB_565:
|
||||
case NV16:
|
||||
case YUY2:
|
||||
case YV12:
|
||||
case NV21:
|
||||
case YUV_420_888:
|
||||
case RAW_SENSOR:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ public class PixelFormat
|
||||
info.bytesPerPixel = 1;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("unkonwon pixel format " + format);
|
||||
throw new IllegalArgumentException("unknown pixel format " + format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,4 +135,29 @@ public class PixelFormat
|
||||
|
||||
public int bytesPerPixel;
|
||||
public int bitsPerPixel;
|
||||
|
||||
/**
|
||||
* Determine whether or not this is a public-visible and non-deprecated {@code format}.
|
||||
*
|
||||
* <p>In particular, {@code @hide} formats will return {@code false}.</p>
|
||||
*
|
||||
* <p>Any other indirect formats (such as {@code TRANSPARENT} or {@code TRANSLUCENT})
|
||||
* will return {@code false}.</p>
|
||||
*
|
||||
* @param format an integer format
|
||||
* @return a boolean
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static boolean isPublicFormat(int format) {
|
||||
switch (format) {
|
||||
case RGBA_8888:
|
||||
case RGBX_8888:
|
||||
case RGB_888:
|
||||
case RGB_565:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user