diff options
-rw-r--r-- | core/jni/Android.bp | 2 | ||||
-rw-r--r-- | core/jni/android/graphics/apex/android_bitmap.cpp | 92 | ||||
-rw-r--r-- | core/jni/android/graphics/apex/include/android/graphics/bitmap.h | 5 | ||||
-rw-r--r-- | native/graphics/jni/bitmap.cpp | 10 | ||||
-rw-r--r-- | native/graphics/jni/libjnigraphics.map.txt | 1 |
5 files changed, 108 insertions, 2 deletions
diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 6e6746f16748..a2f514a85ff8 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -344,7 +344,6 @@ cc_library_static { cppflags: ["-Wno-conversion-null"], srcs: [ - "android/graphics/apex/android_bitmap.cpp", "android/graphics/apex/android_matrix.cpp", "android/graphics/apex/android_paint.cpp", "android/graphics/apex/android_region.cpp", @@ -430,6 +429,7 @@ cc_library_static { android: { srcs: [ // sources that depend on android only libraries "android/graphics/apex/android_canvas.cpp", + "android/graphics/apex/android_bitmap.cpp", "android/graphics/apex/renderthread.cpp", "android/graphics/apex/jni_runtime.cpp", diff --git a/core/jni/android/graphics/apex/android_bitmap.cpp b/core/jni/android/graphics/apex/android_bitmap.cpp index 90cc98699827..6a3c01efe98c 100644 --- a/core/jni/android/graphics/apex/android_bitmap.cpp +++ b/core/jni/android/graphics/apex/android_bitmap.cpp @@ -122,6 +122,98 @@ AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmapHandle) { return getInfo(bitmap->info(), bitmap->rowBytes()); } +static bool nearlyEqual(float a, float b) { + // By trial and error, this is close enough to match for the ADataSpaces we + // compare for. + return ::fabs(a - b) < .002f; +} + +static bool nearlyEqual(const skcms_TransferFunction& x, const skcms_TransferFunction& y) { + return nearlyEqual(x.g, y.g) + && nearlyEqual(x.a, y.a) + && nearlyEqual(x.b, y.b) + && nearlyEqual(x.c, y.c) + && nearlyEqual(x.d, y.d) + && nearlyEqual(x.e, y.e) + && nearlyEqual(x.f, y.f); +} + +static bool nearlyEqual(const skcms_Matrix3x3& x, const skcms_Matrix3x3& y) { + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (!nearlyEqual(x.vals[i][j], y.vals[i][j])) return false; + } + } + return true; +} + +static constexpr skcms_TransferFunction k2Dot6 = {2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; + +// Skia's SkNamedGamut::kDCIP3 is based on a white point of D65. This gamut +// matches the white point used by ColorSpace.Named.DCIP3. +static constexpr skcms_Matrix3x3 kDCIP3 = {{ + {0.486143, 0.323835, 0.154234}, + {0.226676, 0.710327, 0.0629966}, + {0.000800549, 0.0432385, 0.78275}, +}}; + +ADataSpace ABitmap_getDataSpace(ABitmap* bitmapHandle) { + Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle); + const SkImageInfo& info = bitmap->info(); + SkColorSpace* colorSpace = info.colorSpace(); + if (!colorSpace) { + return ADATASPACE_UNKNOWN; + } + + if (colorSpace->isSRGB()) { + if (info.colorType() == kRGBA_F16_SkColorType) { + return ADATASPACE_SCRGB; + } + return ADATASPACE_SRGB; + } + + skcms_TransferFunction fn; + LOG_ALWAYS_FATAL_IF(!colorSpace->isNumericalTransferFn(&fn)); + + skcms_Matrix3x3 gamut; + LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&gamut)); + + if (nearlyEqual(gamut, SkNamedGamut::kSRGB)) { + if (nearlyEqual(fn, SkNamedTransferFn::kLinear)) { + // Skia doesn't differentiate amongst the RANGES. In Java, we associate + // LINEAR_EXTENDED_SRGB with F16, and LINEAR_SRGB with other Configs. + // Make the same association here. + if (info.colorType() == kRGBA_F16_SkColorType) { + return ADATASPACE_SCRGB_LINEAR; + } + return ADATASPACE_SRGB_LINEAR; + } + + if (nearlyEqual(fn, SkNamedTransferFn::kRec2020)) { + return ADATASPACE_BT709; + } + } + + if (nearlyEqual(fn, SkNamedTransferFn::kSRGB) && nearlyEqual(gamut, SkNamedGamut::kDCIP3)) { + return ADATASPACE_DISPLAY_P3; + } + + if (nearlyEqual(fn, SkNamedTransferFn::k2Dot2) && nearlyEqual(gamut, SkNamedGamut::kAdobeRGB)) { + return ADATASPACE_ADOBE_RGB; + } + + if (nearlyEqual(fn, SkNamedTransferFn::kRec2020) && + nearlyEqual(gamut, SkNamedGamut::kRec2020)) { + return ADATASPACE_BT2020; + } + + if (nearlyEqual(fn, k2Dot6) && nearlyEqual(gamut, kDCIP3)) { + return ADATASPACE_DCI_P3; + } + + return ADATASPACE_UNKNOWN; +} + AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj) { uint32_t rowBytes = 0; SkImageInfo imageInfo = GraphicsJNI::getBitmapInfo(env, bitmapObj, &rowBytes); diff --git a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h index f231eeddb7e2..32b8a450e147 100644 --- a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h +++ b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h @@ -17,6 +17,7 @@ #define ANDROID_GRAPHICS_BITMAP_H #include <android/bitmap.h> +#include <android/data_space.h> #include <jni.h> #include <sys/cdefs.h> @@ -49,6 +50,7 @@ void ABitmap_acquireRef(ABitmap* bitmap); void ABitmap_releaseRef(ABitmap* bitmap); AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmap); +ADataSpace ABitmap_getDataSpace(ABitmap* bitmap); void* ABitmap_getPixels(ABitmap* bitmap); void ABitmap_notifyPixelsChanged(ABitmap* bitmap); @@ -106,6 +108,7 @@ namespace graphics { ABitmap* get() const { return mBitmap; } AndroidBitmapInfo getInfo() const { return ABitmap_getInfo(mBitmap); } + ADataSpace getDataSpace() const { return ABitmap_getDataSpace(mBitmap); } void* getPixels() const { return ABitmap_getPixels(mBitmap); } void notifyPixelsChanged() const { ABitmap_notifyPixelsChanged(mBitmap); } @@ -119,4 +122,4 @@ namespace graphics { }; // namespace android #endif // __cplusplus -#endif // ANDROID_GRAPHICS_BITMAP_H
\ No newline at end of file +#endif // ANDROID_GRAPHICS_BITMAP_H diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp index 1aebeaf1e7e8..26c7f8d709e7 100644 --- a/native/graphics/jni/bitmap.cpp +++ b/native/graphics/jni/bitmap.cpp @@ -16,6 +16,7 @@ #include <android/bitmap.h> #include <android/graphics/bitmap.h> +#include <android/data_space.h> int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap, AndroidBitmapInfo* info) { @@ -29,6 +30,15 @@ int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap, return ANDROID_BITMAP_RESULT_SUCCESS; } +int32_t AndroidBitmap_getDataSpace(JNIEnv* env, jobject jbitmap) { + if (NULL == env || NULL == jbitmap) { + return ADATASPACE_UNKNOWN; // Or return a real error? + } + + android::graphics::Bitmap bitmap(env, jbitmap); + return bitmap.getDataSpace(); +} + int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr) { if (NULL == env || NULL == jbitmap) { return ANDROID_BITMAP_RESULT_BAD_PARAMETER; diff --git a/native/graphics/jni/libjnigraphics.map.txt b/native/graphics/jni/libjnigraphics.map.txt index a601d8af2830..6adb95520d6c 100644 --- a/native/graphics/jni/libjnigraphics.map.txt +++ b/native/graphics/jni/libjnigraphics.map.txt @@ -1,6 +1,7 @@ LIBJNIGRAPHICS { global: AndroidBitmap_getInfo; + AndroidBitmap_getDataSpace; AndroidBitmap_lockPixels; AndroidBitmap_unlockPixels; local: |