Bir Drawable'ı bir Bitmap'e dönüştürme


947

DrawableCihazın duvar kağıdı olarak belirli bir ayar yapmak istiyorum , ancak tüm duvar kağıdı işlevleri Bitmapyalnızca s kabul ediyor . Kullanamıyorum WallpaperManagerçünkü önüm 2.1.

Ayrıca, çizilebilir defterlerim web'den indirilir ve içinde bulunmaz R.drawable.



1
lütfen doğru cevabı seçin, bu: stackoverflow.com/a/3035869/4548520
user25 15

Yanıtlar:


1289

Bu kod parçası yardımcı olur.

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

Burada görüntünün indirildiği bir sürüm.

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 değerlerine sahip olduğunuzu düşünüyorum. düzeltilmiş cevabım yardımcı olacaktır.
Praveen

str_url nereden geliyor? Dizelerle ilgili herhangi bir Çekilebilir işlev bulamadım ... yardımınız için teşekkürler.
Rob

12
Ben bir şey buldum düşünüyorum: "beraberlik" çizilebilir bir bitmap sonra dönüştürmek istiyorum: Bitmap bitmap = ((BitmapDrawable) beraberlik) .getBitmap (); hile yapar!
Rob

1
@Rob: Drawable'ınız yalnızca BitmapDrawable ise. (yani
Çekilebilir'iniz

2
not: Bu büyük java.lang.OutOfMemoryError JPG's ile neden olur
Someone Somewhere Somewhere

743
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
Bu, her türlü çekilebilir için işe yarayacak tek cevap gibi görünüyor ve aynı zamanda zaten bir BitmapDrawable olan bir çekilebilir için hızlı bir çözüme sahip. +1
Matt Wolfe

1
sadece bir değişiklik: docs BitmapDrawable.getBitmap () hakkında null geri gelebileceğini söylüyor. Ben de geri dönüştürülmüş geri gelebilir diyorum.
kellogs

16
Dikkat: getIntrinsicWidth()ve getIntrinsicHieght()çekilebilir düz bir renk ise -1 dönecektir.
SD

5
Yani ... ColorDrawable için bir başka kontrol daha var ve kazananımız var. Cidden, birisi bunu kabul edilen cevap yapar.
Kaay

2
İşaretli cevabın aksine, bu soruya cevap verir.
njzk2

214

Bu, bir BitmapDrawable'ı bir Bitmap'e dönüştürür.

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

9
bu gerçekten en iyi yol mu? Elbette çekilebilir başka bir tür olabilir ve bu bir runtimeException atmak? Örneğin, bir ninePatchDrawble olabilir ...?
Dori

4
@Dori, BitmapDrawabledökümden önce gerçekten bir olup olmadığını kontrol etmek için kodu koşullu bir ifadeye sarabilirsiniz : if (d instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable)d).getBitmap(); }
Tony Chan

367
64 upvotes inanamıyor musunuz? Bu kod sadece dzaten bir a ise çalışır BitmapDrawable, bu durumda bir bitmap olarak almak önemsizdir ... ClassCastExceptionTüm diğer durumlarda çökecektir.
Matthias

3
@Matthias bahsetmiyorum .. sorunun kendisi, aynı yazar, 100 oy var: /
quinestor

2
Bu önemsiz bir durum için çok uzmanlaşmıştır.
njzk2

141

A Drawable, a üzerine çizilebilir Canvasve a Canvasaşağıdakilerle desteklenebilir Bitmap:

( BitmapDrawableS için hızlı bir dönüşüm gerçekleştirecek ve Bitmapoluşturulan öğenin geçerli bir boyuta sahip olmasını sağlayacak şekilde güncellenmiştir )

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;
}

Çekilebilir param boşsa ne olur?
hrules6872

1
Bu yöntem VectorDrawable'ı desteklemiyor
Mahmoud


Boş olmayan bir Çekmeceye sahip olduğunuzu varsayarsak, neden genişlik ve yüksekliğin 0 olmadığını kontrol etmeye ihtiyaç vardır? Ayrıca, aynı boyutta iseler neden setBounds () kullanmanız gerekiyor?
Yoav Feuerstein

İyi çözüm! Android 8.0 / sdk 26 ApplicationInfo.loadIcon (PackageManager pm) bir AdaptiveIconDrawable döndürür code Kodunuzu kullanın AdaptiveIconDrawable'ı bitmap cast kullanmama yardımcı olabilir。
burulangtu

43

YÖNTEM 1 : Ya böyle bitmap'e doğrudan dönüştürebilirsiniz

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

YÖNTEM 2 : Kaynağı çekilebilir hale dönüştürebilir ve bundan böyle bitmap alabilirsiniz

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

İçin API> 22 getDrawable yöntemi taşındı ResourcesCompatbu yüzden böyle bir şey yapmak bunun için sınıfın

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

ResourcesCompat yalnızca drawable bir BitmapDrawable ise çalışır, VectorDrawable kullanıyorsanız, bir CCE'ye sahip olursunuz.
Brill Pappin

