| /* |
| * Copyright (C) 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. |
| */ |
| |
| #include <Gainmap.h> |
| |
| #ifdef __ANDROID__ |
| #include <binder/Parcel.h> |
| #endif |
| |
| #include "Bitmap.h" |
| #include "GraphicsJNI.h" |
| #include "ScopedParcel.h" |
| #include "graphics_jni_helpers.h" |
| |
| namespace android { |
| |
| static jclass gGainmap_class; |
| static jmethodID gGainmap_constructorMethodID; |
| |
| using namespace uirenderer; |
| |
| static Gainmap* fromJava(jlong gainmap) { |
| return reinterpret_cast<Gainmap*>(gainmap); |
| } |
| |
| static int getCreateFlags(const sk_sp<Bitmap>& bitmap) { |
| int flags = 0; |
| if (bitmap->info().alphaType() == kPremul_SkAlphaType) { |
| flags |= android::bitmap::kBitmapCreateFlag_Premultiplied; |
| } |
| if (!bitmap->isImmutable()) { |
| flags |= android::bitmap::kBitmapCreateFlag_Mutable; |
| } |
| return flags; |
| } |
| |
| jobject Gainmap_extractFromBitmap(JNIEnv* env, const Bitmap& bitmap) { |
| auto gainmap = bitmap.gainmap(); |
| jobject jGainmapImage; |
| |
| { |
| // Scope to guard the release of nativeBitmap |
| auto nativeBitmap = gainmap->bitmap; |
| const int createFlags = getCreateFlags(nativeBitmap); |
| 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()); |
| |
| if (env->ExceptionCheck() != 0) { |
| // sadtrombone |
| gainmap->decStrong(0); |
| ALOGE("*** Uncaught exception returned from Java call!\n"); |
| env->ExceptionDescribe(); |
| } |
| return obj; |
| } |
| |
| static void Gainmap_destructor(Gainmap* gainmap) { |
| gainmap->decStrong(0); |
| } |
| |
| static jlong Gainmap_getNativeFinalizer(JNIEnv*, jobject) { |
| return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Gainmap_destructor)); |
| } |
| |
| jlong Gainmap_createEmpty(JNIEnv*, jobject) { |
| Gainmap* gainmap = new Gainmap(); |
| gainmap->incStrong(0); |
| return static_cast<jlong>(reinterpret_cast<uintptr_t>(gainmap)); |
| } |
| |
| jlong Gainmap_createCopy(JNIEnv*, jobject, jlong sourcePtr) { |
| Gainmap* gainmap = new Gainmap(); |
| gainmap->incStrong(0); |
| if (sourcePtr) { |
| Gainmap* src = fromJava(sourcePtr); |
| gainmap->info = src->info; |
| } |
| return static_cast<jlong>(reinterpret_cast<uintptr_t>(gainmap)); |
| } |
| |
| 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_setRatioMax(JNIEnv*, jobject, jlong gainmapPtr, jfloat r, jfloat g, jfloat b) { |
| fromJava(gainmapPtr)->info.fGainmapRatioMax = {r, g, b, 1.f}; |
| } |
| |
| 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_setGamma(JNIEnv*, jobject, jlong gainmapPtr, jfloat r, jfloat g, jfloat b) { |
| fromJava(gainmapPtr)->info.fGainmapGamma = {r, g, b, 1.f}; |
| } |
| |
| 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; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Serialization |
| // ---------------------------------------------------------------------------- |
| |
| static void Gainmap_writeToParcel(JNIEnv* env, jobject, jlong nativeObject, jobject parcel) { |
| #ifdef __ANDROID__ // Layoutlib does not support parcel |
| if (parcel == NULL) { |
| ALOGD("write null parcel\n"); |
| return; |
| } |
| ScopedParcel p(env, parcel); |
| SkGainmapInfo info = fromJava(nativeObject)->info; |
| // write gainmap to parcel |
| // ratio min |
| p.writeFloat(info.fGainmapRatioMin.fR); |
| p.writeFloat(info.fGainmapRatioMin.fG); |
| p.writeFloat(info.fGainmapRatioMin.fB); |
| // ratio max |
| p.writeFloat(info.fGainmapRatioMax.fR); |
| p.writeFloat(info.fGainmapRatioMax.fG); |
| p.writeFloat(info.fGainmapRatioMax.fB); |
| // gamma |
| p.writeFloat(info.fGainmapGamma.fR); |
| p.writeFloat(info.fGainmapGamma.fG); |
| p.writeFloat(info.fGainmapGamma.fB); |
| // epsilonsdr |
| p.writeFloat(info.fEpsilonSdr.fR); |
| p.writeFloat(info.fEpsilonSdr.fG); |
| p.writeFloat(info.fEpsilonSdr.fB); |
| // epsilonhdr |
| p.writeFloat(info.fEpsilonHdr.fR); |
| p.writeFloat(info.fEpsilonHdr.fG); |
| p.writeFloat(info.fEpsilonHdr.fB); |
| // display ratio sdr |
| p.writeFloat(info.fDisplayRatioSdr); |
| // display ratio hdr |
| p.writeFloat(info.fDisplayRatioHdr); |
| // base image type |
| p.writeInt32(static_cast<int32_t>(info.fBaseImageType)); |
| #else |
| doThrowRE(env, "Cannot use parcels outside of Android!"); |
| #endif |
| } |
| |
| static void Gainmap_readFromParcel(JNIEnv* env, jobject, jlong nativeObject, jobject parcel) { |
| #ifdef __ANDROID__ // Layoutlib does not support parcel |
| if (parcel == NULL) { |
| jniThrowNullPointerException(env, "parcel cannot be null"); |
| return; |
| } |
| ScopedParcel p(env, parcel); |
| |
| SkGainmapInfo info; |
| info.fGainmapRatioMin = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f}; |
| info.fGainmapRatioMax = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f}; |
| info.fGainmapGamma = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f}; |
| info.fEpsilonSdr = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f}; |
| info.fEpsilonHdr = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f}; |
| info.fDisplayRatioSdr = p.readFloat(); |
| info.fDisplayRatioHdr = p.readFloat(); |
| info.fBaseImageType = static_cast<SkGainmapInfo::BaseImageType>(p.readInt32()); |
| |
| fromJava(nativeObject)->info = info; |
| #else |
| jniThrowRuntimeException(env, "Cannot use parcels outside of Android"); |
| #endif |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // JNI Glue |
| // ---------------------------------------------------------------------------- |
| |
| static const JNINativeMethod gGainmapMethods[] = { |
| {"nGetFinalizer", "()J", (void*)Gainmap_getNativeFinalizer}, |
| {"nCreateEmpty", "()J", (void*)Gainmap_createEmpty}, |
| {"nCreateCopy", "(J)J", (void*)Gainmap_createCopy}, |
| {"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}, |
| {"nWriteGainmapToParcel", "(JLandroid/os/Parcel;)V", (void*)Gainmap_writeToParcel}, |
| {"nReadGainmapFromParcel", "(JLandroid/os/Parcel;)V", (void*)Gainmap_readFromParcel}, |
| }; |
| |
| int register_android_graphics_Gainmap(JNIEnv* env) { |
| gGainmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Gainmap")); |
| gGainmap_constructorMethodID = |
| GetMethodIDOrDie(env, gGainmap_class, "<init>", "(Landroid/graphics/Bitmap;J)V"); |
| return android::RegisterMethodsOrDie(env, "android/graphics/Gainmap", gGainmapMethods, |
| NELEM(gGainmapMethods)); |
| } |
| |
| } // namespace android |