如何将Drawable转换为位图?

我想设置某个Drawable作为设备的壁纸,但所有壁纸功能只接受Bitmap。我不能使用WallpaperManager,因为我是2.1之前的。

此外,我的绘图是从网络下载的,不驻留在R.drawable中。

777584 次浏览

这段代码有帮助。

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

这将BitmapDrawable转换为位图。

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

也许这会帮助别人……

从Picture Drawable到位图,使用:

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可以绘制到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;}
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;}
 // get image path from galleryprotected 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);}}}

非常简单

Bitmap tempBMP = BitmapFactory.decodeResource(getResources(),R.drawable.image);

这里有更好的分辨率

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

Android提供了一个非直接的解决方案:BitmapDrawable。要获得位图,我们必须将资源idR.drawable.flower_pic提供给aBitmapDrawable,然后将其转换为Bitmap

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

使用这个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;}

因此,在查看(和使用)其他答案后,似乎他们都处理ColorDrawablePaintDrawable不好。(尤其是在棒棒糖上)似乎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  > 0final 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 > 0final 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;}

与其他不同,如果您在要求将Drawable转换为位图之前调用setBounds,它将以正确的大小绘制位图!

这是@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

方法1:您可以像这样直接转换为位图

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

方法2:你甚至可以将资源转换为可绘制的,然后你可以得到这样的位图

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

forAPI>22getDrawable方法移动到ResourcesCompat类,因此您可以这样做

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

ImageWorker Library可以将位图转换为可绘制或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

android-ktx有Drawable.toBitmap方法:https://android.github.io/android-ktx/core-ktx/androidx.graphics.drawable/android.graphics.drawable.-drawable/to-bitmap.html

静态编程语言

val bitmap = myDrawable.toBitmap()

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

如果您正在使用kotlin使用下面的代码。它会起作用的

//使用图片路径

val image = Drawable.createFromPath(path)val bitmap = (image as BitmapDrawable).bitmap

1)可绘制位图:

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

2)位图可绘制:

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

最新的androidx核心库(androidx.core: core-ktx: 1.2.0)现在有一个扩展函数:#0来将Drawable转换为位图。

位图=BitmapFactory.decode资源(context.getResources(),R.drawable.icon)

这不会每次都起作用,例如,如果你的绘图是图层列表可绘图,那么它会给出一个空响应,所以作为替代方案,你需要将你的绘图绘制到画布中,然后保存为位图,请参考下面一杯代码。

public void drawableToBitMap(Context context, int drawable, int widthPixels, int heightPixels) {try {File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/", "drawable.png");FileOutputStream fOut = new FileOutputStream(file);Drawable drw = ResourcesCompat.getDrawable(context.getResources(), drawable, null);if (drw != null) {convertToBitmap(drw, widthPixels, heightPixels).compress(Bitmap.CompressFormat.PNG, 100, fOut);}fOut.flush();fOut.close();} catch (Exception e) {e.printStackTrace();}}
private Bitmap convertToBitmap(Drawable drawable, int widthPixels, int heightPixels) {Bitmap bitmap = Bitmap.createBitmap(widthPixels, heightPixels, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);drawable.setBounds(0, 0, widthPixels, heightPixels);drawable.draw(canvas);return bitmap;}

上面的代码保存你在下载目录中drawable.png

我在这个线程上使用了一些答案,但其中一些没有按预期工作(也许他们在旧版本中工作过),但我想在几次尝试和错误后分享我的答案,使用扩展函数:

val markerOption = MarkerOptions().apply {position(LatLng(driver.lat, driver.lng))icon(R.drawabel.your_drawable.toBitmapDescriptor(context))snippet(driver.driverId.toString())}mMap.addMarker(markerOption)

这是扩展函数:

fun Int.toBitmapDescriptor(context: Context): BitmapDescriptor {val vectorDrawable = ResourcesCompat.getDrawable(context.resources, this, context.theme)val bitmap = vectorDrawable?.toBitmap(vectorDrawable.intrinsicWidth,vectorDrawable.intrinsicHeight,Bitmap.Config.ARGB_8888)return BitmapDescriptorFactory.fromBitmap(bitmap!!)}

静态编程语言中,最简单的方法是:

Drawable.toBitmap(width: Int, height: Int, config: Bitmap.Config?): Bitmap

像这样:

val bitmapResult = yourDrawable.toBitmap(1,1,null)

其中,只需要一个可绘制的变量,没有资源,没有上下文,没有id