본문 바로가기
깡샘 코틀린

18-3 이미지 처리하기 - Glide 라이브러리

by 농농씨 2023. 7. 13.

이번 절에서는 이미지를 다루는 Glide 라이브러리를 살펴볼 것이다. 이번 장의 주제는 네트워크 프로그래밍이지만 서버에서 이미지를 내려받을 때 Glide를 이용하면 네트워크 부분을 Volley나 Retrofit보다 더 쉽고 빠르게 개발할 수 잇다.

 

Glide 는 Bump라는 앱에서 내부적으로 이용하다가 구글이 인수하여 공개한 라이브러리이다. Glide는 모든 종류의 이미지를 가능한 한 빠르게 가져와서 이용할 수 있게 한다. 또한 이미지의 크기를 조절하거나 로딩 이미지, 오류 이미지 표시 등을 쉽게 구현할 수 있다. Glide를 이용하려면 빌드 그래들의 dependencies에 다음처럼 등록해야 한다.

// Glide 등록
implementation 'com.github.bumptech.glide:glide:4.12.0'

 

이미지를 가져와 출력하기

앱에서 사용하는 이미지는 리소스, 파일, 서버 이미지이다. 이 이미지를 Glide로 쉽게 가져와 이미지 뷰에 출력할 수 있다.

다음은 리소스 이미지를 이미지 뷰에 출력하는 코드이다. 1️⃣load() 함수에 리소스를 전달하고 2️⃣into() 함수에 이미지 뷰 객체를 전달하면 리소스 이미지를 자동으로 가져와 출력한다.

// 리소스 이미지 출력
Glide.with(this)
    .load(R.drawable.seoul) // load() 함수에 리소스 전달
    .into(bindig.resultView) // into() 함수에 이미지를 출력할 이미지 뷰 객체 전달

다음은 파일 이미지를 이미지 뷰에 출력하는 코드이다. 갤러리 앱의 목록 화면을 보여주고 사용자가 사진을 선택하면 그 경로를 받아서 Glide로 이미지 뷰에 출력한다. 갤러리 앱에서 가져온 사진 파일의 경로만 load() 함수에 지정하면 파일 이미지를 읽어 화면에 출력하므로 16장에서 살펴봤던 ContentResolver를 이용하는 방법보다 훨씬 더 쉽게 파일 이미지를 가져올 수 있다.

// 파일 이미지 출력
val requestLauncher = registerForActivityResult(
    ActivityResultCntracts.StartActivityForResult())
{
    Glide.with(this)
        .load(it.data!!.data) // 갤러리 앱에서 가져온 사진 파일의 경로를 load() 함수에 지정
        .into(binding.resultView)
}
val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
intent.type = "image/*"
requestlauncher.launch(intent)

 

서버에  있는 이미지를 가져오는 코드도 같다. load() 함수에 이미지 URL을 문자열로 지정하면 자동으로 서버에서 이미지 데이터를 읽어 into() 함수에 지정한 이미지 뷰에 출력한다.

// 서버 이미지 출력
Glide.with(this)
    .load(url) // load() 함수에 이미지 url 지정
    .into(binding.resultView) // 이미지를 출력할 이미지 뷰 지정

때로는 PNG나 JPG가 아니라 애니메이션 효과를 포함한 GIF 이미지를 출력할 때도 있다. 이때 이미지 뷰는 GIF 이미지를 출력할 수는 있지만 애니메이션 효과가 적용되지는 않는다. 하지만 Glide를 이용하면 특별히 처리하지 않아도 이미지 뷰에 애니메이션 효과가 그대로 출력되는 GIF 이미지를 출력할 수 있다.

 

 

크기 조절

파일 이미지나 서버에 있는 이미지는 크기가 커서 OOM(out of memory)가 발생할 수 있다. 따라서 16장에서 살펴본 것처럼 BitmapFactory.Option 으로 이미지 크기를 줄여서 출력해야 한다. 그런데 Glide를 이용하면 코드에서 이미지 크기를 줄이지 않아도 이미지 뷰의 크기에 맞게 자동으로 줄여서 불러온다. 그래서 OOM 문제를 크게 신경쓰지 않아도 된다.

만약 특정한 크기로 이미지를 줄이고 싶다면 다음처럼 override() 함수를 이용하면 된다.

// 크기 조절
Glide.with(this)
    .load(R.drawable.seoul)
    .override(200, 200) // 자동으로도 줄여지지만 특정 크기로 이미지 출력
    .into(binding.resultView)

 

 

