Як перетворити графічний файл у бітну карту?


947

Я хотів би встановити певний Drawableяк шпалери пристрою, але всі функції шпалер приймають Bitmapлише s. Я не можу використовувати, 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? Не вдалося знайти жодну функцію Dravable, пов’язану з рядками ... дякую за вашу допомогу.
Роб

12
Я думаю, що я щось знайшов: якщо "draw" - це малюнок, який я хочу перетворити на растрову карту, тоді: Bitmap bitmap = ((BitmapDravable) draw) .getBitmap (); робить трюк!
Роб

1
@Rob: якщо ваш Dravable - лише BitmapDrawable. (це означає, що ваш Dravable - це лише обгортка навколо Bitmap)
njzk2

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
Це схоже на єдину відповідь, яка працювала б для будь-якого виду малювання, а також має швидке рішення для малювання, яке вже є BitmapDrawable. +1
Метт Вулф

1
лише одна поправка: docs говорить про BitmapDravable.getBitmap (), що вона може повернутися нульовою. Я кажу, що він також може повернутися вже переробленим.
kellogs

16
Слідкуйте: getIntrinsicWidth()і getIntrinsicHieght()повернеться -1, якщо малюнок буде суцільним кольором.
SD

5
Отже ... черговий чек на ColorDravable, і у нас є переможець. Серйозно, хтось робить це прийнятою відповіддю.
kaay

2
На відміну від позначеної відповіді, це відповідає на питання.
njzk2

214

Це перетворює BitmapDrawable в Bitmap.

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

9
це справді найкращий спосіб? Зрозуміло, що малювання може бути іншого типу, і це кине виконувати час? Наприклад, це може бути дев'ятьPatchDrawble ...?
Дорі

4
@Dori, ви можете загорнути код у умовному звіті, щоб перевірити, чи він справді BitmapDrawableперед тим, як його викласти : if (d instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable)d).getBitmap(); }
Тоні Чан

367
Не можете повірити 64-ю нагородам? Цей код , очевидно , працює , тільки якщо dвже єBitmapDrawable , в цьому випадку це тривіально , щоб отримати його як растрове зображення ... Буде чи зіткнення з ClassCastExceptionу всіх інших випадках.
Маттіас

3
@Matthias не кажучи про це .. у самого питання, того ж автора, є 100 голосів: /
quinestor

2
Це настільки спеціалізується на тривіальному випадку.
njzk2

141

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

Що станеться, якщо параметр, що малюється, недійсний?
hrules6872

1
Цей метод не підтримує VectorDravable
Махмуд


Якщо припустити, що ви отримуєте не порожній малюнок, чому потрібно перевірити, чи ширина і висота не дорівнюють 0? Крім того, навіщо вам використовувати setBounds (), якщо вони однакового розміру?
Йоав Фюерштейн

Гарне рішення! Android 8.0 / sdk 26 ApplicationInfo.loadIcon (PackageManager pm) повернути AdaptiveIconDravable。 Використання коду може допомогти мені віддати AdaptiveIconDravable до растрової
картини

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, якщо ви використовуєте VectorDravable, тоді у вас буде CCE.
Брілл Паппін

Жоден із них не працює з ресурсом VectorDrawable . Трапляється така помилка -android.graphics.drawable.VectorDrawable cannot be cast to android.graphics.drawable.BitmapDrawable
Адам Гурвіц

Це рішення добре працює з Котліном.
Адам Гурвіц


15

Тож після перегляду (та використання) інших відповідей, здається, що всі вони кепські ColorDrawableта PaintDrawableпогані. (Особливо на льодянику) здавалося, що Shaders були підроблені, тому тверді блоки кольорів неправильно обробляються.

Зараз я використовую такий код:

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як попросити перетворити його в растрову карту, він намалюватиме растрову карту правильного розміру!


Чи не встановленіBound не руйнують попередні межі чертежного? Хіба не краще його зберігати та відновлювати після цього?
андроїд розробник

@androiddeveloper, якщо межі встановлені, ми все одно їх використовуємо. У деяких випадках це потрібно, коли не встановлено меж і не має внутрішнього розміру (наприклад, ColorDrawables у деяких випадках). Тож ширина і висота були б 0, ми даємо рисунок 1x1 таким чином, щоб він насправді щось малював. Я можу стверджувати, що в цих випадках ми можемо перевірити тип ColorDravable, але це працює у 99% випадків. (Ви можете змінити його для своїх потреб).
Chris.Jenkins

@ Chris.Jenkins Що робити, якщо у неї немає меж, і тепер вони отримають нові? Я також хотів би задати ще одне питання: який найкращий спосіб встановити розмір растрової карти (навіть для BitmapDravable), який повертається?
андроїд розробник

Я пропоную уважно прочитати код. Якщо Drawableне встановлено меж, він використовує IntrinsicWidth/Height. Якщо вони обидва <= 0, встановимо полотно в 1px. Ви маєте рацію, якщо у Drawableмеж немає меж, вони будуть пропущені деякими (1x1 - це більшість випадків), але це ПОТРІБНО для речей, на кшталт ColorDrawableяких НЕ мають внутрішніх розмірів. Якби ми цього не зробили, це викине Exception, ви не можете намалювати 0x0 на полотні.
Chris.Jenkins

1
mutate()зробила б копію, залишивши оригінал малювачем у спокої, що скасувало б питання про повернення назад у вихідні межі. Я рідко змінюю код на основі цих пунктів. Якщо ваш випадок використання вимагає, додайте іншу відповідь. Я пропоную вам створити ще одне питання щодо масштабування Bitmap.
Кріс.Дженкінс

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

Як і у відповіді Роба 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());
}

Код з " Як читати" біти, що малюються як "InputStream"


11

1) доступний для Bitmap:

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

2) растровий малюнок до Dravable:

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

10

Ось приємна версія котлінської відповіді, яку надав @ Chris.Jenkins тут: 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 забезпечує не пряме рішення Foward: BitmapDrawable. Щоб отримати Bitmap, нам доведеться надати ідентифікатор ресурсу R.drawable.flower_pica, BitmapDrawableа потім передати його 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)

Впровадження

На рівні проекту

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

У рівні програми Gradle

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

Ви також можете зберігати та витягувати растрові / малюнкові / базові64 зображення із зовнішніх.

Перевірте тут. https://github.com/1AboveAll/ImageWorker/edit/master/README.md

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.