Drawable을 비트 맵으로 변환하는 방법?


947

특정 Drawable장치를 바탕 화면으로 설정하고 싶지만 모든 바탕 화면 기능은 Bitmaps 만 허용 합니다. WallpaperManager2.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 값이 있다고 생각합니다. 편집 된 답변이 도움이 될 것입니다.
— Praveen

str_url은 어디에서 왔습니까? 문자열과 관련된 Drawable 함수를 찾을 수 없습니다. 도와 주셔서 감사합니다.
— Rob

12
뭔가를 찾았다 고 생각합니다. "draw"가 드로어 블이면 비트 맵으로 변환하고 싶습니다. Bitmap bitmap = ((BitmapDrawable) draw) .getBitmap (); 트릭을 수행합니다!
— Rob

1
@Rob : Drawable이 BitmapDrawable 인 경우. (실제로 Drawable은 비트 맵을 감싸는 래퍼
— 일뿐입니다

2
참고 :이 JPG의와 대규모 java.lang.OutOfMemoryError와 원인
— 어딘가의 누군가가

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
— Matt Wolfe

1
한 가지 수정 사항 : docs는 BitmapDrawable.getBitmap ()에 대해 null로 돌아올 수 있다고 말합니다. 나는 또한 이미 재활용 된 상태로 돌아올 수 있다고 말합니다.
— kellogs

16
조심 : getIntrinsicWidth()및 getIntrinsicHieght()반환 -1 당김이 단색 인 경우.
— SD

5
그래서 ... ColorDrawable에 대한 또 다른 점검이며 우리에게는 승자가 있습니다. 진지하게, 누군가 이것을 이것을 정답으로 만듭니다.
— kaay

2
신고 된 답변과 달리 질문에 답변합니다.
— njzk2

214

BitmapDrawable을 비트 맵으로 변환합니다.

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

9
이것이 가장 좋은 방법입니까? 드로어 블은 다른 유형 일 수 있으며 런타임 예외가 발생합니까? 예를 들어 ninePatchDrawble ...?
— Dori

4
@Dori는 코드를 조건문에 넣어서 실제로 BitmapDrawable캐스팅하기 전에 확인할 수 있습니다. if (d instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable)d).getBitmap(); }
— Tony Chan

367
64 개의 공감대를 믿을 수 없습니까? 이 코드 는d 이미 이미 있는 경우에만 작동합니다 .이 경우 비트 맵으로 검색하는 것이 쉽지 않습니다 ... 다른 모든 경우 와 충돌 합니다. BitmapDrawableClassCastException
— Matthias

3
@Matthias는 말할 것도 없습니다 .. 같은 질문의 저자 자체가 100 표를
— 받았습니다

2
이것은 사소한 경우에 매우 전문적입니다.
— njzk2

141

에 a Drawable를 그릴 수 있고 Canvasa 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;
}

드로어 블 매개 변수가 null 인 경우 어떻게됩니까?
— hrules6872

1
이 방법은 VectorDrawable을 지원하지 않습니다
— Mahmoud


비어 있지 않은 Drawable이 있다고 가정하면 너비와 높이가 0이 아닌지 확인 해야하는 이유는 무엇입니까? 또한 크기가 같은 setBounds ()를 사용해야하는 이유는 무엇입니까?
— Yoav Feuerstein

Good solution! Android 8.0 / sdk 26 ApplicationInfo.loadIcon (PackageManager pm)은 AdaptiveIconDrawable을 반환합니다. 코드를 사용하면 AdaptiveIconDrawable을 비트 맵으로 캐스팅하는 데 도움이됩니다.
— burulangtu

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 인 경우에만 작동하며 VectorDrawable을 사용하는 경우 CCE를 갖게됩니다.
— Brill Pappin

이들 중 어느 것도 VectorDrawable 리소스 와 함께 작동하지 않습니다 . 다음과 같은 오류가 발생합니다 -android.graphics.drawable.VectorDrawable cannot be cast to android.graphics.drawable.BitmapDrawable
— 아담 Hurwitz가에게

이 솔루션 은 Kotlin과 잘 작동합니다.
— Adam Hurwitz 2016 년


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비트 맵으로 바꿀 것을 요청하기 전에, 그것은 올바른 크기의 비트 맵을 그릴 것입니다!


setBounds가 drawable의 이전 경계를 망치지 않습니까? 저장하고 나중에 복원하는 것이 좋지 않습니까?
— 안드로이드 개발자

@androiddeveloper, 범위가 설정되면 어쨌든 사용하고 있습니다. 경우에 따라 경계가 설정되지 않고 고유 한 크기가없는 경우 (예 : ColorDrawables)에 필요합니다. 너비와 높이는 0이됩니다. 실제로 무언가를 그리는 방식으로 드로어 블 1x1을줍니다. 이 경우 ColorDrawable에 대한 유형 검사를 수행 할 수 있다고 주장 할 수 있지만 99 %의 경우 작동합니다. (필요에 따라 수정할 수 있습니다).
— Chris.Jenkins

@ Chris.Jenkins 경계가 없으면 어떻게됩니까? 또한 다른 질문을하고 싶습니다 : 반환되는 비트 맵 크기를 설정하는 가장 좋은 방법은 무엇입니까 (BitmapDrawable의 경우에도)?
— 안드로이드 개발자

코드를주의 깊게 읽으십시오. 에 Drawable경계가 설정되어 있지 않으면를 사용합니다 IntrinsicWidth/Height. 둘 다 <= 0이면 캔버스를 1px로 설정합니다. Drawable범위가 없으면 일부가 전달되지만 (1x1이 대부분의 경우) 정확 하지만 ColorDrawable고유 크기가 없는 것과 같은 경우에는 필수입니다 . 이 작업을 수행하지 않으면을 throw 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);

Rob의 답변과 마찬가지로 특정 유형 Drawable의이 경우에는 a 가 필요 합니다 PictureDrawable.
— kabuko

4
"어쩌면 이것이 누군가를 도울 것입니다 ..."
— Mauro

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

Drawable 비트를 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);

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

Android는 간단하지 않은 솔루션을 제공합니다 BitmapDrawable. 비트 맵을 얻으려면 R.drawable.flower_pica에 리소스 ID 를 제공 BitmapDrawable한 다음 a 로 캐스팅해야합니다 Bitmap.

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

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

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 라이브러리는 비트 맵을 드로어 블 또는 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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.