Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29405ed8 authored by Leon Scroggins's avatar Leon Scroggins Committed by Android (Google) Code Review
Browse files

Merge "Refine ColorSpace restrictions for Bitmaps"

parents 1df6e435 bf3e4647
Loading
Loading
Loading
Loading
+21 −62
Original line number Diff line number Diff line
@@ -355,9 +355,16 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
        colorType = kN32_SkColorType;
    }

    sk_sp<SkColorSpace> colorSpace;
    if (colorType == kAlpha_8_SkColorType) {
        colorSpace = nullptr;
    } else {
        colorSpace = GraphicsJNI::getNativeColorSpace(colorSpacePtr);
    }

    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
                GraphicsJNI::getNativeColorSpace(colorSpacePtr)));
                colorSpace));

    sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap);
    if (!nativeBitmap) {
@@ -385,15 +392,17 @@ static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
        case kRGB_565_SkColorType:
            dstInfo = dstInfo.makeAlphaType(kOpaque_SkAlphaType);
            break;
        case kRGBA_F16_SkColorType:
            // The caller does not have an opportunity to pass a dst color space.  Assume that
            // they want linear sRGB.
            dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGBLinear());
        case kAlpha_8_SkColorType:
            dstInfo = dstInfo.makeColorSpace(nullptr);
            break;
        default:
            break;
    }

    if (!dstInfo.colorSpace() && dstCT != kAlpha_8_SkColorType) {
        dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGB());
    }

    if (!dst->setInfo(dstInfo)) {
        return false;
    }
@@ -608,14 +617,6 @@ static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
    return static_cast<jint>(bitmap->getGenerationID());
}

static jboolean Bitmap_isConfigF16(JNIEnv* env, jobject, jlong bitmapHandle) {
    LocalScopedBitmap bitmap(bitmapHandle);
    if (bitmap->info().colorType() == kRGBA_F16_SkColorType) {
        return JNI_TRUE;
    }
    return JNI_FALSE;
}

static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
    LocalScopedBitmap bitmap(bitmapHandle);
    if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
