안드로이드 코틀린 : 사진의 Exif 데이터 읽기, 쓰기 - ExifInterface
Lucy Archive
Lucy 2023
2021. 4. 8. 14:20

Android Kotlin : Exif 데이터 읽기, 쓰기 - ExifInterface

Exif는 디지털 카메라 등에 사용되는 이미지 메타데이터 포멧입니다. 이 포스트는 안드로이드 프로그래밍에서

이미지 파일의 Exif 데이터를 읽고 쓰는 방법

에 대해 정리하였습니다. 

 

Exif란?

Exif(Exchangeable Image File Format)은 디지털 카메라 등에서 이용되는 이미지 파일 메타데이터 포멧이다. 메타데이터란 다른 데이터를 설명해주는 데이터라고 말할 수 있다. 즉, Exif 데이터는 이미지데이터(좌표와 색데이터)를 제외한 이미지를 설명해주는 날짜와 시간 정보, 사진의 방향, 위치 정보, 카메라 조리게 등의 부가적인 데이터를 말한다. 이런 다양한 데이터가 Exif란 형태 구조화되어 JPEG와 같은 이미지 파일에 함께 저장된다.

아래와 왼쪽 그림과 같이 스마트폰 겔러리에서 위치별로 찍은 사진을 정리해주는 기능들은 사진파일에 저장된 Exif 데이터의 위치정보를 사용한다. 우측 그림은 위도우에서 jpg 파일의 속성에서 자세히 탭을 선택하여 Exif 데이터를 보여주는 그림이다. 다양한 데이터가 포함 되었음을 알 수 있다. 

메타데이터 사용 예시 및 윈도우에서 Exif 데이터 보는 방법

사진에서 Exif 데이터 보기

안드로이드에서 Exif 데이터를 보기 위해 ExifInterface를 사용한다. 링크에서 보는 것과 같이 다양한 종류의 데이터 종류가 존재한다. 

지원 파일 형태

ExifInterface 는 아래의 파일 형태를 지원한다.

  • 읽기 : JPEG, PNG, WebP, HEIF, DNG, CR2 등 다수
  • 쓰기 : JPEG, PNG, WebP

 

Exif 데이터 불러오기

예시 코드

아래 코드는 Exif 데이터를 불러오는 예시 코드이다. 3번째 줄의 photo는 사진 파일(File) 객체이다. 아래와 같이 파일 클래스로 선언 되있다. 

  • val photo = File(photofilepath)
var exif : ExifInterface? = null
try{
    exif = ExifInterface(photo.absolutePath)
}catch (e : IOException){
    e.printStackTrace()
}

val filename = photo.name
val manufacturer = exif?.getAttribute(ExifInterface.TAG_MAKE)
val cameraModel = exif?.getAttribute(ExifInterface.TAG_MODEL)
val orientation = when (exif?.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0)) {
        ExifInterface.ORIENTATION_ROTATE_90 -> 90
        ExifInterface.ORIENTATION_ROTATE_180 -> 180
        ExifInterface.ORIENTATION_ROTATE_270 -> 270
        else -> 0
    }

val dateTime = exif?.getAttribute(ExifInterface.TAG_DATETIME)
val length = exif?.getAttribute(ExifInterface.TAG_IMAGE_LENGTH)
val width = exif?.getAttribute(ExifInterface.TAG_IMAGE_WIDTH)

Log.d("ExifData", "File Name : $filename")
Log.d("ExifData", "model : $manufacturer")
Log.d("ExifData", "model2 : $cameraModel")
Log.d("ExifData", "Orientation : $orientation")
Log.d("ExifData", "dateTime : $dateTime")
Log.d("ExifData", "Resolution(x*y) : $width x $length")

※ ExifInterface Import시 androidx.exifinterface.media.ExifInterface 를 참조하길 추천한다. 그렇지 않은 경우 아래의 클래스 선언자 종류에 따라 지원되는 API LEVEL이 다르다. 

ExifInterface 클래스 선언자

ExifInteface 클래스 인스턴스 생성시 매개변수의 아래의 5가지 타입이 올 수 있다. 위 코드에서는 2번째 filename을 사용했다. 파일 경로를 사용하는 방법은 API 5이상 호환된다. 

  • ExifInterface(File file)
  • ExifInterface(String filename)
  • ExifInterface(FileDesscriptor)
  • ExifInterface(InputStream inputStream)
  • ExifInterface(InputStream inputStream, int streamType)

Exif 데이터 불러오기 : getAttribute()

Exif 데이터를 불러오기 위해 getAttribute() 메서드를 사용한다. 불러올 TAG 에 따라 또는 반환 받고 싶은 데이터 형태에 따라 아래의 메서드 사용이 가능하다. 매개변수로 사용되는 TAG 리스트는(Exif 데이터 리스트) 위에서 링크한 안드로이드 ExifInterface 공식 문서에서 확인 가능하다. 

  • getAttribute(String tag) : String 을 반환
  • getAttributeBytes(String tag) : byte[] 를 반환
  • getAttributeDouble(String tag, Double defaultValue) : Double 을 반환
  • getAttributeInt(String tag, int defaultValue) : int 를 반환
  • getAttributeRange(String tag) : Long[] 을 반환

실행 결과

위 코드를 실행 예시 결과로, 안드로이드 스튜디오 Debug 출력에서 아래와 같은 결과를 볼 수 있다. 

코드 실행 결과

 

Exif 데이터 쓰기

Exif 데이터 쓰기는 JPEG, PNG, WebP 형태의 이미지 파일 형태만 가능하다. 데이터를 쓰기 위해 setAttribute() 메서드를 사용한다. 코드 예시는 아래와 같다. 이 코드에서 본 사진의 Orientation은 90이었는데, 아래의 코드에서 0으로 수정 후, 다시 Oritentation 정보를 읽어 디버그 메세지로 전송한다.  

  • setAttribute(String tag, String value)
var exif : ExifInterface? = null

try{
    exif = ExifInterface(photo)
}catch (e : IOException){
    e.printStackTrace()
}

exif?.setAttribute(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED.toString())

val orientation = when (exif?.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0)) {
        ExifInterface.ORIENTATION_ROTATE_90 -> 90
        ExifInterface.ORIENTATION_ROTATE_180 -> 180
        ExifInterface.ORIENTATION_ROTATE_270 -> 270
        else -> 0
    }
    
Log.d("ExifData", "Orientation : $orientation")

위 코드를 실행하면 위의 결과와 다르게 Orientation 값이 0으로 나오는 것 을 확인 할 수 있다.

코드 실행 결과

끝까지 읽어 주셔서 감사합니다.^^

관련포스트

🤞 안드로이드(코틀린) 앱 제작하기 관련글 목록 보기

🤞 안드로이드(코틀린) 이미지파일 관련글 목록 보기