원본출처: 티스토리 바로가기
오늘은 이미지 자르기 (cropper)에 대한 이야기를 적어 보겠습니다. 해당 라이브러리의 출처는 다음과 같습니다.
https://github.com/CanHub/Android-Image-Cropper
2021년쯤에 이 방법을 java 코드에 연결해 보았던 기억이 있으나 그때 사용 되었던 github는 이제 더 이상 관리가 되지 않고 있었고 그걸 fork 해 계속 유지하고 있는 코드를 발견하게 되었습니다.
카메라 또는 갤러리에서 가져오는 이미지는 전체가 필요할 수 도 있지만, 문자 인식 등에 활용 하기 위해서는 필요한 부분만을 가져와야 하는 경우 등이 있습니다.
이 떄 유용하게 활용될 수 있습니다.
이미지 자르기 (cropper 기능)을 활용하는 방법은 먼저 gradle 파일에 다음과 같이 기술합니다.
// image cropper implementation("com.vanniktech:android-image-cropper:4.5.0")
현재는 4.5.0 이 마지막 버전입니다. 이 글을 보시는 시점에는 다시 확인해 보시는 것이 좋을 듯합니다.
이제 코드 구현을 해 보겠습니다. 먼저 callback 을 구현합니다. 호출된 이후에 결과가 돌아오면 그걸 현재는 viewModel에 있는 변수에 저장해 볼 예정입니다.
private val customCropImage = registerForActivityResult(CropImageContract()) { if (it !is CropImage.CancelledResult) { dataViewModel.textRecognitionUri.value = it.uriContent Log.e("", "cropImage = ${it.uriContent}") } }
이 응답을 받기 위해서 아래와 같이 호출을 시도합니다.
private fun startCameraWithoutUri(includeCamera: Boolean, includeGallery: Boolean) { customCropImage.launch( CropImageContractOptions( uri = null, cropImageOptions = CropImageOptions( imageSourceIncludeCamera = includeCamera, imageSourceIncludeGallery = includeGallery, ), ), ) }
첫 번째 인수는 카메라 선택 가능 여부, 두 번째는 갤러리 선택 가능 여부입니다. 저는 두 개다 true로 실행을 했습니다.
이렇게 activity가 실행이 되게 되는 이때 꼭 해야 할 것은 다음과 같이 manifest.xml 파일에 해당 activite을 추가해 주어야 합니다.
<activity android:name="com.canhub.cropper.CropImageActivity" android:theme="@style/Base.Theme.AppCompat" />
또한 갤러리와 카메라 선택 하는 문구가 영문으로 표출되는 것이 기본 값인데, 그걸 한글로 표시 되게 하기 위해서
values / strings.xml 에 다음과 같이 추가했습니다.
<string name="ic_rotate_left_24">반시계 회전</string> <string name="ic_rotate_right_24">회전</string> <string name="crop_image_menu_crop">자르기</string> <string name="ic_flip_24">반전</string> <string name="ic_flip_24_horizontally">좌우반전</string> <string name="ic_flip_24_vertically">상하반전</string> <string name="pick_image_chooser_title">이미지 선택</string> <string name="pick_image_camera">카메라로 촬영하기</string> <string name="pick_image_gallery">저장된 이미지 읽어오기</string>
이런 문구들이 들어가므로 해서 화면에 한글로 표시가 진행됩니다.
이제 실행하고 그 결과를 보겠습니다.
당초에는 전체 촬영된 이미지가 보였으나, 안내선을 이용하여 조정한 후 화면 상단의 자르기 버튼을 선택하면 오른쪽의 그림과 같이 선택된 부분만 이미지로 전달을 받아 보여 줄 수 있었습니다.
위에서 선택된 결과를 viewModel에 있는 변수에 받았으니 그걸 그대로 Image에 넣어주는 것으로 그 코드를 정리가 되었습니다. 그 부분은 다음과 같습니다.
dataViewModel.textRecognitionUri.value?.let { val source = ImageDecoder .createSource(context.contentResolver, it) bitmapPic.value = ImageDecoder.decodeBitmap(source) bitmapPic.value?.let { btm -> val quality = 20 val baos = ByteArrayOutputStream() btm.compress( Bitmap.CompressFormat.WEBP_LOSSLESS, quality, baos ) val b: ByteArray = baos.toByteArray() productImage = Base64.encodeToString(b, Base64.DEFAULT) Image( bitmap = btm.asImageBitmap(), contentDescription = "profile", contentScale = ContentScale.FillBounds, modifier = Modifier .clip(shape = RoundedCornerShape(16.dp)) .width(screenWidth * .8f) .height(300.dp) ) } }
uri로 받아온 응답을 활용해서 이미지로 변환해 바로 보여주는 방식으로 말입니다. Quality는 20으로 조정을 하기는 했으나, 그렇게 차이가 나는 것을 느낄 수 없었습니다.
이제 이미지 자르기는 그렇게 어렵지 않게 구현을 해 볼 수 있을 것 같습니다.
댓글
댓글 쓰기