वेक्टर ड्रॉबल से बिटमैप प्राप्त करना


132

मेरे आवेदन में, मुझे एक अधिसूचना के लिए एक बड़ा आइकन सेट करना होगा। लार्जकैम एक बिटमैप होना चाहिए, और मेरी ड्रॅबल्स वेक्टर छवियां हैं (एंड्रॉइड में नई सुविधा, इस लिंक को देखें ) समस्या यह है कि जब मैं एक संसाधन को डिकोड करने की कोशिश करता हूं जो एक वेक्टर छवि है, तो मुझे एक शून्य वापस मिल जाता है।

यहाँ कोड का नमूना है:

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 को प्रतिस्थापित करता हूं, तो छूट के लिए एक पीएनजी, परिणाम शून्य नहीं है (मुझे सही बिटमैप मिलता है) क्या मुझे कुछ याद आ रहा है?


1
था समान मुद्दा है, समाधान नहीं है, लेकिन एक वैकल्पिक हल: stackoverflow.com/questions/33548447/...
से

जवाबों:


231

एपीआई पर जाँच की गई: 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
    }
    ...
}
...

धन्यवाद। पिछला उत्तर sdk संस्करण के साथ काम नहीं कर रहा है जो 23 से शुरू होता है
Paha

2
यह मेरे लिए बहुत अच्छा काम करता है। एक समस्या के बिना एपीआई 15 पर चल रहा है
वेरा

4
AppCompatDrawableManagerके रूप में चिह्नित किया गया है @RestrictTo(LIBRARY_GROUP)इसलिए यह आंतरिक है और आपको इसका उपयोग नहीं करना चाहिए (यह एपीआई नोटिस के बिना बदल सकता है)। ContextCompatइसके बजाय उपयोग करें ।
mradzinski

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Bitmap.setHasAlpha(boolean)' on a null object referenceइस लाइन पर काम नहीं करताBitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
20:25

5
मेरे पास इसके समाधान के मुद्दे थे। मेरे लिए उपयोग करने के लिए: ContextCompat के बजाय AppCompatResources ने इसे ठीक किया: Drawable drawable = AppCompatResources.getDrawable (संदर्भ, drawableId);
माइक टी

64

आप निम्न विधि का उपयोग कर सकते हैं:

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

2
उम्मीद है कि @liltof वापस आता है और इसे उत्तर के रूप में चिह्नित करता है। ध्यान देने वाली बात यह है कि दोनों विधियां टारगेटरी रैपर चाहते हैं - लेकिन एंड्रॉइड स्टूडियो आपको यह बताएगा।
रॉबर्टो टोमोस

1
मैंने लगभग दो दिन बिताने की कोशिश की है, अब इसके svg फ़ाइल मुद्दे पर विचार कर रहा हूँ। धन्यवाद!
स्पार्कली_फ्रॉग

1
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Bitmap.setHasAlpha(boolean)' on a null object referenceइस लाइन पर काम नहीं करताBitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
20:25

45

यदि आप कोटलिन के लिए एंड्रॉइड केटीएक्स का उपयोग करने के लिए तैयार हैं, तो आप 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.2.0"
}

अपनी परियोजना पर निर्भरता जोड़ने के लिए नवीनतम निर्देशों के लिए यहां देखें ।

ध्यान दें कि यह के लिए काम करेंगे किसी भी के उपवर्ग Drawableऔर अगर Drawableएक BitmapDrawableयह अंतर्निहित उपयोग करने के लिए शॉर्टकट जाएगा Bitmap


कोटलिन के लिए यह सबसे सरल उपाय है।
एडम हर्वित्ज

1
मेरे लिए यह पूरी तरह से ठीक काम करता है VectorDrawable
ubuntudroid

यह सबसे अच्छा विकल्प है .. डिफ़ॉल्ट androidx कार्यक्षमता प्रदान करता है
रेशमा

27

पिछले उत्तरों के आधार पर इसे इस तरह सरल बनाया जा सकता है कि वेक्टरड्रैबल और बिटमैपडर्वेबल दोनों को मिलाया जा सके और कम से कम एपीआई 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");
    }
}

फिर आपको अपनी ग्रेडेल फ़ाइल में जोड़ना होगा:

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

प्री-लॉलीपॉप पर यह वेक्टरड्राएबल.कॉम का उपयोग करेगा और लॉलीपॉप पर यह वेक्टरड्राेबल का उपयोग करेगा।

संपादित करें

मैंने @ user3109468 की टिप्पणी के बाद स्थिति संपादित की है


1
ड्रिबल इंस्टाफॉरेक्ट वेक्टरड्राएबल || आकर्षित करने योग्य इंस्ट्रूमेंट वेक्टरड्राएबल.कॉमप में पक्षों की अदला-बदली होनी चाहिए। जब वेक्टरड्राएबल मौजूद नहीं होता है, तो क्लास में परिणाम नहीं मिलते हैं, जब वेक्टरड्राएबेबल.कॉम को पहले चेक किया जाना चाहिए क्योंकि यह मौजूद है।
वारिक

VertorDrawable के प्रकार की जाँच के रूप में वर्णित किया जा सकता है(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && drawable instanceof VectorDrawable)
chmin

6

कुडोस से @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)

1

एपीआई 16 पर परीक्षण किया गया - वेक्टर ड्रॉबल्स के साथ जेलीबीन

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

1

छवि को सही पहलू अनुपात (उदाहरण के लिए अधिसूचना आइकन) के साथ परिवर्तित करने के लिए निम्न कोड का उपयोग करें :

public static Bitmap getBitmapFromVector(Context context, int drawableId) {
    Drawable drawable = ContextCompat.getDrawable(context, drawableId);
    int width = drawable.getIntrinsicWidth();
    int height = drawable.getIntrinsicHeight();
    Bitmap bitmap;
    if (width < height) {    //make a square
        bitmap = Bitmap.createBitmap(height, height, Bitmap.Config.ARGB_8888);
    } else {
        bitmap = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
    }
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0,
            drawable.getIntrinsicWidth(),    //use dimensions of Drawable
            drawable.getIntrinsicHeight()
    );
    drawable.draw(canvas);
    return bitmap;
}

0

यदि आपका vectorछवि intrinsicWidthऔर intrinsicHeightछोटा है और आप एक बड़े देखने के लिए बिटमैप प्रदर्शित करने के लिए प्रयास करते हैं, तो आप परिणाम कलंक है देखेंगे।

उस मामले में, आप अपने बिटमैप बेहतर छवि प्राप्त करने के लिए एक नया चौड़ाई / ऊंचाई प्रदान कर सकते हैं (या आप एक्सएमएल में वेक्टर आकार बढ़ा सकते हैं, लेकिन उपलब्ध कराने 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
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

यदि आप अपने आउटपुट को वांछित आउटपुट आकार में स्केल करना चाहते हैं, तो निम्नलिखित स्निपेट आज़माएँ:

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

इससे आपको अपने इच्छित आकार में बिटमैप मिल जाता है। इसके अलावा, यह आपको प्रत्येक छवि के आधार पर पारदर्शिता बनाए रखने या न रखने की अनुमति देता है, जिनके लिए इसकी आवश्यकता नहीं है।

public static Bitmap drawableToBitmap(Resources res, int drawableId,
        int width, int height, boolean keepAlpha) {
    Drawable drawable = res.getDrawable(drawableId);
    Bitmap bmp = createBitmap(width, height, keepAlpha ?
            Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
    Canvas cvs = new Canvas(bmp);
    drawable.setBounds(0, 0, width, height);
    drawable.draw(cvs);
    return bmp;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.