RuntimeException : try to draw too large ( 바이트 수 ) Bitmap
위 명시되어 있는 Exception은 메모리 캐싱 등의 부가 기능을 제공해 주는 이미지 라이브러리 없이 직접 메모리 용량이 큰 이미지를 View에 로딩 했을 때, 나타나는 문제입니다.
우리가 사용할 수 있는 application의 메모리는 제한되어 있기 때문에 Bitmap Resize를 적용해주는 것이 좋습니다.
Bitmap 크기 가져오기
BitmapFactory class는 Bitmap을 생성하기 위해 여러 가지 Decode Method를 제공합니다.
decodeByteArray(), decodeFile(),decodeResource(), etc
위 함수를 사용하게 되면 Bitmap의 고유의 크기를 메모리에 할당하게 되면서 Error를 발생시킬 수 있습니다.
때문에 BitmapFactory.Options 사용해야 합니다.
val options = BitmapFactory.Options().apply {
inJustDecodeBounds = true
}
BitmapFactory.decodeResource(resources, R.id.myimage, options)
val imageHeight: Int = options.outHeight
val imageWidth: Int = options.outWidth
val imageType: String = options.outMimeType
BitmapFactory.Options의 속성 중 inJustDecodeBounds에 true를 준 다음, decode Method를 호출하면 Method 반환값인 Bitmap은 null을 반환하지만, options 변수에 해당 Bitmap의 가로 세로 크기와 Type이 저장됩니다.
적용하고자 하는 Image의 크기만 먼저 가져와 application UI에 알맞은 크기를 계산한 뒤 다시 decode를 하는 것입니다.
저해상도 이미지
적용하고자 하는 이미지의 크기를 알아왔으니, application UI 크기에 맞게 크기를 줄이면 됩니다.
fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
// Raw height and width of image
val (height: Int, width: Int) = options.run { outHeight to outWidth }
var inSampleSize = 1
if (height > reqHeight || width > reqWidth) {
val halfHeight: Int = height / 2
val halfWidth: Int = width / 2
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
inSampleSize *= 2
}
}
return inSampleSize
}
BitmapFactory.Options의 속성 중 inSampleSize 속성 값을 구하는 함수입니다. 원하는 가로 , 세로 크기가 함수 인자 reqWidth , reqHeight에 들어오고 미리 구한 Bitmap의 크기가 options.run { outHeight to outWidth }에 있습니다.
미리 로드한 Bitmap의 크기가 reqWidth, reqHeight 보다 작을 때까지 알맞은 SampleSize의 값을 구하고 반환하는 함수입니다.
fun decodeSampledBitmapFromResource(
res: Resources,
resId: Int,
reqWidth: Int,
reqHeight: Int
): Bitmap {
// First decode with inJustDecodeBounds=true to check dimensions
return BitmapFactory.Options().run {
inJustDecodeBounds = true
BitmapFactory.decodeResource(res, resId, this)
// Calculate inSampleSize
inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight)
// Decode bitmap with inSampleSize set
inJustDecodeBounds = false
BitmapFactory.decodeResource(res, resId, this)
}
}
반환된 inSampleSize 값으로 이제 UI에 알맞은 Size인 Bitmap를 실제로 로딩하기 위해, inJustDecodeBounds = false 설정해준 뒤
Decode 합니다.
imageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100))
참고
https://developer.android.com/topic/performance/graphics/load-bitmap#java
'Android > Error' 카테고리의 다른 글
[Android] contact picker doesn't work on Android 11 (2) | 2023.03.16 |
---|---|
[Android] Snackbar에서 발생하는 ScrollView can host only one direct child (0) | 2023.03.02 |
[Android] Kotlin runBlockingTest 오류 (0) | 2021.05.27 |
[Android] Dagger2 적용 후 guava Compile Error (3) | 2020.12.04 |