कैसे एक बिटमैप के लिए एक Drawable कन्वर्ट करने के लिए?


947

मैं Drawableडिवाइस के वॉलपेपर के रूप में एक निश्चित सेट करना चाहता हूं , लेकिन सभी वॉलपेपर फ़ंक्शन Bitmapकेवल एस स्वीकार करते हैं । मैं उपयोग नहीं कर सकता WallpaperManagerक्योंकि मैं पूर्व 2.1 हूँ।

इसके अलावा, मेरे ड्रॉबल्स को वेब से डाउनलोड किया जाता है और इसमें निवास नहीं किया जाता है R.drawable



1
कृपया सही उत्तर का चयन करें, यह: stackoverflow.com/a/3035869/4548520
user25

जवाबों:


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 मान हैं। तो मेरे संपादित जवाब में मदद करनी चाहिए।
प्रवीण

str_url कहाँ से आता है? मुझे स्ट्रिंग्स से संबंधित कोई भी ड्रा करने योग्य फ़ंक्शन नहीं मिला ... आपकी मदद के लिए धन्यवाद।
रोब

12
मुझे लगता है कि मुझे कुछ मिला: अगर "ड्रा" वह ड्रॉबल है जिसे मैं बिटमैप में बदलना चाहता हूं: बिटमैप बिटमैप = ((बिटमैपड्रेबल) ड्रा) .getBitmap (); उसने चाल चली!
रोब

1
@ रब: यदि आपका ड्रॉवेबल केवल बिटमैप है। (जिसका अर्थ है कि आपका
ड्रॉएबल

2
ध्यान दें: इसके कारण बड़े पैमाने पर java.lang.OutOfMemoryError JPG के साथ है
किसी को कहीं

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
यह एकमात्र उत्तर की तरह दिखता है जो किसी भी प्रकार के ड्रॉएबल के लिए काम करेगा और ड्रॉबल के लिए एक त्वरित समाधान भी है जो पहले से ही एक बिटमैपडेबल है। +1
मैट वोल्फ

1
केवल एक संशोधन: डॉक्स BitmapDrawable.getBitmap () के बारे में कहते हैं कि यह शून्य हो सकता है। मैं कहता हूं कि यह पहले से पुनर्नवीनीकरण भी हो सकता है।
kellogs

16
बाहर देखो: getIntrinsicWidth()और getIntrinsicHieght()-1 वापस आ जाएगा अगर drawable एक ठोस रंग है।
एसडी

5
तो ... ColorDrawable के लिए एक और चेक, और हमारे पास एक विजेता है। गंभीरता से, कोई इसे स्वीकृत उत्तर देता है।
काय

2
ध्वजांकित उत्तर के विपरीत, यह प्रश्न का उत्तर देता है।
njzk2

214

यह एक बिटमैप को बिटमैप में परिवर्तित करता है।

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

9
क्या यह वास्तव में सबसे अच्छा तरीका है? निश्चित रूप से ड्रॉबल दूसरे प्रकार का हो सकता है और यह रनटाइम एक्ससेप्शन फेंक देगा? उदाहरण के लिए, यह एक नौचौकी हो सकती है ...?
डोरी

4
@ डोरी आप एक सशर्त विवरण में कोड को यह जांचने के लिए लपेट सकते हैं कि क्या यह वास्तव में BitmapDrawableकास्टिंग से पहले है: if (d instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable)d).getBitmap(); }
टोनी चैन

367
64 upvotes पर विश्वास नहीं कर सकते? यह कोड स्पष्ट रूप से केवल तभी काम करता है जब dपहले से ही एक है BitmapDrawable, जिस स्थिति में इसे एक बिटमैप के रूप में प्राप्त करना तुच्छ है ... ClassCastExceptionसभी मामलों में दुर्घटनाग्रस्त हो जाएगा ।
Matthias

3
@ मैथियास का उल्लेख नहीं है कि .. सवाल ही, एक ही लेखक, 100 वोट हैं: /
quinestor

2
यह एक तुच्छ मामले के लिए विशेष है।
njzk2

