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

Commit e8d2ebb5 authored by Romain Guy's avatar Romain Guy
Browse files

Report bitmap config when decoding only metadata

With the introduction of support for 16 bit images, bitmaps returned
by BitmapFactory may be using the RGBA_F16 configuration. Some apps
and libraries assume the returned configuration is always ARGB_8888
and make assumptions based on that to compute cache sizes, etc.

This changes extract the output config when BitmapFactory is invoked
with the inJustDecodeBounds option. Despite its name, this option
is already used (and documented!) to decode more than bounds as it
also decodes the MIME type.

Bug: 35108998
Test: CtsGraphicsTestCases
Change-Id: If71959751458816678e42b21ab26c889aba5dea0
parent 54afd007
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -12242,6 +12242,7 @@ package android.graphics {
    field public int inTargetDensity;
    field public byte[] inTempStorage;
    field public deprecated boolean mCancel;
    field public android.graphics.Bitmap.Config outConfig;
    field public int outHeight;
    field public java.lang.String outMimeType;
    field public int outWidth;
+1 −0
Original line number Diff line number Diff line
@@ -12810,6 +12810,7 @@ package android.graphics {
    field public int inTargetDensity;
    field public byte[] inTempStorage;
    field public deprecated boolean mCancel;
    field public android.graphics.Bitmap.Config outConfig;
    field public int outHeight;
    field public java.lang.String outMimeType;
    field public int outWidth;
+1 −0
Original line number Diff line number Diff line
@@ -12276,6 +12276,7 @@ package android.graphics {
    field public int inTargetDensity;
    field public byte[] inTempStorage;
    field public deprecated boolean mCancel;
    field public android.graphics.Bitmap.Config outConfig;
    field public int outHeight;
    field public java.lang.String outMimeType;
    field public int outWidth;
+29 −4
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ jfieldID gOptions_targetDensityFieldID;
jfieldID gOptions_widthFieldID;
jfieldID gOptions_heightFieldID;
jfieldID gOptions_mimeFieldID;
jfieldID gOptions_outConfigFieldID;
jfieldID gOptions_mCancelID;
jfieldID gOptions_bitmapFieldID;

@@ -47,6 +48,9 @@ jfieldID gBitmap_ninePatchInsetsFieldID;
jclass gInsetStruct_class;
jmethodID gInsetStruct_constructorMethodID;

jclass gBitmapConfig_class;
jmethodID gBitmapConfig_nativeToConfigMethodID;

using namespace android;

jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format) {
@@ -298,6 +302,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
        env->SetIntField(options, gOptions_widthFieldID, -1);
        env->SetIntField(options, gOptions_heightFieldID, -1);
        env->SetObjectField(options, gOptions_mimeFieldID, 0);
        env->SetObjectField(options, gOptions_outConfigFieldID, 0);

        jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
        prefColorType = GraphicsJNI::getNativeBitmapColorType(env, jconfig);
@@ -352,6 +357,9 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
        scaledHeight = codec->getInfo().height() / sampleSize;
    }

    // Set the decode colorType
    SkColorType decodeColorType = codec->computeOutputColorType(prefColorType);

    // Set the options and return if the client only wants the size.
    if (options != NULL) {
        jstring mimeType = encodedFormatToString(
@@ -363,6 +371,20 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
        env->SetIntField(options, gOptions_heightFieldID, scaledHeight);
        env->SetObjectField(options, gOptions_mimeFieldID, mimeType);

        SkColorType outColorType = decodeColorType;
        // Scaling can affect the output color type
        if (willScale || scale != 1.0f) {
            outColorType = colorTypeForScaledOutput(outColorType);
        }

        jint configID = GraphicsJNI::colorTypeToLegacyBitmapConfig(outColorType);
        if (isHardware) {
            configID = GraphicsJNI::kHardware_LegacyBitmapConfig;
        }
        jobject config = env->CallStaticObjectMethod(gBitmapConfig_class,
                gBitmapConfig_nativeToConfigMethodID, configID);
        env->SetObjectField(options, gOptions_outConfigFieldID, config);

        if (onlyDecodeSize) {
            return nullptr;
        }
@@ -409,10 +431,6 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
        decodeAllocator = &defaultAllocator;
    }

    // Set the decode colorType.  This is necessary because we can't always support
    // the requested colorType.
    SkColorType decodeColorType = codec->computeOutputColorType(prefColorType);

    // Construct a color table for the decode if necessary
    sk_sp<SkColorTable> colorTable(nullptr);
    SkPMColor* colorPtr = nullptr;
@@ -747,6 +765,8 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) {
    gOptions_widthFieldID = GetFieldIDOrDie(env, options_class, "outWidth", "I");
    gOptions_heightFieldID = GetFieldIDOrDie(env, options_class, "outHeight", "I");
    gOptions_mimeFieldID = GetFieldIDOrDie(env, options_class, "outMimeType", "Ljava/lang/String;");
    gOptions_outConfigFieldID = GetFieldIDOrDie(env, options_class, "outConfig",
             "Landroid/graphics/Bitmap$Config;");
    gOptions_mCancelID = GetFieldIDOrDie(env, options_class, "mCancel", "Z");

    jclass bitmap_class = FindClassOrDie(env, "android/graphics/Bitmap");
@@ -758,6 +778,11 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) {
    gInsetStruct_constructorMethodID = GetMethodIDOrDie(env, gInsetStruct_class, "<init>",
                                                        "(IIIIIIIIFIF)V");

    gBitmapConfig_class = MakeGlobalRefOrDie(env, FindClassOrDie(env,
            "android/graphics/Bitmap$Config"));
    gBitmapConfig_nativeToConfigMethodID = GetStaticMethodIDOrDie(env, gBitmapConfig_class,
            "nativeToConfig", "(I)Landroid/graphics/Bitmap$Config;");

    return android::RegisterMethodsOrDie(env, "android/graphics/BitmapFactory",
                                         gMethods, NELEM(gMethods));
}
+1 −15
Original line number Diff line number Diff line
@@ -287,21 +287,7 @@ void GraphicsJNI::point_to_jpointf(const SkPoint& r, JNIEnv* env, jobject obj)
    env->SetFloatField(obj, gPointF_yFieldID, SkScalarToFloat(r.fY));
}

// This enum must keep these int values, to match the int values
// in the java Bitmap.Config enum.
enum LegacyBitmapConfig {
    kNo_LegacyBitmapConfig          = 0,
    kA8_LegacyBitmapConfig          = 1,
    kIndex8_LegacyBitmapConfig      = 2,
    kRGB_565_LegacyBitmapConfig     = 3,
    kARGB_4444_LegacyBitmapConfig   = 4,
    kARGB_8888_LegacyBitmapConfig   = 5,
    kRGBA_16F_LegacyBitmapConfig    = 6,
    kHardware_LegacyBitmapConfig    = 7,

    kLastEnum_LegacyBitmapConfig = kHardware_LegacyBitmapConfig
};

// See enum values in GraphicsJNI.h
jint GraphicsJNI::colorTypeToLegacyBitmapConfig(SkColorType colorType) {
    switch (colorType) {
        case kRGBA_F16_SkColorType:
Loading