web-dev-qa-db-ja.com

ベクトルドロウアブルからビットマップを取得する

私のアプリケーションでは、通知用の大きなアイコンを設定する必要があります。 LargeIconはビットマップである必要があり、私のドロウアブルはベクター画像です(Androidの新機能、 このリンク を参照)問題は、ベクター画像であるリソースをデコードしようとすると、nullが返されることです戻ってきた。

コードのサンプルは次のとおりです。

if (BitmapFactory.decodeResource(arg0.getResources(), R.drawable.vector_menu_objectifs) == null)
        Log.d("ISNULL", "NULL");
    else
        Log.d("ISNULL", "NOT NULL");

このサンプルでは、​​R.drawable.vector_menu_objectifsを「通常の」画像(例:png)に置き換えると、結果はnullではありません(正しいビットマップを取得します)不足しているものはありますか?

96
liltof

APIで確認済み:17、21、23

public static Bitmap getBitmapFromVectorDrawable(Context context, int drawableId) {
    Drawable drawable = ContextCompat.getDrawable(context, drawableId);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        drawable = (DrawableCompat.wrap(drawable)).mutate();
    }

    Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
            drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);

    return bitmap;
}

更新:

プロジェクトのグラドル:

dependencies {
        classpath 'com.Android.tools.build:gradle:2.2.0-alpha5'
    }

モジュールのグラドル:

Android {
    compileSdkVersion 23
    buildToolsVersion '23.0.3'
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 23
        vectorDrawables.useSupportLibrary = true
    }
    ...
}
...
181
Alexey

次の方法を使用できます。

@TargetApi(Build.VERSION_CODES.Lollipop)
private static Bitmap getBitmap(VectorDrawable vectorDrawable) {
    Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
            vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    vectorDrawable.draw(canvas);
    return bitmap;
}

私は時々それと組み合わせます:

private static Bitmap getBitmap(Context context, int drawableId) {
    Drawable drawable = ContextCompat.getDrawable(context, drawableId);
    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable) drawable).getBitmap();
    } else if (drawable instanceof VectorDrawable) {
        return getBitmap((VectorDrawable) drawable);
    } else {
        throw new IllegalArgumentException("unsupported drawable type");
    }
}
59
snodnipper

前の回答に基づいて、VectorDrawableとBitmapDrawableの両方に一致し、少なくともAPI 15と互換性があるように単純化できます。

public static Bitmap getBitmapFromDrawable(Context context, @DrawableRes int drawableId) {
    Drawable drawable = AppCompatResources.getDrawable(context, drawableId);

    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable) drawable).getBitmap();
    } else if (drawable instanceof VectorDrawableCompat || drawable instanceof VectorDrawable) {
        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    } else {
        throw new IllegalArgumentException("unsupported drawable type");
    }
}

次に、gradleファイルを追加する必要があります。

Android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

Lollipopより前ではVectorDrawableCompatを使用し、LollipopではVectorDrawableを使用します。

編集

@ user3109468のコメントに従って条件を編集しました

21
Eselfar

Kotlinで Android KTX を使用する場合は、拡張メソッドDrawable#toBitmap()を使用して、他の回答と同じ効果を実現できます。

val bitmap = AppCompatResources.getDrawable(requireContext(), drawableId).toBitmap() 

または

val bitmap = AppCompatResources.getDrawable(context, drawableId).toBitmap() 

これやその他の便利な拡張メソッドを追加するには、モジュールレベルのbuild.gradleに以下を追加する必要があります

repositories {
    google()
}

dependencies {
    implementation 'androidx.core:core-ktx:1.0.0-alpha1'
}

これは、Drawableanyサブクラスで機能し、DrawableBitmapDrawableである場合は、基礎となるBitmapを使用するショートカットになることに注意してください。

14
David Rawson

@Alexeyへの称賛

以下は、Kotlinの拡張機能を使用したContextバージョンです。

fun Context.getBitmapFromVectorDrawable(drawableId: Int): Bitmap? {
    var drawable = ContextCompat.getDrawable(this, drawableId) ?: return null

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        drawable = DrawableCompat.wrap(drawable).mutate()
    }

    val bitmap = Bitmap.createBitmap(
            drawable.intrinsicWidth,
            drawable.intrinsicHeight,
            Bitmap.Config.ARGB_8888) ?: return null
    val canvas = Canvas(bitmap)
    drawable.setBounds(0, 0, canvas.width, canvas.height)
    drawable.draw(canvas)

    return bitmap
}

Activityの使用例:

val bitmap = this.getBitmapFromVectorDrawable(R.drawable.ic_done_white_24dp)
6
Gunhan

API 16でテスト済み-Vector Drawablesを使用したJellyBean

public static Bitmap getBitmapFromVectorDrawable(Context context, int drawableId) {
    Drawable drawable = AppCompatResources.getDrawable(context, drawableId);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        drawable = (DrawableCompat.wrap(drawable)).mutate();
    }

    Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
            drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);

    return bitmap;

ありがとうございます !

0
tomasmark79
Drawable layerDrawable = (Drawable) imageBase.getDrawable();
Bitmap bitmap = Bitmap.createBitmap(layerDrawable.getIntrinsicWidth(),
        layerDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
layerDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
layerDrawable.draw(canvas);  
imageTeste.setImageBitmap(addGradient(bitmap));
0
Amine

vectorイメージintrinsicWidthおよびintrinsicHeightが小さく、ビットマップを大きなビューに表示しようとすると、結果がぼやけます。

その場合、ビットマップに新しい幅/高さを指定して、より良い画像を取得できます(または、xmlのベクターサイズを大きくできますが、desireWidthおよびdesireHeightの方が柔軟性が高い場合があります)。

private fun getBitmap(drawableId: Int, desireWidth: Int? = null, desireHeight: Int? = null): Bitmap? {
    val drawable = AppCompatResources.getDrawable(context, drawableId) ?: return null
    val bitmap = Bitmap.createBitmap(
        desireWidth ?: drawable.intrinsicWidth,
        desireHeight ?: drawable.intrinsicHeight,
        Bitmap.Config.ARGB_8888
    )
    val canvas = Canvas(bitmap)
    drawable.setBounds(0, 0, canvas.width, canvas.height)
    drawable.draw(canvas)
    return bitmap
}

お役に立てば幸いです

0
Phan Van Linh

出力を目的の出力サイズにスケーリングできるようにする場合は、次のスニペットを試してください。

fun getBitmapFromVectorDrawable(context: Context, drawableId: Int, outputSize: OutputSize? = null): Bitmap? {
    var drawable = ContextCompat.getDrawable(context, drawableId) ?: return null
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        drawable = DrawableCompat.wrap(drawable).mutate()
    }

    var targetBitmap: Bitmap
    if (outputSize != null) {
        targetBitmap = Bitmap.createBitmap(outputSize.width,
                outputSize.height, Bitmap.Config.ARGB_8888)
    } else {
        targetBitmap = Bitmap.createBitmap(drawable.intrinsicWidth,
            drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
    }

    val canvas = Canvas(targetBitmap)
    val scaleX =  targetBitmap.width.toFloat()/drawable.intrinsicWidth.toFloat()
    val scaleY =  targetBitmap.height.toFloat()/drawable.intrinsicHeight.toFloat()
    canvas.scale(scaleX, scaleY)
    drawable.draw(canvas)

    return targetBitmap
}

class OutputSize(val width: Int, val height: Int)
0
Hans