DynamicRange.java
/*
* Copyright 2023 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 androidx.camera.core;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** A representation of the dynamic range of an image. */
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public final class DynamicRange {
/** Standard Dynamic Range (SDR) format. */
public static final int FORMAT_SDR = 0;
//------------------------------------------------------------------------------//
// HDR Formats //
//------------------------------------------------------------------------------//
/**
* An unspecified High Dynamic Range (HDR) format which allows the device to determine the
* underlying dynamic range format.
*/
public static final int FORMAT_HDR_UNSPECIFIED = 1;
/** Hybrid Log Gamma (HLG) dynamic range format. */
public static final int FORMAT_HLG = FORMAT_HDR_UNSPECIFIED + 1;
/** HDR10 dynamic range format. */
public static final int FORMAT_HDR10 = FORMAT_HDR_UNSPECIFIED + 2;
/** HDR10+ dynamic range format. */
public static final int FORMAT_HDR10_PLUS = FORMAT_HDR_UNSPECIFIED + 3;
/** Dolby Vision dynamic range format. */
public static final int FORMAT_DOLBY_VISION = FORMAT_HDR_UNSPECIFIED + 4;
//------------------------------------------------------------------------------//
/** Bit depth is unspecified and may be determined automatically by the device. */
public static final int BIT_DEPTH_UNSPECIFIED = 0;
/** Eight-bit bit depth. */
public static final int BIT_DEPTH_8_BIT = 8;
/** Ten-bit bit depth. */
public static final int BIT_DEPTH_10_BIT = 10;
@RestrictTo(RestrictTo.Scope.LIBRARY)
@IntDef({FORMAT_SDR, FORMAT_HDR_UNSPECIFIED, FORMAT_HLG, FORMAT_HDR10, FORMAT_HDR10_PLUS,
FORMAT_DOLBY_VISION})
@Retention(RetentionPolicy.SOURCE)
public @interface DynamicRangeFormat {
}
@RestrictTo(RestrictTo.Scope.LIBRARY)
@IntDef({BIT_DEPTH_UNSPECIFIED, BIT_DEPTH_8_BIT, BIT_DEPTH_10_BIT})
@Retention(RetentionPolicy.SOURCE)
public @interface BitDepth {
}
/** A dynamic range representing 8-bit standard dynamic range (SDR). */
@NonNull
public static final DynamicRange SDR = new DynamicRange(FORMAT_SDR, BIT_DEPTH_8_BIT);
/**
* A dynamic range representing 10-bit high dynamic range (HDR) with unspecified format.
*
* <p>The HDR format is unspecified, and may defer to device defaults
* when used to select a dynamic range.
*/
@NonNull
public static final DynamicRange HDR_UNSPECIFIED_10_BIT =
new DynamicRange(FORMAT_HDR_UNSPECIFIED, BIT_DEPTH_10_BIT);
private final @DynamicRangeFormat int mFormat;
private final @BitDepth int mBitDepth;
/**
* Creates a dynamic range representation from a format and bit depth.
*
* <p>This constructor is left public for testing purposes. It does not do any verification that
* the provided arguments are a valid combination of format and bit depth.
*
* @param format The dynamic range format.
* @param bitDepth The bit depth.
*/
public DynamicRange(
@DynamicRangeFormat int format,
@BitDepth int bitDepth) {
mFormat = format;
mBitDepth = bitDepth;
}
/**
* Returns the dynamic range format.
*
* @return The dynamic range format. Possible values are {@link #FORMAT_SDR},
* {@link #FORMAT_HLG}, {@link #FORMAT_HDR10}, {@link #FORMAT_HDR10_PLUS}, or
* {@link #FORMAT_DOLBY_VISION}.
*/
@DynamicRangeFormat
public int getFormat() {
return mFormat;
}
/**
* Returns the bit depth used by this dynamic range configuration.
*
* <p>Common values are {@link #BIT_DEPTH_8_BIT}, such as for {@link #FORMAT_SDR} or
* {@link #BIT_DEPTH_10_BIT}, such as for {@link #FORMAT_HDR10}.
*
* @return The bit depth. Possible values are {@link #BIT_DEPTH_8_BIT},
* {@link #BIT_DEPTH_10_BIT}, or {@link #BIT_DEPTH_UNSPECIFIED}.
*/
@BitDepth
public int getBitDepth() {
return mBitDepth;
}
@NonNull
@Override
public String toString() {
return "DynamicRange@" + Integer.toHexString(System.identityHashCode(this)) + "{"
+ "format=" + getFormatLabel(mFormat) + ", "
+ "bitDepth=" + mBitDepth
+ "}";
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof DynamicRange) {
DynamicRange that = (DynamicRange) o;
return this.mFormat == that.getFormat()
&& this.mBitDepth == that.getBitDepth();
}
return false;
}
@Override
public int hashCode() {
int hashCode = 1;
hashCode *= 1000003;
hashCode ^= mFormat;
hashCode *= 1000003;
hashCode ^= mBitDepth;
return hashCode;
}
@NonNull
private static String getFormatLabel(@DynamicRangeFormat int format) {
switch (format) {
case FORMAT_SDR: return "FORMAT_SDR";
case FORMAT_HDR_UNSPECIFIED: return "FORMAT_HDR_UNSPECIFIED";
case FORMAT_HLG: return "FORMAT_HLG";
case FORMAT_HDR10: return "FORMAT_HDR10";
case FORMAT_HDR10_PLUS: return "FORMAT_HDR10_PLUS";
case FORMAT_DOLBY_VISION: return "FORMAT_DOLBY_VISION";
}
return "<Unknown>";
}
}