Bunların hiçbiri VectorDrawable kaynağıyla çalışmaz . Aşağıdaki hata oluşur -android.graphics.drawable.VectorDrawable cannot be cast to android.graphics.drawable.BitmapDrawable
Adam Hurwitz

Bu çözüm Kotlin ile iyi çalışır.
Adam Hurwitz


15

Diğer cevaplara baktıktan (ve kullandıktan) sonra, hepsi iyi ColorDrawableve PaintDrawablekötü görünüyor . (Özellikle lolipopta), Shaders renklerin katı blokların doğru bir şekilde işlenmediği için ince ayarlanmış gibi görünüyordu .

Şimdi aşağıdaki kodu kullanıyorum:

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;
}

Diğerlerinin aksine eğer arama setBoundsüzerinde Drawablebir bitmap çevirmek için istemeden önce, doğru boyutta bitmap çekecek!


Setbounds çekmecenin önceki sınırlarını bozmaz mıydı? Daha sonra depolamak ve geri yüklemek daha iyi değil mi?
android geliştirici

@androiddeveloper, sınırlar belirlenmişse, bunları zaten kullanıyoruz. Bazı durumlarda, sınırların belirlenmediği ve gerçek boyutunun olmadığı durumlarda bu gereklidir (bazı durumlarda ColorDrawables gibi). Yani genişlik ve yükseklik 0 olur, çekilebilir 1x1'i bir şey çizer. Bu durumlarda ColorDrawable için bir tür kontrol yapabileceğimizi iddia edebilirim, ancak bu vakaların% 99'unda işe yarar. (Gereksinimleriniz için değiştirebilirsiniz).
Chris.Jenkins

@ Chris.Jenkins Sınırları yoksa, şimdi yenilerini alacak mı? Ayrıca başka bir soru sormak istiyorum: Döndürülen bitmap boyutunu (BitmapDrawable için bile) ayarlamanın en iyi yolu nedir?
android geliştirici

Kodu dikkatlice okumanızı tavsiye ederim. Eğer Drawableyoksa sınırları kullandığı set IntrinsicWidth/Height. Her ikisi de <= 0 ise, tuvali 1 piksel olarak ayarladık. DrawableSınırları yoksa, bazı geçirilecek (1x1 çoğu durumda), ancak bu ColorDrawablegerçek boyutlara sahip OLMAYAN şeyler için GEREKLİDİR. Eğer bunu yapmazsak, Exceptionbir tuvale 0x0 çizemezsiniz.
Chris.Jenkins

1
mutate()orijinal sınırları tek başına çekilebilir bırakarak orijinal sınırlara geri dönme sorununu ortadan kaldıracak bir kopya oluşturur. Ben nadiren bu noktalara göre kodu değiştirmek için. Kullanım durumunuz gerektiriyorsa başka bir yanıt ekleyin. Bitmap ölçeklemesi için başka bir soru oluşturmanızı öneririm.
Chris.Jenkins

13

Belki bu birine yardım eder ...

PictureDrawable'dan Bitmap'e şunu kullanın:

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; 
}

... şu şekilde uygulanmaktadır:

Bitmap bmp = pictureDrawableToBitmap((PictureDrawable) drawable);

Rob'un cevabında olduğu gibi, belirli bir tipte Drawable, bu durumda a PictureDrawable.
kabuko

4
"Belki bu birine yardımcı olacaktır ..."
Mauro

11

İşte daha iyi çözünürlük

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());
}

Kod How InputStream olarak çekilebilir bitlerini okumak


11

1) Bitmap'e çekilebilir:

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

2) Çekilebilir Bitmap:

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

10

@ Chris.Jenkins tarafından verilen cevabın güzel Kotlin versiyonu: 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


8

Android olmayan bir basittir geçin çözüm sağlar: BitmapDrawable. Bitmap almak için, kaynak kimliği sağlamanız gerekecek R.drawable.flower_pica kadar BitmapDrawableve daha sonra bir için döküm Bitmap.

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

5

Bu kodu kullanın. Hedefinize ulaşmanızda size yardımcı olacaktır.

 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()bitmap'i otomatik olarak ölçeklendirir, böylece bitmap'iniz bulanık olabilir. Ölçeklendirmeyi önlemek için şunları yapın:

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

veya

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

2

kotlin kullanıyorsanız aşağıdaki kodu kullanın. işe yarayacak

// görüntü yolunu kullanmak için

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);
        }
    }
}

Sanırım soruyu yanlış okudun. Soru soruyor: Sistem galerisi değil, çekilebilir bir kaynaktan bir bitmap nasıl elde edilir
kc ochibili

1

ImageWorker Kütüphanesi bitmap'i çekilebilir veya base64'e dönüştürebilir veya tersi de geçerlidir.

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

uygulama

Proje Seviyesinde

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

Uygulama Seviyesinde

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

Ayrıca bitmap'leri / çekilebilirleri / base64 görüntüleri harici olarak saklayabilir ve alabilirsiniz.

Burayı kontrol et. https://github.com/1AboveAll/ImageWorker/edit/master/README.md

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.