ドローアブルをビットマップに変換する方法は?


947

Drawableデバイスの壁紙として特定のものを設定したいのですが、すべての壁紙機能はBitmapsのみを受け入れます。WallpaperManager2.1以前なので使用できません。

また、私のドローアブルはWebからダウンロードされ、にはありませんR.drawable



1
正しい答えを選択してください。これは、stackoverflow.com
a / 3035869/4548520

回答:


1289

このコードが役立ちます。

Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
                                           R.drawable.icon_resource);

ここでは、イメージがダウンロードされるバージョンです。

String name = c.getString(str_url);
URL url_value = new URL(name);
ImageView profile = (ImageView)v.findViewById(R.id.vdo_icon);
if (profile != null) {
    Bitmap mIcon1 =
        BitmapFactory.decodeStream(url_value.openConnection().getInputStream());
    profile.setImageBitmap(mIcon1);
}

1
私はあなたがURL値を持っていると思います。次に、私の編集した回答が役立ちます。
Praveen

str_urlはどこから来たのですか?文字列に関連するDrawable関数が見つかりませんでした...ご協力ありがとうございます。
Rob

12
私は何かを見つけたと思います:「ドロー」がビットマップに変換したいドローアブルの場合:Bitmap bitmap =((BitmapDrawable)draw).getBitmap(); トリックを行います!
Rob

1
@Rob:DrawableがBitmapDrawableのみの場合。(つまり、
Drawable

2
注:これにより、JPGで大量のjava.lang.OutOfMemoryErrorが発生します
誰かのどこか

744
public static Bitmap drawableToBitmap (Drawable drawable) {
    Bitmap bitmap = null;

    if (drawable instanceof BitmapDrawable) {
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        if(bitmapDrawable.getBitmap() != null) {
            return bitmapDrawable.getBitmap();
        }
    }

    if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
        bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
    } else {
        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;
}

41
これは、あらゆる種類のドローアブルで機能する唯一の回答のようであり、すでにBitmapDrawableであるドローアブルの簡単な解決策もあります。+1
Matt Wolfe

1
ただ1つの修正:docsは、BitmapDrawable.getBitmap()についてnullを返す可能性があると述べています。すでにリサイクルされて戻ってくるかもしれませんね。
ケルログ2012

16
気をつけろ:getIntrinsicWidth()getIntrinsicHieght()-1を返します描画可能でソリッドカラーである場合。
SD

5
だから... ColorDrawableの別のチェックで、勝者がいます。真剣に、誰かがこれを受け入れられた答えにします。
kaay

2
フラグの付いた回答とは異なり、これは質問に答えます。
njzk2 2013年

214

これにより、BitmapDrawableがBitmapに変換されます。

Drawable d = ImagesArrayList.get(0);  
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();

9
これは本当に最善の方法ですか?ドローアブルは別のタイプである可能性があり、これはruntimeExceptionをスローしますか?例えば、それはninePatchDrawbleかもしれません...?
ドリ

4
あなたはそれが実際にあるかどうかを確認するために条件文のコードをラップすることができ@Dori BitmapDrawableそれをキャストする前に: if (d instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable)d).getBitmap(); }
トニー・チャン

367
64の賛成票を信じられないのですか?このコードは明らか場合にのみ動作しd、すでにあるBitmapDrawable、それはビットマップとしてそれを取得するために些細です、その場合には...とクラッシュしますClassCastException他のすべてのケースで。
Matthias

3
@Matthiasは言うまでもありません。質問自体、同じ著者が100票を持っています:/
quinestor

2
これは些細なケースに特化しています。
njzk2 2013年

141

AはDrawable上に描画することができCanvas、かつCanvasによってバックアップすることができますBitmap

BitmapDrawablesのクイック変換を処理し、Bitmap作成されたサイズが有効であることを確認するために更新されました)

public static Bitmap drawableToBitmap (Drawable drawable) {
    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable)drawable).getBitmap();
    }

    int width = drawable.getIntrinsicWidth();
    width = width > 0 ? width : 1;
    int height = drawable.getIntrinsicHeight();
    height = height > 0 ? height : 1;

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

    return bitmap;
}

ドローアブルパラメータがnullの場合はどうなりますか?
hrules6872

1
このメソッドはVectorDrawableをサポートしていません
Mahmoud


空でないDrawableを取得すると仮定すると、幅と高さが0でないことを確認する必要があるのはなぜですか?また、同じサイズの場合にsetBounds()を使用する必要があるのはなぜですか?
Yoav Feuerstein 2017年

良い解決策のAndroid 8.0 / SDK 26 ApplicationInfo.loadIcon(PackageManager午後は)AdaptiveIconDrawableを返すあなたのコードを使用して、私はビットマップにAdaptiveIconDrawableをキャストすることができます!。。
burulangtu

43

方法1:このように直接ビットマップに変換できるか

Bitmap myLogo = BitmapFactory.decodeResource(context.getResources(), R.drawable.my_drawable);

方法2:リソースをドローアブルに変換することもでき、そこからこのようにビットマップを取得できます

