diff --git a/core/api/current.txt b/core/api/current.txt index de540bf93e4bf..6c2ba6d4b780a 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -14779,6 +14779,7 @@ package android.graphics { method @Nullable public android.graphics.ColorSpace getColorSpace(); method @NonNull public android.graphics.Bitmap.Config getConfig(); method public int getDensity(); + method @Nullable public android.graphics.Gainmap getGainmap(); method public int getGenerationId(); method @NonNull public android.hardware.HardwareBuffer getHardwareBuffer(); method public int getHeight(); @@ -14794,6 +14795,7 @@ package android.graphics { method public int getScaledWidth(int); method public int getWidth(); method public boolean hasAlpha(); + method public boolean hasGainmap(); method public boolean hasMipMap(); method public boolean isMutable(); method public boolean isPremultiplied(); @@ -14805,6 +14807,7 @@ package android.graphics { method public void setColorSpace(@NonNull android.graphics.ColorSpace); method public void setConfig(@NonNull android.graphics.Bitmap.Config); method public void setDensity(int); + method public void setGainmap(@Nullable android.graphics.Gainmap); method public void setHasAlpha(boolean); method public void setHasMipMap(boolean); method public void setHeight(int); @@ -15338,6 +15341,26 @@ package android.graphics { ctor @Deprecated public EmbossMaskFilter(float[], float, float, float); } + public final class Gainmap { + ctor public Gainmap(@NonNull android.graphics.Bitmap); + method @NonNull public float getDisplayRatioForFullHdr(); + method @NonNull public float[] getEpsilonHdr(); + method @NonNull public float[] getEpsilonSdr(); + method @NonNull public android.graphics.Bitmap getGainmapContents(); + method @NonNull public float[] getGamma(); + method @NonNull public float getMinDisplayRatioForHdrTransition(); + method @NonNull public float[] getRatioMax(); + method @NonNull public float[] getRatioMin(); + method @NonNull public void setDisplayRatioForFullHdr(float); + method @NonNull public void setEpsilonHdr(float, float, float); + method @NonNull public void setEpsilonSdr(float, float, float); + method public void setGainmapContents(@NonNull android.graphics.Bitmap); + method @NonNull public void setGamma(float, float, float); + method @NonNull public void setMinDisplayRatioForHdrTransition(@FloatRange(from=1.0f) float); + method @NonNull public void setRatioMax(float, float, float); + method @NonNull public void setRatioMin(float, float, float); + } + public class HardwareBufferRenderer implements java.lang.AutoCloseable { ctor public HardwareBufferRenderer(@NonNull android.hardware.HardwareBuffer); method public void close(); diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 046373d671afe..b1abc2a1a6797 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -1899,7 +1899,6 @@ public final class Bitmap implements Parcelable { /** * Returns whether or not this Bitmap contains a Gainmap. - * @hide */ public boolean hasGainmap() { checkRecycled("Bitmap is recycled"); @@ -1908,7 +1907,6 @@ public final class Bitmap implements Parcelable { /** * Returns the gainmap or null if the bitmap doesn't contain a gainmap - * @hide */ public @Nullable Gainmap getGainmap() { checkRecycled("Bitmap is recycled"); @@ -1918,6 +1916,14 @@ public final class Bitmap implements Parcelable { return mGainmap; } + /** + * Sets a gainmap on this bitmap, or removes the gainmap if null + */ + public void setGainmap(@Nullable Gainmap gainmap) { + checkRecycled("Bitmap is recycled"); + nativeSetGainmap(mNativePtr, gainmap == null ? 0 : gainmap.mNativePtr); + } + /** * Fills the bitmap's pixels with the specified {@link Color}. * @@ -2403,6 +2409,7 @@ public final class Bitmap implements Parcelable { private static native void nativeSetImmutable(long nativePtr); private static native Gainmap nativeExtractGainmap(long nativePtr); + private static native void nativeSetGainmap(long bitmapPtr, long gainmapPtr); // ---------------- @CriticalNative ------------------- diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java index a25a60568510d..53f23c08dab62 100644 --- a/graphics/java/android/graphics/Gainmap.java +++ b/graphics/java/android/graphics/Gainmap.java @@ -16,6 +16,7 @@ package android.graphics; +import android.annotation.FloatRange; import android.annotation.NonNull; import libcore.util.NativeAllocationRegistry; @@ -24,104 +25,288 @@ import libcore.util.NativeAllocationRegistry; * Gainmap represents a mechanism for augmenting an SDR image to produce an HDR one with variable * display adjustment capability. * - * It is a combination of a set of metadata describing the gainmap, as well as either a 1 or 3 + * It is a combination of a set of metadata describing how to apply the gainmap, as well as either + * a 1 (such as {@link android.graphics.Bitmap.Config#ALPHA_8} or 3 + * (such as {@link android.graphics.Bitmap.Config#ARGB_8888} with the alpha channel ignored) * channel Bitmap that represents the gainmap data itself. * - * @hide + * When rendering to an {@link android.content.pm.ActivityInfo#COLOR_MODE_HDR} activity, the + * hardware accelerated {@link Canvas} will automatically apply the gainmap when sufficient + * HDR headroom is available. + * + *

Gainmap Structure

+ * + * The logical whole of a gainmap'd image consists of a base Bitmap that represents the original + * image as would be displayed without gainmap support in addition to a gainmap with a second + * enhancement image. In the case of a JPEG, the base image would be the typical 8-bit SDR image + * that the format is commonly associated with. The gainmap image is embedded alongside the base + * image, often at a lower resolution (such as 1/4th), along with some metadata to describe + * how to apply the gainmap. The gainmap image itself is then a greyscale image representing + * the transformation to apply onto the base image to reconstruct an HDR rendition of it. + * + * As such these "gainmap images" consist of 3 parts - a base {@link Bitmap} with a + * {@link Bitmap#getGainmap()} that returns an instance of this class which in turn contains + * the enhancement layer represented as another Bitmap, accessible via {@link #getGainmapContents()} + * + *

Applying a gainmap manually

+ * + * When doing custom rendering such as to an OpenGL ES or Vulkan context, the gainmap is not + * automatically applied. In such situations, the following steps are appropriate to render the + * gainmap in combination with the base image. + * + * Suppose our display has HDR to SDR ratio of H, and we wish to display an image with gainmap on + * this display. Let B be the pixel value from the base image in a color space that has the + * primaries of the base image and a linear transfer function. Let G be the pixel value from the + * gainmap. Let D be the output pixel in the same color space as B. The value of D is computed + * as follows: + * + * First, let W be a weight parameter determining how much the gainmap will be applied. + * W = clamp((log(H) - log(displayRatioHdr)) / + * (log(displayRatioHdr) - log(displayRatioSdr), 0, 1) + * + * Next, let L be the gainmap value in log space. We compute this from the value G that was + * sampled from the texture as follows: + * L = mix(log(gainmapRatioMin), log(gainmapRatioMax), pow(G, gainmapGamma)) + * + * Finally, apply the gainmap to compute D, the displayed pixel. If the base image is SDR then + * compute: + * D = (B + epsilonSdr) * exp(L * W) - epsilonHdr + * If the base image is HDR then compute: + * D = (B + epsilonHdr) * exp(L * (W - 1)) - epsilonSdr + * + * In the above math, log() is a natural logarithm and exp() is natural exponentiation. */ -public class Gainmap { - private final long mNativePtr; - private final Bitmap mGainmapImage; +public final class Gainmap { - // called from JNI and Bitmap_Delegate. - private Gainmap(Bitmap gainmapImage, long nativeGainmap, int allocationByteCount, - boolean fromMalloc) { + // Use a Holder to allow static initialization of Gainmap in the boot image. + private static class NoImagePreloadHolder { + public static final NativeAllocationRegistry sRegistry = + NativeAllocationRegistry.createMalloced( + Gainmap.class.getClassLoader(), nGetFinalizer()); + } + + final long mNativePtr; + private Bitmap mGainmapContents; + + // called from JNI + private Gainmap(Bitmap gainmapContents, long nativeGainmap) { if (nativeGainmap == 0) { throw new RuntimeException("internal error: native gainmap is 0"); } - mGainmapImage = gainmapImage; + mGainmapContents = gainmapContents; mNativePtr = nativeGainmap; - final NativeAllocationRegistry registry; - if (fromMalloc) { - registry = NativeAllocationRegistry.createMalloced( - Bitmap.class.getClassLoader(), nGetFinalizer(), allocationByteCount); - } else { - registry = NativeAllocationRegistry.createNonmalloced( - Bitmap.class.getClassLoader(), nGetFinalizer(), allocationByteCount); - } - registry.registerNativeAllocation(this, nativeGainmap); + NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, nativeGainmap); } /** - * Returns the image data of the gainmap represented as a Bitmap - * @return + * Creates a gainmap from a given Bitmap. The caller is responsible for setting the various + * fields to the desired values. The defaults are as follows: + * + * It is strongly recommended that at least the ratio max and display ratio HDR are adjusted + * to better suit the given gainmap contents. + */ + public Gainmap(@NonNull Bitmap gainmapContents) { + this(gainmapContents, nCreateEmpty()); + } + + /** + * @return Returns the image data of the gainmap represented as a Bitmap. This is represented + * as a Bitmap for broad API compatibility, however certain aspects of the Bitmap are ignored + * such as {@link Bitmap#getColorSpace()} or {@link Bitmap#getGainmap()} as they are not + * relevant to the gainmap's enhancement layer. */ @NonNull - public Bitmap getGainmapImage() { - return mGainmapImage; + public Bitmap getGainmapContents() { + return mGainmapContents; } /** - * Sets the gainmap max metadata. For single-plane gainmaps, r, g, and b should be the same. + * Sets the image data of the gainmap. This is the 1 or 3 channel enhancement layer to apply + * to the base image. This is represented as a Bitmap for broad API compatibility, however + * certain aspects of the Bitmap are ignored such as {@link Bitmap#getColorSpace()} or + * {@link Bitmap#getGainmap()} as they are not relevant to the gainmap's enhancement layer. + * + * @param bitmap The non-null bitmap to set as the gainmap's contents + */ + public void setGainmapContents(@NonNull Bitmap bitmap) { + // TODO: Validate here or leave native-side? + if (bitmap.isRecycled()) throw new IllegalArgumentException("Bitmap is recycled"); + nSetBitmap(mNativePtr, bitmap); + mGainmapContents = bitmap; + } + + /** + * Sets the gainmap ratio min. For single-plane gainmaps, r, g, and b should be the same. */ @NonNull - public void setGainmapMax(float r, float g, float b) { - nSetGainmapMax(mNativePtr, r, g, b); + public void setRatioMin(float r, float g, float b) { + nSetRatioMin(mNativePtr, r, g, b); } /** - * Gets the gainmap max metadata. For single-plane gainmaps, all 3 components should be the + * Gets the gainmap ratio max. For single-plane gainmaps, all 3 components should be the * same. The components are in r, g, b order. */ @NonNull - public float[] getGainmapMax() { + public float[] getRatioMin() { float[] ret = new float[3]; - nGetGainmapMax(mNativePtr, ret); + nGetRatioMin(mNativePtr, ret); return ret; } /** - * Sets the maximum HDR ratio for the gainmap + * Sets the gainmap ratio max. For single-plane gainmaps, r, g, and b should be the same. */ @NonNull - public void setHdrRatioMax(float max) { - nSetHdrRatioMax(mNativePtr, max); + public void setRatioMax(float r, float g, float b) { + nSetRatioMax(mNativePtr, r, g, b); } /** - * Gets the maximum HDR ratio for the gainmap + * Gets the gainmap ratio max. For single-plane gainmaps, all 3 components should be the + * same. The components are in r, g, b order. */ @NonNull - public float getHdrRatioMax() { - return nGetHdrRatioMax(mNativePtr); + public float[] getRatioMax() { + float[] ret = new float[3]; + nGetRatioMax(mNativePtr, ret); + return ret; } /** - * Sets the maximum HDR ratio for the gainmap + * Sets the gainmap gamma. For single-plane gainmaps, r, g, and b should be the same. */ @NonNull - public void setHdrRatioMin(float min) { - nSetHdrRatioMin(mNativePtr, min); + public void setGamma(float r, float g, float b) { + nSetGamma(mNativePtr, r, g, b); } /** - * Gets the maximum HDR ratio for the gainmap + * Gets the gainmap gamma. For single-plane gainmaps, all 3 components should be the + * same. The components are in r, g, b order. */ @NonNull - public float getHdrRatioMin() { - return nGetHdrRatioMin(mNativePtr); + public float[] getGamma() { + float[] ret = new float[3]; + nGetGamma(mNativePtr, ret); + return ret; + } + + /** + * Sets the sdr epsilon which is used to avoid numerical instability. + * For single-plane gainmaps, r, g, and b should be the same. + */ + @NonNull + public void setEpsilonSdr(float r, float g, float b) { + nSetEpsilonSdr(mNativePtr, r, g, b); + } + + /** + * Gets the sdr epsilon. For single-plane gainmaps, all 3 components should be the + * same. The components are in r, g, b order. + */ + @NonNull + public float[] getEpsilonSdr() { + float[] ret = new float[3]; + nGetEpsilonSdr(mNativePtr, ret); + return ret; + } + + /** + * Sets the hdr epsilon which is used to avoid numerical instability. + * For single-plane gainmaps, r, g, and b should be the same. + */ + @NonNull + public void setEpsilonHdr(float r, float g, float b) { + nSetEpsilonHdr(mNativePtr, r, g, b); + } + + /** + * Gets the hdr epsilon. For single-plane gainmaps, all 3 components should be the + * same. The components are in r, g, b order. + */ + @NonNull + public float[] getEpsilonHdr() { + float[] ret = new float[3]; + nGetEpsilonHdr(mNativePtr, ret); + return ret; + } + + /** + * Sets the hdr/sdr ratio at which point the gainmap is fully applied. + * @param max The hdr/sdr ratio at which the gainmap is fully applied. Must be >= 1.0f + */ + @NonNull + public void setDisplayRatioForFullHdr(float max) { + if (!Float.isFinite(max) || max < 1f) { + throw new IllegalArgumentException( + "setDisplayRatioForFullHdr must be >= 1.0f, got = " + max); + } + nSetDisplayRatioHdr(mNativePtr, max); + } + + /** + * Gets the hdr/sdr ratio at which point the gainmap is fully applied. + */ + @NonNull + public float getDisplayRatioForFullHdr() { + return nGetDisplayRatioHdr(mNativePtr); + } + + /** + * Sets the hdr/sdr ratio below which only the SDR image is displayed. + * @param min The minimum hdr/sdr ratio at which to begin applying the gainmap. Must be >= 1.0f + */ + @NonNull + public void setMinDisplayRatioForHdrTransition(@FloatRange(from = 1.0f) float min) { + if (!Float.isFinite(min) || min < 1f) { + throw new IllegalArgumentException( + "setMinDisplayRatioForHdrTransition must be >= 1.0f, got = " + min); + } + nSetDisplayRatioSdr(mNativePtr, min); + } + + /** + * Gets the hdr/sdr ratio below which only the SDR image is displayed. + */ + @NonNull + public float getMinDisplayRatioForHdrTransition() { + return nGetDisplayRatioSdr(mNativePtr); } private static native long nGetFinalizer(); + private static native long nCreateEmpty(); - private static native void nSetGainmapMax(long ptr, float r, float g, float b); - private static native void nGetGainmapMax(long ptr, float[] components); + private static native void nSetBitmap(long ptr, Bitmap bitmap); - private static native void nSetHdrRatioMax(long ptr, float max); - private static native float nGetHdrRatioMax(long ptr); + private static native void nSetRatioMin(long ptr, float r, float g, float b); + private static native void nGetRatioMin(long ptr, float[] components); - private static native void nSetHdrRatioMin(long ptr, float min); - private static native float nGetHdrRatioMin(long ptr); + private static native void nSetRatioMax(long ptr, float r, float g, float b); + private static native void nGetRatioMax(long ptr, float[] components); + + private static native void nSetGamma(long ptr, float r, float g, float b); + private static native void nGetGamma(long ptr, float[] components); + + private static native void nSetEpsilonSdr(long ptr, float r, float g, float b); + private static native void nGetEpsilonSdr(long ptr, float[] components); + + private static native void nSetEpsilonHdr(long ptr, float r, float g, float b); + private static native void nGetEpsilonHdr(long ptr, float[] components); + + private static native void nSetDisplayRatioHdr(long ptr, float max); + private static native float nGetDisplayRatioHdr(long ptr); + + private static native void nSetDisplayRatioSdr(long ptr, float min); + private static native float nGetDisplayRatioSdr(long ptr); } diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp index 6d7c72772c7e1..5bf53d0c17908 100644 --- a/libs/hwui/hwui/ImageDecoder.cpp +++ b/libs/hwui/hwui/ImageDecoder.cpp @@ -506,6 +506,9 @@ SkCodec::Result ImageDecoder::extractGainmap(Bitmap* destination) { decoder.mOverrideOrigin.emplace(getOrigin()); // Update mDecodeSize / mTargetSize for the overridden origin decoder.setTargetSize(decoder.width(), decoder.height()); + if (decoder.gray()) { + decoder.setOutColorType(kGray_8_SkColorType); + } const bool isScaled = width() != mTargetSize.width() || height() != mTargetSize.height(); @@ -528,6 +531,9 @@ SkCodec::Result ImageDecoder::extractGainmap(Bitmap* destination) { } SkImageInfo bitmapInfo = decoder.getOutputInfo(); + if (bitmapInfo.colorType() == kGray_8_SkColorType) { + bitmapInfo = bitmapInfo.makeColorType(kAlpha_8_SkColorType); + } SkBitmap bm; if (!bm.setInfo(bitmapInfo)) { diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp index 10c287d1e07df..aee5242c72d31 100644 --- a/libs/hwui/jni/Bitmap.cpp +++ b/libs/hwui/jni/Bitmap.cpp @@ -1269,6 +1269,13 @@ static jobject Bitmap_extractGainmap(JNIEnv* env, jobject, jlong bitmapHandle) { return Gainmap_extractFromBitmap(env, bitmapHolder->bitmap()); } +static void Bitmap_setGainmap(JNIEnv*, jobject, jlong bitmapHandle, jlong gainmapPtr) { + LocalScopedBitmap bitmapHolder(bitmapHandle); + if (!bitmapHolder.valid()) return; + uirenderer::Gainmap* gainmap = reinterpret_cast(gainmapPtr); + bitmapHolder->bitmap().setGainmap(sp::fromExisting(gainmap)); +} + /////////////////////////////////////////////////////////////////////////////// static const JNINativeMethod gBitmapMethods[] = { @@ -1320,6 +1327,7 @@ static const JNINativeMethod gBitmapMethods[] = { {"nativeIsSRGBLinear", "(J)Z", (void*)Bitmap_isSRGBLinear}, {"nativeSetImmutable", "(J)V", (void*)Bitmap_setImmutable}, {"nativeExtractGainmap", "(J)Landroid/graphics/Gainmap;", (void*)Bitmap_extractGainmap}, + {"nativeSetGainmap", "(JJ)V", (void*)Bitmap_setGainmap}, // ------------ @CriticalNative ---------------- {"nativeIsImmutable", "(J)Z", (void*)Bitmap_isImmutable}, diff --git a/libs/hwui/jni/Gainmap.cpp b/libs/hwui/jni/Gainmap.cpp index f2efbc7b833e5..9cd3fb0799d76 100644 --- a/libs/hwui/jni/Gainmap.cpp +++ b/libs/hwui/jni/Gainmap.cpp @@ -45,20 +45,18 @@ static int getCreateFlags(const sk_sp& bitmap) { jobject Gainmap_extractFromBitmap(JNIEnv* env, const Bitmap& bitmap) { auto gainmap = bitmap.gainmap(); jobject jGainmapImage; - size_t allocationSize; { // Scope to guard the release of nativeBitmap auto nativeBitmap = gainmap->bitmap; const int createFlags = getCreateFlags(nativeBitmap); - allocationSize = nativeBitmap->getAllocationByteCount(); jGainmapImage = bitmap::createBitmap(env, nativeBitmap.release(), createFlags); } // Grab a ref for the jobject gainmap->incStrong(0); jobject obj = env->NewObject(gGainmap_class, gGainmap_constructorMethodID, jGainmapImage, - gainmap.get(), allocationSize + sizeof(Gainmap), true); + gainmap.get()); if (env->ExceptionCheck() != 0) { // sadtrombone @@ -77,47 +75,109 @@ static jlong Gainmap_getNativeFinalizer(JNIEnv*, jobject) { return static_cast(reinterpret_cast(&Gainmap_destructor)); } -static void Gainmap_setGainmapMax(JNIEnv*, jobject, jlong gainmapPtr, jfloat r, jfloat g, - jfloat b) { - fromJava(gainmapPtr)->info.fLogRatioMax = {r, g, b, 1.f}; +jlong Gainmap_createEmpty(JNIEnv*, jobject) { + Gainmap* gainmap = new Gainmap(); + gainmap->incStrong(0); + return static_cast(reinterpret_cast(gainmap)); } -static void Gainmap_getGainmapMax(JNIEnv* env, jobject, jlong gainmapPtr, jfloatArray components) { - const auto ratioMax = fromJava(gainmapPtr)->info.fLogRatioMax; - jfloat buf[3]{ratioMax.fR, ratioMax.fG, ratioMax.fB}; +static void Gainmap_setBitmap(JNIEnv* env, jobject, jlong gainmapPtr, jobject jBitmap) { + android::Bitmap* bitmap = GraphicsJNI::getNativeBitmap(env, jBitmap); + fromJava(gainmapPtr)->bitmap = sk_ref_sp(bitmap); +} + +static void Gainmap_setRatioMin(JNIEnv*, jobject, jlong gainmapPtr, jfloat r, jfloat g, jfloat b) { + fromJava(gainmapPtr)->info.fGainmapRatioMin = {r, g, b, 1.f}; +} + +static void Gainmap_getRatioMin(JNIEnv* env, jobject, jlong gainmapPtr, jfloatArray components) { + const auto value = fromJava(gainmapPtr)->info.fGainmapRatioMin; + jfloat buf[3]{value.fR, value.fG, value.fB}; env->SetFloatArrayRegion(components, 0, 3, buf); } -static void Gainmap_setHdrRatioMax(JNIEnv*, jobject, jlong gainmapPtr, jfloat max) { - fromJava(gainmapPtr)->info.fHdrRatioMax = max; +static void Gainmap_setRatioMax(JNIEnv*, jobject, jlong gainmapPtr, jfloat r, jfloat g, jfloat b) { + fromJava(gainmapPtr)->info.fGainmapRatioMax = {r, g, b, 1.f}; } -static jfloat Gainmap_getHdrRatioMax(JNIEnv*, jobject, jlong gainmapPtr) { - return fromJava(gainmapPtr)->info.fHdrRatioMax; +static void Gainmap_getRatioMax(JNIEnv* env, jobject, jlong gainmapPtr, jfloatArray components) { + const auto value = fromJava(gainmapPtr)->info.fGainmapRatioMax; + jfloat buf[3]{value.fR, value.fG, value.fB}; + env->SetFloatArrayRegion(components, 0, 3, buf); } -static void Gainmap_setHdrRatioMin(JNIEnv*, jobject, jlong gainmapPtr, jfloat min) { - fromJava(gainmapPtr)->info.fHdrRatioMin = min; +static void Gainmap_setGamma(JNIEnv*, jobject, jlong gainmapPtr, jfloat r, jfloat g, jfloat b) { + fromJava(gainmapPtr)->info.fGainmapGamma = {r, g, b, 1.f}; } -static jfloat Gainmap_getHdrRatioMin(JNIEnv*, jobject, jlong gainmapPtr) { - return fromJava(gainmapPtr)->info.fHdrRatioMin; +static void Gainmap_getGamma(JNIEnv* env, jobject, jlong gainmapPtr, jfloatArray components) { + const auto value = fromJava(gainmapPtr)->info.fGainmapGamma; + jfloat buf[3]{value.fR, value.fG, value.fB}; + env->SetFloatArrayRegion(components, 0, 3, buf); +} + +static void Gainmap_setEpsilonSdr(JNIEnv*, jobject, jlong gainmapPtr, jfloat r, jfloat g, + jfloat b) { + fromJava(gainmapPtr)->info.fEpsilonSdr = {r, g, b, 1.f}; +} + +static void Gainmap_getEpsilonSdr(JNIEnv* env, jobject, jlong gainmapPtr, jfloatArray components) { + const auto value = fromJava(gainmapPtr)->info.fEpsilonSdr; + jfloat buf[3]{value.fR, value.fG, value.fB}; + env->SetFloatArrayRegion(components, 0, 3, buf); +} + +static void Gainmap_setEpsilonHdr(JNIEnv*, jobject, jlong gainmapPtr, jfloat r, jfloat g, + jfloat b) { + fromJava(gainmapPtr)->info.fEpsilonHdr = {r, g, b, 1.f}; +} + +static void Gainmap_getEpsilonHdr(JNIEnv* env, jobject, jlong gainmapPtr, jfloatArray components) { + const auto value = fromJava(gainmapPtr)->info.fEpsilonHdr; + jfloat buf[3]{value.fR, value.fG, value.fB}; + env->SetFloatArrayRegion(components, 0, 3, buf); +} + +static void Gainmap_setDisplayRatioHdr(JNIEnv*, jobject, jlong gainmapPtr, jfloat max) { + fromJava(gainmapPtr)->info.fDisplayRatioHdr = max; +} + +static jfloat Gainmap_getDisplayRatioHdr(JNIEnv*, jobject, jlong gainmapPtr) { + return fromJava(gainmapPtr)->info.fDisplayRatioHdr; +} + +static void Gainmap_setDisplayRatioSdr(JNIEnv*, jobject, jlong gainmapPtr, jfloat min) { + fromJava(gainmapPtr)->info.fDisplayRatioSdr = min; +} + +static jfloat Gainmap_getDisplayRatioSdr(JNIEnv*, jobject, jlong gainmapPtr) { + return fromJava(gainmapPtr)->info.fDisplayRatioSdr; } static const JNINativeMethod gGainmapMethods[] = { {"nGetFinalizer", "()J", (void*)Gainmap_getNativeFinalizer}, - {"nSetGainmapMax", "(JFFF)V", (void*)Gainmap_setGainmapMax}, - {"nGetGainmapMax", "(J[F)V", (void*)Gainmap_getGainmapMax}, - {"nSetHdrRatioMax", "(JF)V", (void*)Gainmap_setHdrRatioMax}, - {"nGetHdrRatioMax", "(J)F", (void*)Gainmap_getHdrRatioMax}, - {"nSetHdrRatioMin", "(JF)V", (void*)Gainmap_setHdrRatioMin}, - {"nGetHdrRatioMin", "(J)F", (void*)Gainmap_getHdrRatioMin}, + {"nCreateEmpty", "()J", (void*)Gainmap_createEmpty}, + {"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*)Gainmap_setBitmap}, + {"nSetRatioMin", "(JFFF)V", (void*)Gainmap_setRatioMin}, + {"nGetRatioMin", "(J[F)V", (void*)Gainmap_getRatioMin}, + {"nSetRatioMax", "(JFFF)V", (void*)Gainmap_setRatioMax}, + {"nGetRatioMax", "(J[F)V", (void*)Gainmap_getRatioMax}, + {"nSetGamma", "(JFFF)V", (void*)Gainmap_setGamma}, + {"nGetGamma", "(J[F)V", (void*)Gainmap_getGamma}, + {"nSetEpsilonSdr", "(JFFF)V", (void*)Gainmap_setEpsilonSdr}, + {"nGetEpsilonSdr", "(J[F)V", (void*)Gainmap_getEpsilonSdr}, + {"nSetEpsilonHdr", "(JFFF)V", (void*)Gainmap_setEpsilonHdr}, + {"nGetEpsilonHdr", "(J[F)V", (void*)Gainmap_getEpsilonHdr}, + {"nSetDisplayRatioHdr", "(JF)V", (void*)Gainmap_setDisplayRatioHdr}, + {"nGetDisplayRatioHdr", "(J)F", (void*)Gainmap_getDisplayRatioHdr}, + {"nSetDisplayRatioSdr", "(JF)V", (void*)Gainmap_setDisplayRatioSdr}, + {"nGetDisplayRatioSdr", "(J)F", (void*)Gainmap_getDisplayRatioSdr}, }; int register_android_graphics_Gainmap(JNIEnv* env) { gGainmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Gainmap")); gGainmap_constructorMethodID = - GetMethodIDOrDie(env, gGainmap_class, "", "(Landroid/graphics/Bitmap;JIZ)V"); + GetMethodIDOrDie(env, gGainmap_class, "", "(Landroid/graphics/Bitmap;J)V"); return android::RegisterMethodsOrDie(env, "android/graphics/Gainmap", gGainmapMethods, NELEM(gGainmapMethods)); }