Как преобразовать Drawable в растровое изображение?

950

Я хотел бы установить определенные Drawableв качестве обоев устройства, но все функции обоев принимают Bitmapтолько s. Я не могу использовать, WallpaperManagerпотому что я предварительно 2.1.

Кроме того, мои рисунки загружаются из Интернета и не находятся в R.drawable.

обкрадывать
источник
1
Пожалуйста, выберите правильный ответ, это: stackoverflow.com/a/3035869/4548520
user25
1
stackoverflow.com/a/15555203/1731082
Эрфан Багери

Ответы:

1290

Этот кусок кода помогает.

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);
}
Praveen
источник
1
Я думаю, у вас есть значения URL. тогда мой отредактированный ответ должен помочь.
Правин
откуда берется str_url? Я не смог найти функцию Drawable, связанную со строками ... спасибо за вашу помощь.
Роб
12
Я думаю, что нашел что-то: если «draw» - это нарисованный объект, который я хочу преобразовать в растровое изображение, то: Bitmap bitmap = ((BitmapDrawable) draw) .getBitmap (); делает трюк!
Роб
1
@Rob: если ваш Drawable только BitmapDrawable. (что означает, что ваш Drawable - это всего лишь обертка вокруг растрового изображения)
njzk2
2
примечание: это вызывает массивный java.lang.OutOfMemoryError с JPG
Кто-то где-то
745
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 говорит о BitmapDrawable.getBitmap (), что он может вернуться к нулю. Я говорю, что это может также вернуться уже переработано.
kellogs
16
Осторожно: getIntrinsicWidth()и getIntrinsicHieght()вернет -1, если рисуемый сплошной цвет.
SD
5
Итак ... еще одна проверка для ColorDrawable, и у нас есть победитель. Серьезно, кто-то делает это принятым ответом.
Кай
2
Вопреки помеченному ответу, это отвечает на вопрос.
njzk2
214

Это преобразует BitmapDrawable в Bitmap.

Drawable d = ImagesArrayList.get(0);  
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
обкрадывать
источник
9
это действительно лучший способ? Конечно, drawable может быть другого типа, и это вызовет исключение runtimeException? Например, это может быть ninePatchDrawble ...?
Дори
4
@ Дори, вы можете обернуть код в условный оператор, чтобы проверить, действительно ли он BitmapDrawableперед тем, как его разыграть : if (d instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable)d).getBitmap(); }
Тони Чан,
367
Не можете поверить, 64 голосов? Этот код , очевидно , работает , только если dуже естьBitmapDrawable , в этом случае это тривиально , чтобы получить его как растровое изображение ... Будет ли столкновение с ClassCastExceptionво всех остальных случаях.
Матиас
3
@Matthias, не говоря уже о том, что ... сам вопрос, тот же автор, имеет 100 голосов: /
quinestor
2
Это так специализируется на тривиальном случае.
njzk2
141

Drawable может быть нарисован на a Canvas, а a 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;
}
kabuko
источник
Что произойдет, если drawable param будет нулевым?
hrules6872
1
Этот метод не поддерживает VectorDrawable
Махмуд
Предполагая, что вы получаете непустой Drawable, почему нужно проверить, что ширина и высота не равны 0? Кроме того, зачем вам нужно использовать setBounds (), если они одного размера?
Йоав
Хорошее решение! Android 8.0 / sdk 26 ApplicationInfo.loadIcon (PackageManager pm) возвращает AdaptiveIconDrawable。 Использование вашего кода может помочь мне привести AdaptiveIconDrawable к растровому изображению。
burulangtu
45

МЕТОД 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();
Keyur
источник
ResourcesCompat работает только в том случае, если объект рисования является BitmapDrawable, если вы используете VectorDrawable, то у вас будет CCE.
Брилл Паппин
Ни один из них не работает с ресурсом VectorDrawable . Возникает следующая ошибкаandroid.graphics.drawable.VectorDrawable cannot be cast to android.graphics.drawable.BitmapDrawable
Адам Гурвиц
Это решение хорошо работает с Kotlin.
Адам Гурвиц
31

очень просто

Bitmap tempBMP = BitmapFactory.decodeResource(getResources(),R.drawable.image);
Эрфан Багери
источник
6
Это просто плагиат другого ответа на этот вопрос три года назад
Ник Кардосо
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как попросить превратить его в растровое изображение, оно будет отображать растровое изображение в правильном размере!

Chris.Jenkins
источник
Разве setBounds не разрушит предыдущие границы отрисовки? Не лучше ли хранить его и восстанавливать потом?
Android-разработчик
@androiddeveloper, если границы были установлены, мы все равно их используем. В некоторых случаях это необходимо, когда границы не установлены и не имеют собственного размера (например, ColorDrawables в некоторых случаях). Таким образом, ширина и высота будут равны 0, мы даем рисуемому 1x1 таким образом, чтобы он что-то рисовал. Я мог бы утверждать, что мы могли бы сделать проверку типа для ColorDrawable в тех случаях, но это работает в 99% случаев. (Вы можете изменить его для своих нужд).
Chris.Jenkins
@ Chris.Jenkins Что если у него нет границ, а теперь у него будут новые? Я также хотел бы задать еще один вопрос: каков наилучший способ установить размер растрового изображения (даже для BitmapDrawable), который будет возвращен?
Android-разработчик
Я предлагаю вам внимательно прочитать код. Если Drawableграницы не установлены, он использует IntrinsicWidth/Height. Если они оба <= 0, мы устанавливаем холст в 1px. Вы правы, если Drawableу границы нет границ, ей будут пропущены некоторые (в большинстве случаев 1x1), но это ТРЕБУЕТСЯ для таких вещей, ColorDrawableкоторые НЕ имеют внутренних размеров. Если бы мы этого не делали, это бы вывело Exception, вы не можете нарисовать 0x0 на холсте.
Chris.Jenkins
1
mutate()сделал бы копию, оставив оригинал пригодным для рисования в одиночку, что сведет на нет проблему возврата в исходные рамки. Я редко меняю код, основываясь на этих пунктах. Если ваш вариант использования требует, добавьте еще один ответ. Я предлагаю вам создать еще один вопрос для масштабирования растровых изображений.
Chris.Jenkins
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);
Mauro
источник
Как и в случае с ответом Роба, вам требуется определенный тип Drawable, в данном случае a 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 mIcon = BitmapFactory.decodeResource(context.getResources(),R.drawable.icon);
// mImageView.setImageBitmap(mIcon);

2) растровое изображение в Drawable:

Drawable mDrawable = new BitmapDrawable(getResources(), bitmap);
// mImageView.setDrawable(mDrawable);
Sanjayrajsinh
источник
10

Вот хорошая версия ответа от Kotlin, предоставленная @ 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
tasomaniac
источник
8

Android обеспечивает не прямое решение Foward: BitmapDrawable. Чтобы получить растровое изображение, мы должны предоставить идентификатор ресурса 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);
Джон Доу
источник
3

Последняя базовая библиотека androidx (androidx.core: core-ktx: 1.2.0) теперь имеет функцию расширения:Drawable.toBitmap(...) для преобразования Drawable в растровое изображение.

Balazs Banyai
источник
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);
        }
    }
}
ангел
источник
Я думаю, что вы прочитали вопрос неправильно. Спрашивается вопрос: как получить растровое изображение из рисованного ресурса, а не из системной галереи
kc ochibili
1

Библиотека ImageWorker может конвертировать растровое изображение в drawable или 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

Химаншу Рават
источник