Exif 란?

Exif(Exchangeable Image File format)는 스캐너, 스마트폰, 디지털 카메라 등에서 기록된 이미지(또는 오디오) 파일을 다룰 때 태그를 보조적으로 사용하는 표준 포맷이다.

위 이미지에 나타나는 ‘출처‘, ‘규격‘, ‘기기 제조사‘, ‘위도‘, ‘경도‘ 등이 일반적으로 Exif형식의 내용이며, 이 메타데이터들은 이미지 파일 자체에 내장되어 있다.

ExifInterface

안드로이드에서 ExifInterface는 다양한 이미지 파일 형식의 Exif 태그를 읽고 쓰는 클래스이다.

안드로이드에서는 Android SDK에 포함된 ExifInterface를 활용하여 Exif 데이터를 다룰 수 있지만 구버전 안드로이드 기기들과 문제가 있을 수 있다. 그렇기 때문에 공식문서에서는 AndroidX ExifInterface 라이브러리를 사용을 권고하고 있다.

// build.gradle 에 AndroidX ExifInterface 라이브러리 추가하기
dependencies {
    implementation "androidx.exifinterface:exifinterface:1.3.3"
}

ExifInterface 객체 생성

위 이미지처럼 총 다섯개의 생성자를 제공한다.

아마도 가장 자주 사용하게 되는 생성자가 파일(또는 파일경로)을 인자로 갖는 생성자다. 하지만 Android Q 이후로 Scoped Storage 정책이 적용되면서 File 대신 Uri로 Exif 데이터에 접근해야 하는 경우가 있다. 이런경우 InputStream을 인자로 갖는 생성자를 선택하면 된다. 다음 예제 코드를 확인하자.

val inputStream = context.contentResolver.openInputStream(uri) // Uri를 통해 InputStream 얻는 법
val exif = ExifInterface(inputStream)

하지만 위 예제코드의 경우 읽기만 가능하며, Scoped Storeage 정책때문에 당연히 쓰기는 불가능하다. Exif 쓰기를 원하는 경우 접근 가능한 File 경로로 원본 파일을 복사한 뒤에 쓰기를 진행하도록 하자.

Exif 읽기

ExifInterface를 활용하여 Exif를 정보를 가져올 시 지원하는 이미지 포맷은 다음과 같다.

지원하는 이미지 포맷 : JPEG, PNG, WebP, HEIF, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW, RAF, AVIF

ExifInterface를 객체를 생성 한 뒤 특정 태그에 대한 속성이 존재하는지 확인할 수 있다. 다음 예제코드를 확인하자.

val tag = ExifInterface.TAG_IMAGE_WIDTH // 이미지 너비 태그
if (exif.hasAttribute(tag)){ // 주어진 태그와 관련된 속성이 Exif에 포함되어 있는지 확인한다.
    ... // 이미지 파일에 이미지의 너비(width) 정보가 포함되어 있음.
}

androidx.exifinterface.media.ExifInterface 클래스 안에 TAG_*로 시작하는 정적 태그 필드들이 존재한다.
태그명을 하드코딩하는 대신 이런 정의된 필드를 참조하는 것이 좋다.

해당 태그에 대한 속성이 Exif에 존재 한다면, getAttribute로 시작하는 메서드를 통해 속성을 읽어올 수 있다. 다음 예제코드를 확인하자.

// 이미지 너비 읽어오기
val width:Int = exif.getAttributeInt( // Integer 타입으로 속성을 읽음
    ExifInterface.TAG_IMAGE_WIDTH, // 태그명
    0 // 기본값
) 

// 모델명을 가져온다. 
// String 타입으로 속성을 읽는다. 속성이 없을 경우 null 반환
val model:String? = exif.getAttribute(ExifInterface.TAG_MODEL) 

// 노출시간을 읽어오기
val exposureTime:Double = exif.getAttributeDouble( // Double 타입으로 속성을 읽음
    ExifInterface.TAG_EXPOSURE_TIME, // 태그명
    0.0 // 기본값
)

Exif 쓰기

ExifInterface를 활용하여 Exif 정보를 내보낼 때 지원하는 이미지 포맷은 다음과 같다.

지원하는 이미지 포맷 : JPEG, PNG, WebP, DNG

Exif를 수정할 때는 제약이 많이 따르므로, ExifInterface 생성자 인자와 이미지 포맷을 반드시 확인하도록 하자. 쓰기 조건이 맞지 않으면 크래시가 발생한다.

ExifInterface를 객체를 생성 한 뒤 setAttribute 메서드를 활용하여 특정 태그에 대한 속성값을 수정하거나 삭제할 수 있다. 다음 예제코드를 확인하자.

exif.setAttribute(ExifInterface.TAG_ARTIST, "Charlezz") // 카메라 주인, 포토그래퍼 또는 이미지 생성자의 이름을 변경한다.
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, null) // 위도 값을 제거 한다
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, null) // 경도 값을 제거 한다
exif.saveAttributes() // 변경한 속성들 파일에 저장

속성값을 쓴 뒤에 반드시 saveAttributes()를 호출해야 한다. 만약 saveAttributes() 호출시 크래시가 발생한다면, 위에서 언급한 내용들을 확인하여 쓰기 조건이 잘 설정되어 있는지 확인하고, 그래도 문제를 파악하기 어렵다면 로그캣에 출력되는 메시지를 확인하도록 하자.

Exif 태그의 종류와 결함

Exif의 버전별로 지원하는 태그 종류는 다양하므로 다음의 링크에서 자세한 내용을 확인하도록 하자.
표준 Exif 태그 목록 : https://exiv2.org/tags.html

Exif 형식에는 주로 레거시 파일 구조와 관련된 여러가지 이슈가 있다. 이 부분은 위키문서에서 확인할 수 있다.
Exif 문제점 : https://en.wikipedia.org/wiki/Exif#Problems

macOS 미리보기 앱으로 Exif 간단히 확인하기

Finder에서 파일을 선택후 단축키 cmd+i로 간단한 Exif 요약정보를 확인할 수도 있지만, 좀더 상세한 내용을 알고 싶다면 기본 앱인 ‘미리보기’를 실행한 뒤 여기서 다시 한번 cmd+i를 눌러서 더 많은 내용을 확인할 수도 있다.

카테고리: etc

0개의 댓글

답글 남기기

Avatar placeholder

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.