Android의 리소스들은 기본적으로 Drawable 객체로 가져옵니다. 하지만 간혹 코딩을 하다보면 Bitmap을 인자로 받는 애들이 있습니다.
예를 들어, 아래 코드에서 Notification을 생성할 때 setSmallIcon()
는 인자로 Resource ID를 받습니다. 하지만 setLargeIcon()
는 인자로 Bitmap을 받습니다.
val builder = NotificationCompat.Builder(this, channelId)
builder.setSmallIcon(R.drawable.ic_codechacha)
builder.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.castle))
...
프로젝트의 리소스들은 Drawable로만 가져올 수 있기 때문에 Bitmap으로 변경이 필요합니다. Drawable을 Bitmap으로 변경하거나 Bitmap을 Drawable로 변경하는 방법에 대해서 정리하였습니다.
이 글에서 사용하는 예제는 모두 코틀린으로 작성되었습니다.
Drawable => Bitmap 으로 변경 (1)
getDrawable()
는 인자로 전달된 리소스 ID에 대한 이미지를 Drawable로 가져옵니다.
Drawable은 BitmapDrawable으로 형변환이 가능하며 BitmapDrawable.bitmap
은 bitmap 객체를 리턴합니다.
val drawable = getDrawable(R.drawable.castle)
val bitmapDrawable = drawable as BitmapDrawable
val bitmap = bitmapDrawable.bitmap
Drawable => Bitmap 으로 변경 (2)
다른 방법으로는 BitmapFactory
를 사용하는 것입니다.
decodeResource()
는 인자로 전달된 Drawable ID에 대한 Drawable을 Bitmap 변환하여 리턴해 줍니다.
여기서 resources는 Resources 객체를 말하며 Activity에서 바로 접근할 수 있습니다.
val resources: Resources = this.resources
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.castle)
AdaptiveIconDrawable => Bitmap
Android O에서 Adaptive Icon가 소개되었습니다. 그래서 Android O 이상의 디바이스에서 앱 아이콘은 AdaptiveIconDrawable 객체일 수 있습니다. 이 경우, Bitmap으로 변경하려면 조금 처리가 필요합니다.
Adaptive Icon은 Foreground와 Background 이미지 두개가 합쳐져서 보이는 아이콘인데요. 이 때문에 Bitmap으로 변경하려면 이 두개의 이미지를 합성해야 합니다.
AdaptiveIconDrawable을 Bitmap으로 변경하는 코드는 다음과 같습니다.
val drawable = getDrawable(R.mipmap.ic_launcher)
if (drawable is AdaptiveIconDrawable) {
val backgroundDrawable = (drawable as AdaptiveIconDrawable).background // 1
val foregroundDrawable = (drawable as AdaptiveIconDrawable).foreground // 2
val drawables = arrayOfNulls<Drawable>(2)
drawables[0] = backgroundDrawable
drawables[1] = foregroundDrawable
val layerDrawable = LayerDrawable(drawables) // 3
val width = layerDrawable.intrinsicWidth
val height = layerDrawable.intrinsicHeight
val bitmap = Bitmap.createBitmap(
width, height, Bitmap.Config.ARGB_8888) // 4
val canvas = Canvas(bitmap) // 5
layerDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight())
layerDrawable.draw(canvas) // 6
}
bitmap // 7
주석 '// 1'
처럼 중요한 코드에 번호를 붙였고 아래에 설명하였습니다.
- AdaptiveIconDrawable 객체에서 background 이미지만 추출
- AdaptiveIconDrawable 객체에서 foreground 이미지만 추출
- LayerDrawable로 두개의 객체를 합성. 인자로 전달되는 배열의 가장 큰 Index가 가장 높은 layer에 그려집니다.
- 합성된 LayerDrawable의 크기만큼의 Bitmap 객체를 만듭니다.
- Canvas 객체를 만듭니다.
- Canvas를 통해 LayerDrawable의 이미지를 Bitmap 객체에 draw합니다.
- AdaptiveIcon의 모든 레이어가 합성된 Bitmap 객체입니다.
Bitmap => Drawable
간혹 웹에서 Bitmap 이미지를 받아서 디바이스에 보여줄 때 Drawable로 변경해야할 때가 있습니다. 다음 코드처럼 Bitmap 객체를 BitmapDrawable로 wrapping해주면 Drawable 객체로 변경이 됩니다. Android Developer를 보시면 BitmapDrawable은 Drawable을 상속합니다.
val resources: Resources = this.resources
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.castle)
val drawable = BitmapDrawable(resources, bitmap)
정리
Drawable을 Bitmap으로, Bitmap을 Drawable로 변환하는 방법에 대해서 알아보았습니다.
참고
Related Posts
- Android 14 - 사진/동영상 파일, 일부 접근 권한 소개
- Android - adb push, pull로 파일 복사, 다운로드
- Android 14 - 암시적 인텐트 변경사항 및 문제 해결
- Jetpack Compose - Row와 Column
- Android 13, AOSP 오픈소스 다운로드 및 빌드
- Android 13 - 세분화된 미디어 파일 권한
- Android 13에서 Notification 권한 요청, 알림 띄우기
- Android 13에서 'Access blocked: ComponentInfo' 에러 해결
- 에러 해결: android gradle plugin requires java 11 to run. you are currently using java 1.8.
- 안드로이드 - 코루틴과 Retrofit으로 비동기 통신 예제
- 안드로이드 - 코루틴으로 URL 이미지 불러오기
- Android - 진동, Vibrator, VibrationEffect 예제
- Some problems were found with the configuration of task 에러 수정
- Query method parameters should either be a type that can be converted into a database column or a List
- 우분투에서 Android 12 오픈소스 다운로드 및 빌드
- Android - ViewModel을 생성하는 방법
- Android - Transformations.map(), switchMap() 차이점
- Android - Transformations.distinctUntilChanged() 소개
- Android - TabLayout 구현 방법 (+ ViewPager2)
- Android - 휴대폰 전화번호 가져오는 방법
- Android 12 - Splash Screens 알아보기
- Android 12 - Incremental Install (Play as you Download) 소개
- Android - adb 명령어로 bugreport 로그 파일 추출
- Android - adb 명령어로 App 데이터 삭제
- Android - adb 명령어로 앱 비활성화, 활성화
- Android - adb 명령어로 특정 패키지의 PID 찾기
- Android - adb 명령어로 퍼미션 Grant 또는 Revoke
- Android - adb 명령어로 apk 설치, 삭제
- Android - adb 명령어로 특정 패키지의 프로세스 종료
- Android - adb 명령어로 screen capture 저장
- Android - adb 명령어로 System 앱 삭제, 설치
- Android - adb 명령어로 settings value 확인, 변경
- Android 12 - IntentFilter의 exported 명시적 선언
- Android - adb 명령어로 공장초기화(Factory reset)
- Android - adb logcat 명령어로 로그 출력