@@ -684,9 +685,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
    const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
    const uint32_t    colorSpaceSize = p->readUint32();
    sk_sp<SkColorSpace> colorSpace;
    if (kRGBA_F16_SkColorType == colorType) {
        colorSpace = SkColorSpace::MakeSRGBLinear();
    } else if (colorSpaceSize > 0) {
    if (colorSpaceSize > 0) {
        if (colorSpaceSize > kMaxColorSpaceSerializedBytes) {
            ALOGD("Bitmap_createFromParcel: Serialized SkColorSpace is larger than expected: "
                    "%d bytes\n", colorSpaceSize);
@@ -811,7 +810,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
    p->writeInt32(bitmap.colorType());
    p->writeInt32(bitmap.alphaType());
    SkColorSpace* colorSpace = bitmap.colorSpace();
    if (colorSpace != nullptr && bitmap.colorType() != kRGBA_F16_SkColorType) {
    if (colorSpace != nullptr) {
        sk_sp<SkData> data = colorSpace->serialize();
        size_t size = data->size();
        p->writeUint32(size);
@@ -924,44 +923,14 @@ static jboolean Bitmap_isSRGBLinear(JNIEnv* env, jobject, jlong bitmapHandle) {
    return colorSpace == srgbLinear.get() ? JNI_TRUE : JNI_FALSE;
}

static jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle,
        jfloatArray xyzArray, jfloatArray paramsArray) {

static jobject Bitmap_computeColorSpace(JNIEnv* env, jobject, jlong bitmapHandle) {
    LocalScopedBitmap bitmapHolder(bitmapHandle);
    if (!bitmapHolder.valid()) return JNI_FALSE;
    if (!bitmapHolder.valid()) return nullptr;

    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
    if (colorSpace == nullptr) return JNI_FALSE;

    skcms_Matrix3x3 xyzMatrix;
    if (!colorSpace->toXYZD50(&xyzMatrix)) return JNI_FALSE;

    jfloat* xyz = env->GetFloatArrayElements(xyzArray, NULL);
    xyz[0] = xyzMatrix.vals[0][0];
    xyz[1] = xyzMatrix.vals[1][0];
    xyz[2] = xyzMatrix.vals[2][0];
    xyz[3] = xyzMatrix.vals[0][1];
    xyz[4] = xyzMatrix.vals[1][1];
    xyz[5] = xyzMatrix.vals[2][1];
    xyz[6] = xyzMatrix.vals[0][2];
    xyz[7] = xyzMatrix.vals[1][2];
    xyz[8] = xyzMatrix.vals[2][2];
    env->ReleaseFloatArrayElements(xyzArray, xyz, 0);

    skcms_TransferFunction transferParams;
    if (!colorSpace->isNumericalTransferFn(&transferParams)) return JNI_FALSE;

    jfloat* params = env->GetFloatArrayElements(paramsArray, NULL);
    params[0] = transferParams.a;
    params[1] = transferParams.b;
    params[2] = transferParams.c;
    params[3] = transferParams.d;
    params[4] = transferParams.e;
    params[5] = transferParams.f;
    params[6] = transferParams.g;
    env->ReleaseFloatArrayElements(paramsArray, params, 0);
    if (colorSpace == nullptr) return nullptr;

    return JNI_TRUE;
    return GraphicsJNI::getColorSpace(env, colorSpace, bitmapHolder->info().colorType());
}

static void Bitmap_setColorSpace(JNIEnv* env, jobject, jlong bitmapHandle, jlong colorSpacePtr) {
@@ -1174,13 +1143,6 @@ static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitm
    return createJavaGraphicBuffer(env, buffer);
}

static void Bitmap_copyColorSpace(JNIEnv* env, jobject, jlong srcBitmapPtr, jlong dstBitmapPtr) {
    LocalScopedBitmap srcBitmapHandle(srcBitmapPtr);
    LocalScopedBitmap dstBitmapHandle(dstBitmapPtr);

    dstBitmapHandle->bitmap().setColorSpace(srcBitmapHandle->bitmap().info().refColorSpace());
}

static jboolean Bitmap_isImmutable(jlong bitmapHandle) {
    LocalScopedBitmap bitmapHolder(bitmapHandle);
    if (!bitmapHolder.valid()) return JNI_FALSE;
@@ -1215,7 +1177,6 @@ static const JNINativeMethod gBitmapMethods[] = {
    {   "nativeErase",              "(JJJ)V", (void*)Bitmap_eraseLong },
    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
    {   "nativeIsConfigF16",        "(J)Z", (void*)Bitmap_isConfigF16 },
    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
    {   "nativeIsPremultiplied",    "(J)Z", (void*)Bitmap_isPremultiplied},
    {   "nativeSetHasAlpha",        "(JZZ)V", (void*)Bitmap_setHasAlpha},
@@ -1248,12 +1209,10 @@ static const JNINativeMethod gBitmapMethods[] = {
        (void*) Bitmap_wrapHardwareBufferBitmap },
    {   "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
        (void*) Bitmap_createGraphicBufferHandle },
    {   "nativeGetColorSpace",      "(J[F[F)Z", (void*)Bitmap_getColorSpace },
    {   "nativeComputeColorSpace",  "(J)Landroid/graphics/ColorSpace;", (void*)Bitmap_computeColorSpace },
    {   "nativeSetColorSpace",      "(JJ)V", (void*)Bitmap_setColorSpace },
    {   "nativeIsSRGB",             "(J)Z", (void*)Bitmap_isSRGB },
    {   "nativeIsSRGBLinear",       "(J)Z", (void*)Bitmap_isSRGBLinear},
    {   "nativeCopyColorSpace",     "(JJ)V",
        (void*)Bitmap_copyColorSpace },
    {   "nativeSetImmutable",       "(J)V", (void*)Bitmap_setImmutable},

    // ------------ @CriticalNative ----------------
+1 −1
Original line number Diff line number Diff line
@@ -307,7 +307,7 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream,
        env->SetObjectField(options, gOptions_outConfigFieldID, config);

        env->SetObjectField(options, gOptions_outColorSpaceFieldID,
                GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType));
                GraphicsJNI::getColorSpace(env, decodeColorSpace.get(), decodeColorType));

        if (onlyDecodeSize) {
            return nullptr;
+1 −1
Original line number Diff line number Diff line
@@ -215,7 +215,7 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in
        env->SetObjectField(options, gOptions_outConfigFieldID, config);

        env->SetObjectField(options, gOptions_outColorSpaceFieldID,
                GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType));
                GraphicsJNI::getColorSpace(env, decodeColorSpace.get(), decodeColorType));
    }

    // If we may have reused a bitmap, we need to indicate that the pixels have changed.
+72 −55
Original line number Diff line number Diff line
@@ -187,6 +187,8 @@ static jmethodID gColorSpaceRGB_constructorMethodID;

static jclass gColorSpace_Named_class;
static jfieldID gColorSpace_Named_sRGBFieldID;
static jfieldID gColorSpace_Named_ExtendedSRGBFieldID;
static jfieldID gColorSpace_Named_LinearSRGBFieldID;
static jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID;

static jclass gTransferParameters_class;
@@ -412,24 +414,37 @@ jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region)

///////////////////////////////////////////////////////////////////////////////

jobject GraphicsJNI::getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace,
jobject GraphicsJNI::getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace,
        SkColorType decodeColorType) {
    jobject colorSpace = nullptr;
    if (!decodeColorSpace || decodeColorType == kAlpha_8_SkColorType) {
        return nullptr;
    }

    // No need to match, we know what the output color space will be
    // Special checks for the common sRGB cases and their extended variants.
    jobject namedCS = nullptr;
    sk_sp<SkColorSpace> srgbLinear = SkColorSpace::MakeSRGBLinear();
    if (decodeColorType == kRGBA_F16_SkColorType) {
        jobject linearExtendedSRGB = env->GetStaticObjectField(
                gColorSpace_Named_class, gColorSpace_Named_LinearExtendedSRGBFieldID);
        colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
                gColorSpace_getMethodID, linearExtendedSRGB);
    } else {
        // Same here, no need to match
        // An F16 Bitmap will always report that it is EXTENDED if
        // it matches a ColorSpace that has an EXTENDED variant.
        if (decodeColorSpace->isSRGB()) {
            jobject sRGB = env->GetStaticObjectField(
                    gColorSpace_Named_class, gColorSpace_Named_sRGBFieldID);
            colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
                    gColorSpace_getMethodID, sRGB);
        } else if (decodeColorSpace.get() != nullptr) {
            namedCS = env->GetStaticObjectField(gColorSpace_Named_class,
                                                gColorSpace_Named_ExtendedSRGBFieldID);
        } else if (decodeColorSpace == srgbLinear.get()) {
            namedCS = env->GetStaticObjectField(gColorSpace_Named_class,
                                                gColorSpace_Named_LinearExtendedSRGBFieldID);
        }
    } else if (decodeColorSpace->isSRGB()) {
        namedCS = env->GetStaticObjectField(gColorSpace_Named_class,
                                            gColorSpace_Named_sRGBFieldID);
    } else if (decodeColorSpace == srgbLinear.get()) {
        namedCS = env->GetStaticObjectField(gColorSpace_Named_class,
                                            gColorSpace_Named_LinearSRGBFieldID);
    }

    if (namedCS) {
        return env->CallStaticObjectMethod(gColorSpace_class, gColorSpace_getMethodID, namedCS);
    }

    // Try to match against known RGB color spaces using the CIE XYZ D50
    // conversion matrix and numerical transfer function parameters
    skcms_Matrix3x3 xyzMatrix;