Bitmap myLogo = ((BitmapDrawable)getResources().getDrawable(R.drawable.logo)).getBitmap();

以下のためにAPI> 22 getDrawableの方法は、に移動しResourcesCompatますので、このような何かをすることをのためのクラス

Bitmap myLogo = ((BitmapDrawable) ResourcesCompat.getDrawable(context.getResources(), R.drawable.logo, null)).getBitmap();

ResourcesCompatは、ドローアブルがBitmapDrawableである場合にのみ機能します。VectorDrawableを使用している場合は、CCEになります。
Brill Pappin

これらはどちらもVectorDrawableリソースでは機能しません。次のエラーが発生した-android.graphics.drawable.VectorDrawable cannot be cast to android.graphics.drawable.BitmapDrawable
アダム・フルビッツ

このソリューションはKotlinでうまく機能します。
Adam Hurwitz


15

したがって、他の回答を調べて(そして使用して)みると、それらはすべて扱いにくくColorDrawablePaintDrawableひどいようです。(特にロリポップ)Shaderが微調整されたため、色の固体ブロックが正しく処理されなかったようです。

現在、次のコードを使用しています。

public static Bitmap drawableToBitmap(Drawable drawable) {
    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable) drawable).getBitmap();
    }

    // We ask for the bounds if they have been set as they would be most
    // correct, then we check we are  > 0
    final int width = !drawable.getBounds().isEmpty() ?
            drawable.getBounds().width() : drawable.getIntrinsicWidth();

    final int height = !drawable.getBounds().isEmpty() ?
            drawable.getBounds().height() : drawable.getIntrinsicHeight();

    // Now we check we are > 0
    final Bitmap bitmap = Bitmap.createBitmap(width <= 0 ? 1 : width, height <= 0 ? 1 : height,
            Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);

    return bitmap;
}

他の人とは違って、あなたが呼び出す場合setBoundsにはDrawable、ビットマップにそれを回すために尋ねる前に、それが正しいサイズでビットマップを描画します!


setBoundsはドローアブルの以前の境界を台無しにしませんか?保存して後で復元した方がいいですか?
Androidデベロッパー

@androiddeveloper、境界が設定されている場合は、とにかくそれらを使用しています。これは、境界が設定されておらず、固有のサイズがない場合に必要です(場合によってはColorDrawablesなど)。したがって、幅と高さは0になります。ドローアブル1x1を指定して、実際に何かを描画します。それらのケースではColorDrawableのタイプチェックを実行できると主張できますが、これは99%のケースで機能します。(必要に応じて変更できます)。
Chris.Jenkins、2015

@ Chris.Jenkins境界がない場合はどうなりますか?また、別の質問をしたいと思います。返されるビットマップサイズ(BitmapDrawableの場合でも)を設定する最良の方法は何ですか?
Android開発者

コードを注意深く読むことをお勧めします。にDrawable境界が設定されていない場合は、を使用しIntrinsicWidth/Heightます。両方とも0以下の場合は、キャンバスを1pxに設定します。にDrawable境界がない場合は正しいですが、一部が渡されます(1x1がほとんどの場合)。これは、ColorDrawable固有のサイズを持たないような場合に必要です。これを行わなかった場合、がスローさExceptionれ、キャンバスに0x0を描画できません。
Chris.Jenkins、2015

1
mutate()オリジナルのドローアブルをそのままにしてコピーを作成します。これにより、オリジナルの境界でパスバックする問題が解消されます。これらの点に基づいてコードを変更することはほとんどありません。ユースケースで必要な場合は、別の回答を追加してください。ビットマップのスケーリングについて別の質問を作成することをお勧めします。
Chris.Jenkins、2015

13

多分これは誰かを助けるでしょう...

PictureDrawableからBitmapまで、以下を使用します。

private Bitmap pictureDrawableToBitmap(PictureDrawable pictureDrawable){ 
    Bitmap bmp = Bitmap.createBitmap(pictureDrawable.getIntrinsicWidth(), pictureDrawable.getIntrinsicHeight(), Config.ARGB_8888); 
    Canvas canvas = new Canvas(bmp); 
    canvas.drawPicture(pictureDrawable.getPicture()); 
    return bmp; 
}

...そのように実装:

Bitmap bmp = pictureDrawableToBitmap((PictureDrawable) drawable);

Robの回答と同様に、特定のタイプのDrawable、この場合はが必要ですPictureDrawable
kabuko

4
「多分これは誰かを助けるでしょう...」
マウロ

11

これはより良い解像度です

public static Bitmap drawableToBitmap (Drawable drawable) {
    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable)drawable).getBitmap();
    }

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

    return bitmap;
}

public static InputStream bitmapToInputStream(Bitmap bitmap) {
    int size = bitmap.getHeight() * bitmap.getRowBytes();
    ByteBuffer buffer = ByteBuffer.allocate(size);
    bitmap.copyPixelsToBuffer(buffer);
    return new ByteArrayInputStream(buffer.array());
}

描画可能なビットをInputStreamとして読み取る方法からのコード