로딩, 오류 이미지 출력

파일이나 서버에 있는 이미지를 이용할 때는 이미지를 불러오는 데 시간이 오래 걸릴 수 있다. 보통 이럴 때는 로딩 상태를 표현하는 이미지를 먼저 출력했다가 완료되었을 때 본래 이미지를 출력한다. 또한 서버에 접속이 원활하지 않아서 이미지를 불러올 수 없다면 오류 이미지를 출력한다.

이러한 기능을 구현하려면 placeholder(), error() 함수를 사용해 해당 상황에 표시할 이미지를 지정하면 된다.

// 로딩, 오류 이미지 출력
Glide.with(this)
    .load(url) // 서버에 있는 이미지 가져오기 위해 load() 함수에 이미지 url 전달
    .override(200, 200) // 이미지를 특정 크기로 줄이기
    .placeholder(R.drawable.loading) // 로딩 상태일 때 이미지
    .error(R.drawable.error) // 오류 상태일 때 이미지
    .into(binding.resultView) // 이미지를 출력할 이미지 뷰 객체를 into() 함수에 전달

placeholder() 함수에 지정한 이미지를 먼저 출력하며 load() 함수에 지정한 이미지를 불러오면 그 이미지를 출력한다. 그리고 이미지를 불러오는 데 실패하면 error() 함수에 지정한 이미지를 출력한다.

 

 

이미지 데이터 사용하기

앞의 예에서는 불러온 이미지를 이미지 뷰에 출력했는데 때로는 이미지 데이터를 직접 사용해야 할 수도 있다. 이때에는 into() 함수에 CustomTarget 객체를 지정해주면 된다.

// 이미지 데이터 사용하기
Glide.with(this)
    .load(url) // load() 함수에 이미지 url 을 문자열로 지정하여 서버에서 이미지 데이터 읽도록 하기
    .into(object : CustomTarget<Drawable>() {
    // 이미지 데이터를 직접 사용하기 위해 into() 함수에 
    // 이미지 뷰 객체가 아닌 이미지 데이터를 받을 CustomTarget 객체를 지정함
        override fun onResourceReady(
        // CustomTarget을 상속받은 객체의 함수를 재정의
        // onResourceReady()는 load() 함수에 명시한 이미지를 불러왔을 때 자동으로 호출됨
        // 이 함수의 매개변수로 이미지 데이터를 Drawable 타입으로 전달함
            resource: Drawable, // 불러온 이미지 데이터
            transition: Transition<in Drawable>?
        ) {
            TODO("Not yet implemented")
        }
        override fun onLoadCleared(placeholder: Drawable?) {
            TODO("Not yet implemented")
        }
    })

into() 함수에 이미지 뷰 객체가 아니라 이미지 데이터를 받을 객체를 지정했다. 이 객체는 CustomTarget을 상속받아 onResourceReady()와 onLoadCleared() 함수를 재정의해야 한다. 그러면 load() 함수에 명시한 이미지를 불러왔을 때 onResourceReady() 함수가 자동으로 호출되며, 이 함수의 매개변수로 이미지 데이터를 Drawable 타입으로 전달해 준다.

 

만약 이미지를 Bitmap 타입으로 받아야 한다면 다음처럼 asBitmap() 함수를 추가하고 CustomTarget의 제네릭에 <Bitmap>을 선언하면 된다.

// 람다 함수 선언
Glide.With(this)
    .asBitmap() // 이미지를 비트맵 타비으로 받기 위해 함수 추가
    .load(url)
    .into(object : CustomTarget<Bitmap>() {
    // CustomTarget의 제네릭에 <Bitmap> 선언
        override fun onResourceReady(
            resource: Bitmap,
            transition: Transition<in Bitmap>?
        ) {
            TODO("Not yet implemented")
        }
        override fun onLoadCleared(placeholder: Drawable?) {
            TODO("Not yet implemented")
        }
    })

'깡샘 코틀린' 카테고리의 다른 글

19-2 구글 지도 활용하기  (0) 2023.07.13
19-1 사용자 위치 얻기  (0) 2023.07.13
18-2 HTTP 통신하기  (0) 2023.07.13
18-1 스마트폰 정보 구하기  (0) 2023.07.12
17-3 공유된 프리퍼런스에 보관하기  (0) 2023.07.12