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

다른 사람과는 달리, 당신이 호출하면 setBoundsDrawable비트 맵으로 바꿀 것을 요청하기 전에, 그것은 올바른 크기의 비트 맵을 그릴 것입니다!


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.