141

A Drawableको एक पर खींचा जा सकता है Canvas, और एक Canvasद्वारा समर्थित किया जा सकता है Bitmap:

( BitmapDrawableएस के लिए एक त्वरित रूपांतरण को संभालने के लिए अद्यतन किया गया है और यह सुनिश्चित करने के लिए कि 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;
}

अगर ड्रॉबल परम शून्य है तो क्या होगा?
hrules6872

1
इस विधि का समर्थन नहीं करता वेक्टरड्राेबल
महमूद


यह मानते हुए कि आपको एक गैर-रिक्त ड्रॉबल मिल गया है, तो उस चौड़ाई और ऊंचाई की जाँच करने की आवश्यकता क्यों नहीं है? इसके अलावा, यदि आपको एक ही आकार का है, तो आपको सेटबाउंड () का उपयोग करने की आवश्यकता क्यों है?
योआव फ्यूरस्टीन

अच्छा समाधान fo Android 8.0 / sdk 26 ApplicationInfo.loadIcon (PackageManager pm) एक AdaptiveIconDrawable वापस करें code अपने कोड का उपयोग करें मुझे AdaptiveIconDrawable को बिटमैप
bur

43

विधि 1 : या तो आप इस तरह सीधे बिटमैप में परिवर्तित कर सकते हैं

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

METHOD 2 : आप संसाधन को ड्रॉबल में भी बदल सकते हैं और उसी से आप इस तरह बिटमैप प्राप्त कर सकते हैं

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

के लिए एपीआई> 22 getDrawable विधि में ले जाया गया ResourcesCompatतो के लिए है कि आप कुछ इस तरह कर वर्ग

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

ResourcesCompat केवल तभी काम करता है यदि ड्रॉबल एक बिटमैपडेबल है, यदि आप वेक्टरड्रॉबल का उपयोग कर रहे हैं, तो आप CCE करने जा रहे हैं।
ब्रिल पप्पिन

न तो इनमें से कोई वेक्टरड्राइव संसाधन के साथ काम करता है। निम्नलिखित त्रुटि होती है -android.graphics.drawable.VectorDrawable cannot be cast to android.graphics.drawable.BitmapDrawable
एडम हर्वित्ज

यह समाधान कोटलिन के साथ अच्छी तरह से काम करता है।
एडम हर्वित्ज


15

इसलिए अन्य उत्तरों की तलाश (और उपयोग) के बाद, लगता है कि वे सभी को संभाल रहे हैं ColorDrawableऔर PaintDrawableबुरी तरह से। (विशेष रूप से लॉलीपॉप पर) ऐसा लगता था कि 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यह एक बिटमैप में बदलने के लिए पूछ रहा से पहले, यह बिटमैप सही आकार में आकर्षित करेगा!


क्या सेट करने योग्य सीमाएं ड्रा करने योग्य के पिछले सीमा को बर्बाद नहीं करेंगी? क्या इसे स्टोर करना और बाद में इसे बहाल करना बेहतर नहीं है?
एंड्रॉयड डेवलपर

@androiddeveloper, यदि सीमाएं निर्धारित की गई हैं, तो हम वैसे भी उपयोग कर रहे हैं। कुछ मामलों में यह आवश्यक है जहां कोई सीमा निर्धारित नहीं की गई है और कोई आंतरिक आकार नहीं है (जैसे कि कुछ मामलों में ColorDrawables)। तो चौड़ाई और ऊँचाई 0 होगी, हम ड्रा करने योग्य 1x1 देते हैं जिस तरह से यह वास्तव में कुछ आकर्षित करता है। मुझे तर्क दिया जा सकता है कि हम उन मामलों में ColorDrawable के लिए एक प्रकार की जाँच कर सकते हैं, लेकिन यह 99% मामलों के लिए काम करता है। (आप इसे अपनी आवश्यकताओं के लिए संशोधित कर सकते हैं)।
क्रिस। जेनकिंस

