정상에서 IT를 외치다

[Android, bitmap] 비트맵에 대한 탐구_이미지 자르기 본문

안드로이드

[Android, bitmap] 비트맵에 대한 탐구_이미지 자르기

Black-Jin 2018. 9. 6. 14:45
반응형


안녕하세요. 블랙진입니다.

이번 시간에는 비트맵 사용법에 대해 공부해볼려고 합니다.


사용한 이미지 url : https://i.ytimg.com/vi/WCXM4DnwT1g/maxresdefault.jpg


위 링크는 1280 x 720 크기의 black panther 이미지 입니다. 

테스트로 사용한 기기는 SM-G920K 로 해상도는 1440 x 2560 입니다. 

dpi 는 640 이며 1 dp = dpi / 160 * px 의 관계이므로 1dp = 4px 입니다.

// device 높이와 넓이
val deviceWidth = resources.displayMetrics.widthPixels
val deviceHeight = resources.displayMetrics.heightPixels

// dpi 구하기
val density = resources.displayMetrics.densityDpi

이미지를 다운 받아 black_panther 로 저장하여 drawable 에 넣어 주었습니다.

시작하기에 앞서 3가지 비트맵 사이즈에 대해 끄적여 보겠습니다.



1. drawable 을 비트맵으로 바꿀 때 크기 변환

// black_panther 이미지를 비트맵으로 변환 합니다.
val originalBitmap = BitmapFactory.decodeResource(resources, R.drawable.black_panther)

// 원본 비트맵 이미지 넓이와 높이
val bitmapWidth = originalBitmap.width
val bitmapHeight = originalBitmap.height
Log.d("MyTag", "bitmapWidth : $bitmapWidth , bitmapHeight : $bitmapHeight")

이 때 비트맵을 drawable 어느 폴더에 넣느냐에 따라 이미지 사이즈가 바뀝니다.


drawable -> bitmapWidth : 5120 , bitmapHeight : 2880


drawable-xhdpi -> bitmapWidth : 2560 , bitmapHeight : 1440


drawable-xxhdpi -> bitmapWidth ; 1707 , bitmapHeight : 960


drawable-xxxhdp -> bitmapWidth ; 1280 , bitmapHeight : 720




2. 원본 이미지 크기 가져오기

// 원본 이미지 크기 가져오기
val options = BitmapFactory.Options()

// true 설정을 해주면 이미지를 decoding 할 때 이미지의 크기만을 먼저 불러옵니다.
options.inJustDecodeBounds = true

// options 에 원본이미지를 디코드 시킵니다.
BitmapFactory.decodeResource(resources, R.drawable.black_panther, options)

// 넓이와 높이, 이미지 타입을 반환합니다.
val imageWidth = options.outWidth
val imageHeight = options.outHeight
val imageType = options.outMimeType
Log.e("MyTag", " imageWidth : $imageWidth , imageHeight ; $imageHeight , imageType : $imageType")

BitmapFactory.Options 를 사용하여 원본 이미지의 크기를 가져올 수 있습니다.


 imageWidth : 1280 , imageHeight ; 720 , imageType : image/jpeg





3. 샘플링을 통해 원본 이미지의 사이즈를 줄여보기

val options = BitmapFactory.Options()

val inSampleSize = 4
options.inSampleSize = inSampleSize

val result = BitmapFactory.decodeResource(resources, R.drawable.black_panther, options)

Log.d("MyTag", "result resultWidth ; ${result.width} , resultHeight : ${result.height}")

BitmapFactory.Options 에서 inSampleSize 를 변경할 수 있습니다.


의미는 inSampleSize 를 1픽셀로 설정합니다. 위 예제 에서는 4 픽셀을 1픽셀로 바꾼다는 의미로 이미지의 크기가 1/4 이 됩니다.


1번 에서의 크기에 1/4 이되었음을 확인 할 수 있습니다.






비트맵 이미지 자르기



drawable 을 dpi 별로 이미지를 넣어주지 않으면 디바이스 해상도 별로 사이즈가 다르게 나옵니다. ㅜㅠ

하여 디바이스 화면을 기준으로 비트맵을 리사이징 하고 크롭해보도록 하겠습니다.


위 예제 이미지는 가로가 긴 이미지 입니다. 가로 크기를 기준으로 세로 크기를 변경해 주었습니다.

// device 높이와 넓이
val deviceWidth = resources.displayMetrics.widthPixels
val deviceHeight = resources.displayMetrics.heightPixels
Log.d("MyTag", "deviceWidth ; $deviceWidth , deviceHeight : $deviceHeight")

// black_panther 이미지를 비트맵으로 변환 합니다.
val originalBitmap = BitmapFactory.decodeResource(resources, R.drawable.black_panther)

// 원본 비트맵 이미지 넓이와 높이
val bitmapWidth = originalBitmap.width
val bitmapHeight = originalBitmap.height
Log.d("MyTag", "bitmapWidth ; $bitmapWidth , bitmapHeight : $bitmapHeight")

// 디바이스 가로 비율에 맞춘 세로 크기
val scaleHeight = deviceWidth * bitmapHeight / bitmapWidth

// 비트 맵의 가로 세로 비율 조정
val resizeBp = Bitmap.createScaledBitmap(originalBitmap, deviceWidth, scaleHeight, true)
Log.d("MyTag","resizeWidth : $deviceWidth , resizeHeight : $scaleHeight")


디바이스 크기 1440 x 2560 입니다.


위 이미지는 기존의  1280 x 720  에서  1440 X 810 인 형태가 되었습니다. 위 이미지에서 블랙팬서의 얼굴부분을 잘라보고 싶은데요. 디바이스를 보고 좌표를 예측할 수 있으신가요?


이미지의 왼쪽 위 모서리를 (0,0) 이며 오른쪽 아래 모서리는 (1440, 810) 입니다. 어림잡아...

(800, 200) 정도 되지 않을까요?? 한번 크롭해보겠습니다!

// 비트맵 자르기
val cropBitmap
= Bitmap.createBitmap(resizeBp
, 800 // X 시작위치
, 200 // Y 시작위치
, 400 // 크롭한 이미지의 가로
, 400 // 크롭한 이미지의 세로
)

비트맵은 (800, 200) 지점에서 크기 400 x 400 박스로 크롭하는 코드입니다.




약간 애매한 위치가 되었지만 어림잡아서 잘 맞췄습니다 .ㅋㅋㅋ


반응형
Comments