@@ -459,7 +474,7 @@ jobject GraphicsJNI::getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColor
    };
    env->SetFloatArrayRegion(xyzArray, 0, 9, xyz);

            colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
    jobject colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
            gColorSpace_matchMethodID, xyzArray, params);

    if (colorSpace == nullptr) {
@@ -471,8 +486,6 @@ jobject GraphicsJNI::getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColor
    }

    env->DeleteLocalRef(xyzArray);
        }
    }
    return colorSpace;
}

@@ -658,6 +671,10 @@ int register_android_graphics_Graphics(JNIEnv* env)
            FindClassOrDie(env, "android/graphics/ColorSpace$Named"));
    gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env,
            gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;");
    gColorSpace_Named_ExtendedSRGBFieldID = GetStaticFieldIDOrDie(env,
            gColorSpace_Named_class, "EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;");
    gColorSpace_Named_LinearSRGBFieldID = GetStaticFieldIDOrDie(env,
            gColorSpace_Named_class, "LINEAR_SRGB", "Landroid/graphics/ColorSpace$Named;");
    gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env,
            gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;");

+7 −1
Original line number Diff line number Diff line
@@ -109,7 +109,13 @@ public:
     */
    static sk_sp<SkColorSpace> getNativeColorSpace(jlong colorSpaceHandle);

    static jobject getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace,
    /**
     * Return the android.graphics.ColorSpace Java object that corresponds to decodeColorSpace
     * and decodeColorType.
     *
     * This may create a new object if none of the Named ColorSpaces match.
     */
    static jobject getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace,
            SkColorType decodeColorType);

    /**
Loading