11

1)ビットマップに描画可能:

Bitmap mIcon = BitmapFactory.decodeResource(context.getResources(),R.drawable.icon);
// mImageView.setImageBitmap(mIcon);

2)ビットマップからDrawableへ:

Drawable mDrawable = new BitmapDrawable(getResources(), bitmap);
// mImageView.setDrawable(mDrawable);

10

ここに@ Chris.Jenkinsによって提供された答えの素敵なKotlinバージョンがあります:https ://stackoverflow.com/a/27543712/1016462

fun Drawable.toBitmap(): Bitmap {
  if (this is BitmapDrawable) {
    return bitmap
  }

  val width = if (bounds.isEmpty) intrinsicWidth else bounds.width()
  val height = if (bounds.isEmpty) intrinsicHeight else bounds.height()

  return Bitmap.createBitmap(width.nonZero(), height.nonZero(), Bitmap.Config.ARGB_8888).also {
    val canvas = Canvas(it)
    setBounds(0, 0, canvas.width, canvas.height)
    draw(canvas)
  }
}

private fun Int.nonZero() = if (this <= 0) 1 else this

9

android-ktxにはDrawable.toBitmapメソッドがあります:https : //android.github.io/android-ktx/core-ktx/androidx.graphics.drawable/android.graphics.drawable.-drawable/to-bitmap.html

コトリンから

val bitmap = myDrawable.toBitmap()

これはVectorDrawableKotlinでの最も簡単なソリューションです。詳細については、このSO投稿でもこちらを共有てください。
Adam Hurwitz

8

Androidは、正直ではない解決策を提供しますBitmapDrawable。ビットマップを取得するには、リソースID R.drawable.flower_picをa に提供し、BitmapDrawableそれをaにキャストする必要がありBitmapます。

Bitmap bm = ((BitmapDrawable) getResources().getDrawable(R.drawable.flower_pic)).getBitmap();

5

このcode.itを使用すると、目標を達成するのに役立ちます。

 Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.profileimage);
    if (bmp!=null) {
        Bitmap bitmap_round=getRoundedShape(bmp);
        if (bitmap_round!=null) {
            profileimage.setImageBitmap(bitmap_round);
        }
    }

  public Bitmap getRoundedShape(Bitmap scaleBitmapImage) {
    int targetWidth = 100;
    int targetHeight = 100;
    Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, 
            targetHeight,Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(targetBitmap);
    Path path = new Path();
    path.addCircle(((float) targetWidth - 1) / 2,
            ((float) targetHeight - 1) / 2,
            (Math.min(((float) targetWidth), 
                    ((float) targetHeight)) / 2),
                    Path.Direction.CCW);

    canvas.clipPath(path);
    Bitmap sourceBitmap = scaleBitmapImage;
    canvas.drawBitmap(sourceBitmap, 
            new Rect(0, 0, sourceBitmap.getWidth(),
                    sourceBitmap.getHeight()), 
                    new Rect(0, 0, targetWidth, targetHeight), new Paint(Paint.FILTER_BITMAP_FLAG));
    return targetBitmap;
}

3

BitmapFactory.decodeResource()はビットマップを自動的にスケーリングするため、ビットマップがぼやける場合があります。スケーリングを防ぐには、次のようにします。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap source = BitmapFactory.decodeResource(context.getResources(),
                                             R.drawable.resource_name, options);

または

InputStream is = context.getResources().openRawResource(R.drawable.resource_name)
bitmap = BitmapFactory.decodeStream(is);

2

あなたがkotlinを使用している場合は、以下のコードを使用してください。それはうまくいきます

//画像パスを使用するため

val image = Drawable.createFromPath(path)
val bitmap = (image as BitmapDrawable).bitmap


1
 // get image path from gallery
protected void onActivityResult(int requestCode, int resultcode, Intent intent) {
    super.onActivityResult(requestCode, resultcode, intent);

    if (requestCode == 1) {
        if (intent != null && resultcode == RESULT_OK) {             
            Uri selectedImage = intent.getData();

            String[] filePathColumn = {MediaStore.Images.Media.DATA};
            Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            filePath = cursor.getString(columnIndex);

            //display image using BitmapFactory

            cursor.close(); bmp = BitmapFactory.decodeFile(filepath); 
            iv.setBackgroundResource(0);
            iv.setImageBitmap(bmp);
        }
    }
}

質問を間違って読んだと思います。質問:システムギャラリーではなく
ドローアブル

1

ImageWorkerライブラリはビットマップをドローアブルまたはbase64に、またはその逆に変換できます。

val bitmap: Bitmap? = ImageWorker.convert().drawableToBitmap(sourceDrawable)

実装

プロジェクトレベルのGradle

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

アプリケーションレベルのGradle

dependencies {
            implementation 'com.github.1AboveAll:ImageWorker:0.51'
    }

また、外部からビットマップ/ドローアブル/ base64イメージを保存および取得することもできます。

こちらをチェックしてください。https://github.com/1AboveAll/ImageWorker/edit/master/README.md

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.