TIFF 형식
Tagged Image File Format
헤더 구조
TIFF는 이미지 메타데이터의 할아버지 격이에요. JPEG 안에서 보는 EXIF 데이터도 사실은 파일 속에 들어간 TIFF 구조입니다. TIFF를 이해하면 대부분의 이미지 메타데이터가 어떻게 돌아가는지 알게 되는 셈이죠.
파일은 8바이트 헤더로 시작하는데, 여기서 두 가지 중요한 걸 알려 줍니다. 바이트 순서(Intel이냐 Motorola냐)와 첫 IFD가 어디 있는지죠. 그다음부터는 계속 포인터를 따라가는 일입니다.
TIFF 파일 구조
TIFF 헤더
| Offset | Hex | ASCII | |||||||
|---|---|---|---|---|---|---|---|---|---|
| 0000 | 49492A0008000000 | II*..... | |||||||
바이트 순서
49 49 (II)Intel:리틀엔디언 (낮은 자리 바이트가 먼저)
4D 4D (MM)Motorola:빅엔디언 (높은 자리 바이트가 먼저)
IFD의 구조
IFD는 Image File Directory의 약자인데, 그냥 목차라고 생각하면 돼요. 태그를 쭉 늘어놓은 목록이고, 각 태그가 어떤 데이터를 가리킵니다. 영리한 점은 IFD가 다른 IFD를 가리킬 수 있어서 트리 구조가 만들어진다는 거예요.
IFD 배치
태그 항목의 구조 (12바이트)
데이터가 4바이트 안에 들어가면 값 필드에 그대로 저장합니다. 그렇지 않으면 값 필드에 데이터가 있는 위치의 오프셋이 들어가요.
태그 타입
TIFF는 타입이 엄격한 형식이에요. 각 태그는 무엇이 들어 있는지뿐 아니라 바이트를 어떻게 해석해야 하는지도 함께 지정합니다. 그래서 TIFF를 제대로 파싱하려면 타입 체계를 알아야 해요.
| ID | 이름 | 크기 | 설명 |
|---|---|---|---|
| 1 | BYTE | 1 | 부호 없는 8비트 정수 |
| 2 | ASCII | 1 | null로 끝나는 문자열 (8비트) |
| 3 | SHORT | 2 | 부호 없는 16비트 정수 |
| 4 | LONG | 4 | 부호 없는 32비트 정수 |
| 5 | RATIONAL | 8 | LONG 두 개: 분자/분모 |
| 6 | SBYTE | 1 | 부호 있는 8비트 정수 |
| 7 | UNDEFINED | 1 | 원시 바이트 (바이너리 데이터) |
| 8 | SSHORT | 2 | 부호 있는 16비트 정수 |
| 9 | SLONG | 4 | 부호 있는 32비트 정수 |
| 10 | SRATIONAL | 8 | SLONG 두 개: 부호 있는 분자/분모 |
| 11 | FLOAT | 4 | IEEE 32비트 부동소수점 |
| 12 | DOUBLE | 8 | IEEE 64비트 배정밀도 |
| 13 | IFD | 4 | 중첩된 IFD를 가리키는 포인터 |
값 저장 규칙
크기 × 개수 ≤ 4바이트이면 값을 4바이트짜리 값 필드에 그대로 저장합니다. 그보다 크면 값 필드에는 데이터가 저장된 위치를 가리키는 오프셋이 들어갑니다.
IFD 오프셋 계산
TIFF 파싱에서 제일 까다로운 건 오프셋 사슬을 따라가는 일이에요. 모든 값이 파일 시작을 기준으로 하기 때문에, 파일 안을 이리저리 많이 건너뛰게 됩니다. 계산은 이렇게 해요:
IFD0_offset = bytes[4:8] // TIFF 헤더에서 가져옴
next_IFD = IFD0_offset + 2 + (entry_count × 12) + 4
subIFD_offset = tag_value // 포인터 태그(0x8769, 0x8825)에서 가져옴
중요한 태그
이미지 데이터 태그 (남김)
0x0100:ImageWidth0x0101:ImageLength0x0102:BitsPerSample0x0103:Compression0x0111:StripOffsets0x0117:StripByteCounts메타데이터 태그 (지움)
0x010F:Make (카메라 제조사)0x0110:Model (카메라 모델)0x0132:DateTime0x013B:Artist0x8298:Copyright0x9003:DateTimeOriginal포인터 태그 (하위 IFD)
0x8769:ExifIFDPointer0x8825:GPSInfoIFDPointer0xA005:InteroperabilityIFDPointer하위 IFD
메인 IFD(IFD0)에는 하위 디렉터리를 가리키는 "포인터 태그"가 들어 있는 경우가 많습니다. 이렇게 해서 EXIF, GPS를 비롯한 메타데이터를 의미 있는 묶음으로 정리하면서도 메인 IFD를 깔끔하게 유지해요.
EXIF SubIFD
카메라 관련 메타데이터가 들어 있습니다. 노출, 조리개, ISO, 초점 거리, 플래시, 화이트 밸런스 등이죠.
GPS SubIFD
위치 정보가 들어 있습니다. 위도, 경도, 고도, 시각, 위성 수, 속도, 방향까지요. 프라이버시에 가장 위험한 부분이에요.
메이커 노트
제조사 고유의 카메라 데이터입니다. 형식은 제조사마다 다르고, 일련번호, 펌웨어 버전, 사용자 설정이 들어 있을 수 있어요.
PicScrub이 TIFF를 처리하는 방법
헤더 파싱
바이트 순서(II/MM)를 판별하고 첫 IFD 위치를 찾습니다
태그 허용 목록 만들기
이미지를 그리는 데 꼭 필요한 태그를 추려냅니다
IFD 항목 걸러내기
메타데이터 태그를 지우고 하위 IFD 포인터를 0으로 만듭니다
파일 다시 쓰기
깨끗해진 IFD와 그대로 복사한 이미지 데이터로 TIFF를 다시 조립합니다
오프셋 재계산
TIFF는 파일 오프셋을 아주 많이 씁니다. 그래서 메타데이터를 지운 뒤에는 파일이 온전하게 유지되도록 PicScrub이 모든 오프셋을 다시 계산해야 해요.