오늘도 삽질중

호기심으로 찾아본 카카오톡 채팅이미지 사이즈 변환규칙 본문

안드로이드

호기심으로 찾아본 카카오톡 채팅이미지 사이즈 변환규칙

Choi3950 2021. 8. 7. 18:05
반응형

firebase DB를 사용해서 앱 내 채팅을 구현하는 작업을 했습니다.

너무나 당연하듯이 채팅은 단순 텍스트와 이모티콘 및 사진과 같은 이미지도 주고받을 수 있습니다.

 

문득 리스트에 사진과 같은 이미지를 보여주는 과정에서 동적으로 뷰가 변경이 되는걸 어떻게 구현해야 될까?

고민하다가 누구나 사용하는 카카오톡은 어떻게 이루어 졌는지 궁금해서 여러 방면으로 테스트를 해보고 저만의 규칙?을 정의해서 작업을 마무리 했습니다.

 

 

참고로 저는 카카오 개발자가 아닙니다. 기능 구현을 위한 일종의 탐험? 이라고 생각해주시고

해당 내용은 제가 정한 가설이므로 재미로 봐주시면 좋겠습니다!

 

 

 

자 우리가 자주 쓰는 카카오톡에 사진과 같은 이미지를 넣으면 아래와 같은 모습이 됩니다.

이미지의 사이즈가 각각 다르죠

 

 

해당 이미지의 사이즈를 직접 확인해보겠습니다.

(해상도와 사이즈를 비교해보세요)

앨범에서 이미지 정보 카카오톡 앱에서 이미지정보


 

 

이미지의 사이즈도 줄어들고 무엇보다 해상도가

960이라는 기준으로 맞춰지게 됩니다.

 

즉 가로와 세로 중에서 긴 쪽의 해상도를 960으로 맞추고

나머지는 720에 맞추는 것으로 추측을 해볼 수 있습니다.

그렇다면 해상도가 960보다 작으면 어떻게 될까요?

 

 

이걸 기반으로 제가 사진 몇 장을 좀 더 테스트해보니 아래 표와 같이 결과가 나왔습니다.

앨범에서 체크한 해상도 (사이즈)  사진이 회전되었을 경우 실제 해상도 카카오톡에서 체크한 해상도 (사이즈)
9248 x 6936 (12.28MB) 6936 x 9248 720 x 960 (148KB)
1032 x 822 (158.41MB) 회전 되지 않음 960 x 765 (92KB) 
420 x 236 (21.78KB) 회전 되지 않음 420 x 236 (22KB)
1920 x 2560 (3.43MB) 회전 되지 않음 720 x 960 (206KB)
4608 x 2592 (9.5MB) 회전 되지 않음 960 x 540 (186KB)

 

표에서 사진이 회전되었을 경우 실제 해상도는

해당 이미지의 회전 정보가 있는 것을 확인하여 정상적인 방향으로 잡은 후에 실제 해상도를 가져왔습니다.

여담으로 안드로이드 개발을 하시는 분들은 모두 아시겠지만 사진을 뷰에 올릴 시 회전되는 이슈가 있기 때문에

우리는 모두 회전된 값을 가져와서 정상적인 방향으로 돌려서 보여줍니다.

 

 

해당 표를 보고 나온 저의 결론은

1. 가로 또는 세로가 960보다 작을 경우에는 원본 해상도를 그대로 보여준다.

2. 가로 또는 세로가 960보다 클 경우 큰 쪽을 960으로 맞추고 나머지는 비율에 따라 리사이즈 한다.

ex) 4608 x 2592를 예를 들면 4608 / 960 = 4.8 이 나옵니다.

4.8을 2592와 나눕니다.

2592 / 4.8 = 540

그래서 해상도는 960 x 540

 

제가 처음에 얘기한 것처럼 해당 내용은 저만의 가설이고 정답이 아닙니다!