@ क्रिस। जेनकिंस क्या है अगर इसमें सीमा नहीं है, और अब इसे नया मिलेगा? मैं एक और सवाल पूछना चाहता हूं: बिटमैप आकार (यहां तक ​​कि बिटमैप के लिए भी) सेट करने का सबसे अच्छा तरीका क्या है?
एंड्रॉयड डेवलपर

मेरा सुझाव है कि आप कोड को ध्यान से पढ़ें। यदि Drawableसीमा निर्धारित नहीं है, तो यह उपयोग करता है IntrinsicWidth/Height। यदि वे दोनों <= 0 हैं, तो हम कैनवास को 1px पर सेट करते हैं। आप सही हैं यदि Drawableसीमा नहीं है तो इसे कुछ पास किया जाएगा (1x1 सबसे अधिक मामले हैं), लेकिन यह उन चीजों के लिए आवश्यक है, ColorDrawableजिनमें आंतरिक आकार नहीं हैं। अगर हमने ऐसा नहीं किया, तो यह एक फेंक देगा Exception, आप 0x0 को एक कैनवस पर नहीं खींच सकते।
क्रिस। जेनकिंस

1
mutate()मूल ड्रॉबल को छोड़कर एक कॉपी बना देगा जो मूल सीमा में वापस पारित होने के मुद्दे को नकार देगा। मैं उन बिंदुओं के आधार पर कोड बदलने के लिए शायद ही कभी हूँ। यदि आपके उपयोग के मामले में इसे एक और उत्तर जोड़ने की आवश्यकता है। मेरा सुझाव है कि आप बिटमैप स्केलिंग के लिए एक और प्रश्न बनाएं।
क्रिस। जेनकिंस

13

शायद यह किसी की मदद करेगा ...

चित्रपट से बिटमैप तक, उपयोग करें:

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

रोब के जवाब के साथ, आपको Drawableइस मामले में एक विशेष प्रकार की आवश्यकता है PictureDrawable
काबूको

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

इनपुटस्ट्रीम के रूप में ड्रा करने योग्य बिट्स को पढ़ने के लिए कोड


11

1) बिटमैप के योग्य:

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

2) ड्रा करने योग्य के लिए बिटमैप:

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

8

एंड्रॉइड एक गैर सीधे फ़ॉवर्ड समाधान प्रदान करता है BitmapDrawable:। बिटमैप को प्राप्त करने के लिए, हमें संसाधन आईडी R.drawable.flower_picको ए को प्रदान करना होगा BitmapDrawableऔर फिर इसे एक को डालना होगा Bitmap

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

8

android-ktx में Drawable.toBitmapविधि है: https://android.github.io/android-ktx/core-ktx/androidx.graphics.rectable/android.graphics.drawable.-drawable/to-bitmap.html

कोटलिन से

val bitmap = myDrawable.toBitmap()

VectorDrawableकोटलिन में ए के लिए यह सबसे सरल उपाय है ! इसके अलावा इस एसओ पोस्ट में यहां और अधिक विस्तार से साझा किया गया है।
एडम हर्वित्ज

5

इस कोड का उपयोग करें। यह आपको अपना लक्ष्य प्राप्त करने में मदद करेगा।

 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

यदि आप कोड के नीचे कोटलिन का उपयोग कर रहे हैं। यह काम करेगा

// छवि पथ का उपयोग करने के लिए

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

मुझे लगता है कि आपने प्रश्न को गलत पढ़ा है। सवाल पूछता है: कैसे एक drawable संसाधन नहीं सिस्टम गैलरी से एक बिटमैप पाने के लिए
kc ochibili

1

ImageWorker लाइब्रेरी बिटमैप को ड्रा करने योग्य या बेस 64 और इसके विपरीत में बदल सकती है।

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

कार्यान्वयन

प्रोजेक्ट लेवल ग्रेड में

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

आवेदन स्तर ग्रेड में

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

आप बाहरी से बिटमैप / ड्राबल्स / बेस 64 इमेज को स्टोर और पुनः प्राप्त कर सकते हैं।

यहा जांचिये। https://github.com/1AboveAll/ImageWorker/edit/master/README.md

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.