From 12d371af853554e30905e0b7922e9d6912e2efab Mon Sep 17 00:00:00 2001
From: Sally Qi Composed of the following -
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index ef1e7bfc66511..701e20c499dac 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -161,11 +161,17 @@ public class BitmapFactory {
* be thrown by the decode methods when setting a non-RGB color space
* such as {@link ColorSpace.Named#CIE_LAB Lab}.
The specified color space's transfer function must be + *
+ * Prior to {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+ * the specified color space's transfer function must be
* an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}. An
* IllegalArgumentException will be thrown by the decode methods
* if calling {@link ColorSpace.Rgb#getTransferParameters()} on the
- * specified color space returns null.
After decode, the bitmap's color space is stored in * {@link #outColorSpace}.
@@ -458,7 +464,11 @@ public class BitmapFactory { throw new IllegalArgumentException("The destination color space must use the " + "RGB color model"); } - if (((ColorSpace.Rgb) opts.inPreferredColorSpace).getTransferParameters() == null) { + if (!opts.inPreferredColorSpace.equals(ColorSpace.get(ColorSpace.Named.BT2020_HLG)) + && !opts.inPreferredColorSpace.equals( + ColorSpace.get(ColorSpace.Named.BT2020_PQ)) + && ((ColorSpace.Rgb) opts.inPreferredColorSpace) + .getTransferParameters() == null) { throw new IllegalArgumentException("The destination color space must use an " + "ICC parametric transfer function"); } diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java index 31df474eb10cf..2427dec169d6f 100644 --- a/graphics/java/android/graphics/ColorSpace.java +++ b/graphics/java/android/graphics/ColorSpace.java @@ -199,6 +199,8 @@ public abstract class ColorSpace { private static final float[] SRGB_PRIMARIES = { 0.640f, 0.330f, 0.300f, 0.600f, 0.150f, 0.060f }; private static final float[] NTSC_1953_PRIMARIES = { 0.67f, 0.33f, 0.21f, 0.71f, 0.14f, 0.08f }; + private static final float[] BT2020_PRIMARIES = + { 0.708f, 0.292f, 0.170f, 0.797f, 0.131f, 0.046f }; /** * A gray color space does not have meaningful primaries, so we use this arbitrary set. */ @@ -208,6 +210,12 @@ public abstract class ColorSpace { private static final Rgb.TransferParameters SRGB_TRANSFER_PARAMETERS = new Rgb.TransferParameters(1 / 1.055, 0.055 / 1.055, 1 / 12.92, 0.04045, 2.4); + private static final Rgb.TransferParameters BT2020_HLG_TRANSFER_PARAMETERS = + new Rgb.TransferParameters(2.0f, 2.0f, 1 / 0.17883277f, + 0.28466892f, 0.5599107f, 0.0f, -3.0f, true); + private static final Rgb.TransferParameters BT2020_PQ_TRANSFER_PARAMETERS = + new Rgb.TransferParameters(107 / 128.0f, 1.0f, 32 / 2523.0f, + 2413 / 128.0f, -2392 / 128.0f, 8192 / 1305.0f, -2.0f, true); // See static initialization block next to #get(Named) private static final ColorSpace[] sNamedColorSpaces = new ColorSpace[Named.values().length]; @@ -703,7 +711,29 @@ public abstract class ColorSpace { *{@link ColorSpace.Rgb RGB} color space BT.2100 standardized as + * Hybrid Log Gamma encoding.
+ *| Property | Value | |||
|---|---|---|---|---|
| Name | Hybrid Log Gamma encoding | |||
| CIE standard illuminant | D65 | |||
| Range | \([0..1]\) | |||
{@link ColorSpace.Rgb RGB} color space BT.2100 standardized as + * Perceptual Quantizer encoding.
+ *| Property | Value | |||
|---|---|---|---|---|
| Name | Perceptual Quantizer encoding | |||
| CIE standard illuminant | D65 | |||
| Range | \([0..1]\) | |||
Defines the parameters for the ICC parametric curve type 3, as * defined in ICC.1:2004-10, section 10.15.
@@ -2219,7 +2365,7 @@ public abstract class ColorSpace { * @throws IllegalArgumentException If the parameters form an invalid transfer function */ public TransferParameters(double a, double b, double c, double d, double g) { - this(a, b, c, d, 0.0, 0.0, g); + this(a, b, c, d, 0.0, 0.0, g, false); } /** @@ -2238,51 +2384,7 @@ public abstract class ColorSpace { */ public TransferParameters(double a, double b, double c, double d, double e, double f, double g) { - - if (Double.isNaN(a) || Double.isNaN(b) || Double.isNaN(c) || - Double.isNaN(d) || Double.isNaN(e) || Double.isNaN(f) || - Double.isNaN(g)) { - throw new IllegalArgumentException("Parameters cannot be NaN"); - } - - // Next representable float after 1.0 - // We use doubles here but the representation inside our native code is often floats - if (!(d >= 0.0 && d <= 1.0f + Math.ulp(1.0f))) { - throw new IllegalArgumentException("Parameter d must be in the range [0..1], " + - "was " + d); - } - - if (d == 0.0 && (a == 0.0 || g == 0.0)) { - throw new IllegalArgumentException( - "Parameter a or g is zero, the transfer function is constant"); - } - - if (d >= 1.0 && c == 0.0) { - throw new IllegalArgumentException( - "Parameter c is zero, the transfer function is constant"); - } - - if ((a == 0.0 || g == 0.0) && c == 0.0) { - throw new IllegalArgumentException("Parameter a or g is zero," + - " and c is zero, the transfer function is constant"); - } - - if (c < 0.0) { - throw new IllegalArgumentException("The transfer function must be increasing"); - } - - if (a < 0.0 || g < 0.0) { - throw new IllegalArgumentException("The transfer function must be " + - "positive or increasing"); - } - - this.a = a; - this.b = b; - this.c = c; - this.d = d; - this.e = e; - this.f = f; - this.g = g; + this(a, b, c, d, e, f, g, false); } @SuppressWarnings("SimplifiableIfStatement") @@ -2357,6 +2459,36 @@ public abstract class ColorSpace { private static native long nativeCreate(float a, float b, float c, float d, float e, float f, float g, float[] xyz); + private static DoubleUnaryOperator generateOETF(TransferParameters function) { + boolean isNonCurveTransferParameters = function.equals(BT2020_HLG_TRANSFER_PARAMETERS) + || function.equals(BT2020_PQ_TRANSFER_PARAMETERS); + if (isNonCurveTransferParameters) { + return function.f == 0.0 && function.g < 0.0 ? x -> transferHLGOETF(x) + : x -> transferST2048OETF(x); + } else { + return function.e == 0.0 && function.f == 0.0 + ? x -> rcpResponse(x, function.a, function.b, + function.c, function.d, function.g) + : x -> rcpResponse(x, function.a, function.b, function.c, + function.d, function.e, function.f, function.g); + } + } + + private static DoubleUnaryOperator generateEOTF(TransferParameters function) { + boolean isNonCurveTransferParameters = function.equals(BT2020_HLG_TRANSFER_PARAMETERS) + || function.equals(BT2020_PQ_TRANSFER_PARAMETERS); + if (isNonCurveTransferParameters) { + return function.f == 0.0 && function.g < 0.0 ? x -> transferHLGEOTF(x) + : x -> transferST2048EOTF(x); + } else { + return function.e == 0.0 && function.f == 0.0 + ? x -> response(x, function.a, function.b, + function.c, function.d, function.g) + : x -> response(x, function.a, function.b, function.c, + function.d, function.e, function.f, function.g); + } + } + /** *Creates a new RGB color space using a 3x3 column-major transform matrix.
* The transform matrix must convert from the RGB space to the profile connection
@@ -2553,16 +2685,8 @@ public abstract class ColorSpace {
@NonNull TransferParameters function,
@IntRange(from = MIN_ID, to = MAX_ID) int id) {
this(name, primaries, whitePoint, transform,
- function.e == 0.0 && function.f == 0.0 ?
- x -> rcpResponse(x, function.a, function.b,
- function.c, function.d, function.g) :
- x -> rcpResponse(x, function.a, function.b, function.c,
- function.d, function.e, function.f, function.g),
- function.e == 0.0 && function.f == 0.0 ?
- x -> response(x, function.a, function.b,
- function.c, function.d, function.g) :
- x -> response(x, function.a, function.b, function.c,
- function.d, function.e, function.f, function.g),
+ generateOETF(function),
+ generateEOTF(function),
0.0f, 1.0f, function, id);
}
@@ -3063,7 +3187,12 @@ public abstract class ColorSpace {
*/
@Nullable
public TransferParameters getTransferParameters() {
- return mTransferParameters;
+ if (mTransferParameters != null
+ && !mTransferParameters.equals(BT2020_PQ_TRANSFER_PARAMETERS)
+ && !mTransferParameters.equals(BT2020_HLG_TRANSFER_PARAMETERS)) {
+ return mTransferParameters;
+ }
+ return null;
}
@Override
diff --git a/libs/hwui/jni/Graphics.cpp b/libs/hwui/jni/Graphics.cpp
index 6a3bc8fe11527..c8358497ad62c 100644
--- a/libs/hwui/jni/Graphics.cpp
+++ b/libs/hwui/jni/Graphics.cpp
@@ -576,14 +576,22 @@ jobject GraphicsJNI::getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace,
LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix));
skcms_TransferFunction transferParams;
- // We can only handle numerical transfer functions at the moment
- LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams));
+ decodeColorSpace->transferFn(&transferParams);
+ auto res = skcms_TransferFunction_getType(&transferParams);
+ LOG_ALWAYS_FATAL_IF(res == skcms_TFType_HLGinvish || res == skcms_TFType_Invalid);
- jobject params = env->NewObject(gTransferParameters_class,
- gTransferParameters_constructorMethodID,
- transferParams.a, transferParams.b, transferParams.c,
- transferParams.d, transferParams.e, transferParams.f,
- transferParams.g);
+ jobject params;
+ if (res == skcms_TFType_PQish || res == skcms_TFType_HLGish) {
+ params = env->NewObject(gTransferParameters_class, gTransferParameters_constructorMethodID,
+ transferParams.a, transferParams.b, transferParams.c,
+ transferParams.d, transferParams.e, transferParams.f,
+ transferParams.g, true);
+ } else {
+ params = env->NewObject(gTransferParameters_class, gTransferParameters_constructorMethodID,
+ transferParams.a, transferParams.b, transferParams.c,
+ transferParams.d, transferParams.e, transferParams.f,
+ transferParams.g, false);
+ }
jfloatArray xyzArray = env->NewFloatArray(9);
jfloat xyz[9] = {
@@ -808,8 +816,8 @@ int register_android_graphics_Graphics(JNIEnv* env)
gTransferParameters_class = MakeGlobalRefOrDie(env, FindClassOrDie(env,
"android/graphics/ColorSpace$Rgb$TransferParameters"));
- gTransferParameters_constructorMethodID = GetMethodIDOrDie(env, gTransferParameters_class,
- "