제가 직접 테스트하며 비교해 봤을 때 저는 위 2가지의 공식을 얻을 수 있었습니다.

참고로 해당 사이즈는 카카오톡 설정에서 사진 화질 설정이 저용량으로 돼있을 경우에만 해당됩니다!!

 

해당 설정을 일반 화질 또는 원본으로 바꿨을 경우 값은 완전히 다르게 나왔습니다.

 

 

해당 규칙을 정의한 뒤 개발 작업을 진행했습니다.

채팅에서 이미지뷰의 동적 계산을 위해 아래와 같은 함수를 만들어서 작업해봤습니다.

우선 이미지의 회전값을 체크하여 정상적인 사이즈를 설정한 뒤

이미지의 Width 가 휴대폰 디바이스의 Width 보다 작다면 그대로 사이즈를 반환하고

그렇지 않을 경우에는 해당 공식을 이용해서 사이즈를 계산합니다.

 

 

 

//채팅에서 이미지 전송시 이미지의 해상도를 체크하여 일정한 사이즈를 계산한다.
//return array width , height , degree , ratio
fun getImageReSizeInfo(context: Context?, uri: Uri): Array<Int> {
context?.let {
val deviceWidth = DisplayUtil.LazyHolder.instance.getScreenWidth(it)

if (deviceWidth == 0) return arrayOf(-1, -1, -1, -1)

val standardWidth = (deviceWidth / 3) * 2

val inputStreamRotate = it.contentResolver?.openInputStream(uri)
val fileDescriptor = it.contentResolver.openFileDescriptor(uri, "r")

val bitmapOption = BitmapFactory.Options()
bitmapOption.inJustDecodeBounds = true
BitmapFactory.decodeFileDescriptor(fileDescriptor?.fileDescriptor, null, bitmapOption)

var originalImageWidth = bitmapOption.outWidth
var originalImageHeight = bitmapOption.outHeight

bitmapOption.inJustDecodeBounds = false

val exif = inputStreamRotate?.let { ExifInterface(it) }
var exifDegree = 0
val exifOrientation = exif?.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
?: 0

when (exifOrientation) {
ExifInterface.ORIENTATION_ROTATE_90 -> exifDegree = 90
ExifInterface.ORIENTATION_ROTATE_180 -> exifDegree = 180
ExifInterface.ORIENTATION_ROTATE_270 -> exifDegree = 270
}
inputStreamRotate?.close()

when (exifDegree) {
90, 270 -> {
//이미지 가로세로가 반대로 회전되었으므로 값을 서로 교체
val changeWidth = originalImageWidth
val changeHeight = originalImageHeight

originalImageWidth = changeHeight
originalImageHeight = changeWidth

}
}

var resizeRatio = 0f
var reSizeImageWidth = 0f
var reSizeImageHeight = 0f

//이미지 사이즈가 디바이스 기준사이즈보다 작을 경우 이미지사이즈 반환
if (originalImageWidth < standardWidth) {
return arrayOf(originalImageWidth, originalImageHeight, exifDegree, resizeRatio.toInt())
} else {


when {
originalImageWidth > originalImageHeight -> {
//가로가 더 큰경우
resizeRatio = originalImageWidth / 960.toFloat()
reSizeImageWidth = 960f
reSizeImageHeight = originalImageHeight / resizeRatio

}
originalImageWidth < originalImageHeight -> {
//세로가 더 큰경우
resizeRatio = originalImageHeight / 960.toFloat()
reSizeImageWidth = originalImageWidth / resizeRatio
reSizeImageHeight = 960f

}
else -> {
//가로 세로가 똑같은 경우 해상도 960으로 고정
reSizeImageWidth = 960f
reSizeImageHeight = 960f

}
}

return arrayOf(reSizeImageWidth.toInt(), reSizeImageHeight.toInt(), exifDegree, resizeRatio.toInt())

}


} ?: return arrayOf(-1, -1, -1, -1)

}

 

 

 

 

 

반응형
Comments