HEIC 형식
High Efficiency Image Container
ISOBMFF 컨테이너
MP4 비디오 파일을 다뤄 본 적이 있다면 HEIC이 낯설지 않을 거예요. Apple은 HEIC의 컨테이너로 ISO Base Media File Format(ISOBMFF)을 골랐습니다. 그래서 JPEG이나 PNG 같은 전통적인 이미지 형식보다 비디오 형식과 훨씬 닮았어요.
이 형식은 4글자 타입 코드를 가진 "박스"(아톰이라고도 해요)를 겹겹이 중첩해서 구성합니다. 복잡한 계층 구조를 담으면서도 기본만 알면 파싱하기 어렵지 않은, 의외로 우아한 설계예요.
HEIC 파일 구조
HEIC 헤더 (ftyp 박스)
| Offset | Hex | ASCII | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0000 | 000000186674797068656963 | ....ftypheic | |||||||||||
| 000C | 000000006D69663168656963 | ....mif1heic | |||||||||||
박스의 구조
크기가 1이면 타입 뒤에 8바이트짜리 확장 크기가 옵니다. 크기가 0이면 박스가 파일 끝까지 이어져요.
주요 박스
HEIC 파일의 박스 계층은 꽤 깊어질 수 있어요. 메타데이터가 예상 가능한 위치에 놓이는 JPEG과 달리, HEIC은 중첩 구조 안쪽 몇 겹 아래에 메타데이터를 묻어 둡니다. 주요 조각들이 어떻게 맞물리는지 볼까요.
ftyp:파일 타입
파일의 첫 박스입니다. 주 브랜드와 호환 브랜드가 들어 있고, 형식을 식별하는 데 꼭 필요해요.
heic heix hevc hevx heim heis hevm hevs mif1 msf1meta:메타데이터 컨테이너
아이템 위치, 속성, 연결 정보를 비롯한 모든 메타데이터가 들어 있습니다. EXIF/XMP 데이터가 사는 곳이 바로 여기예요.
meta (메타데이터 컨테이너) ├── hdlr (핸들러 참조) ├── pitm (주 아이템 ID) ├── iloc (아이템 위치 → mdat 안의 오프셋) │ └── [item_id, offset, length] 항목들 ├── iinf (아이템 정보 → 'Exif' 아이템 찾기) │ └── 아이템 타입이 담긴 infe 항목들 ├── iprp (아이템 속성) │ ├── ipco (속성 컨테이너) │ │ ├── hvcC (HEVC 디코더 설정) │ │ ├── ispe (이미지 크기) │ │ ├── colr (ICC 프로필, offset+12) │ │ ├── Exif (TIFF 형식의 EXIF) │ │ └── pixi (픽셀 정보) │ └── ipma (속성 연결) └── iref (아이템 참조)
mdat:미디어 데이터
HEVC로 인코딩된 실제 이미지 데이터가 들어 있습니다. meta 안의 iloc 박스가 mdat 안의 오프셋을 알려 줘요.
HEIC 속의 메타데이터
JPEG의 APP 마커에 익숙하다면 HEIC은 방식이 다르다는 걸 알게 될 거예요. 파일 앞쪽에 마커가 줄줄이 놓이는 대신, 메타데이터가 meta 박스 안의 "아이템 속성"으로 들어갑니다. 실제 EXIF 데이터는 여전히 익숙한 TIFF 형식이지만, 그걸 찾으려면 박스 계층을 먼저 헤쳐 나가야 해요.
EXIF 속성
ipco(아이템 속성 컨테이너) 안에 "Exif" 타입으로 저장됩니다. JPEG과 마찬가지로 TIFF 형식의 표준 EXIF 데이터가 들어 있어요.
XMP 속성
XML 기반 메타데이터로, content-type이 "application/rdf+xml"인 "mime" 타입 속성에 저장됩니다.
ICC 프로필
색상 프로필은 타입이 "prof"인 "colr" 박스에 저장됩니다.
오프셋이 중요한 이유
iloc 박스에는 mdat 안을 가리키는 정확한 바이트 오프셋이 들어 있습니다. 박스 크기가 하나라도 바뀌면(예를 들어 메타데이터를 지우면) 이 오프셋을 다시 계산해야 하고, 그러지 않으면 파일을 열 수 없게 돼요.
무손실 익명화
HEIC이 까다로워지는 지점이 여기예요. 이 형식은 비디오와 이미지를 효율적으로 저장하려고 설계된 것이지, 메타데이터를 손보기 쉽게 만들어진 게 아니거든요.
어려운 점
HEIC은 오프셋에 기반한 구조라서 바이트를 빼는 게 위험합니다. iloc 박스에는 mdat 안을 가리키는 정확한 바이트 오프셋이 들어 있어요. 박스를 하나만 지워도 그 오프셋이 전부 어긋나고, 이미지는 더 이상 열리지 않습니다.
0으로 덮어쓰는 방식
PicScrub은 메타데이터 박스를 지우는 대신, 박스 구조와 크기는 그대로 두고 내용만 0으로 덮어씁니다.
이후: [Exif][0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00...]
왜 0으로 덮어쓸까요?
- • 파일이 온전하게 유지됨:모든 오프셋이 그대로 유효합니다
- • 재압축 없음:이미지 데이터는 건드리지 않아요
- • 메타데이터는 파괴됨:0에는 아무 정보도 없죠
- • 되돌릴 수 있나요?:아니요, 덮어쓴 데이터는 사라집니다
PicScrub이 HEIC을 처리하는 방법
박스 구조 파싱
ftyp와 meta를 재귀적으로 파싱해 모든 박스를 찾아냅니다
메타데이터 위치 찾기
ipco 컨테이너에서 Exif와 XMP 속성을 찾습니다
메타데이터 내용 0으로 채우기
메타데이터 박스의 내용을 0으로 덮어씁니다
구조 그대로 유지
박스 헤더, 크기, 모든 오프셋을 손대지 않고 남깁니다
파일 크기에 대해
PicScrub은 삭제 대신 0으로 덮어쓰기 때문에, 결과 파일의 크기는 원본과 같습니다. 메타데이터가 있던 공간은 그대로 남고 0으로 채워져요.
HEIC, HEIF, AVIF의 차이
이름이 헷갈리니 정리해 볼게요. HEIF는 컨테이너 형식이고, HEIC과 AVIF는 그 컨테이너 안의 이미지를 어떤 코덱으로 압축했는지를 가리킵니다.
| 형식 | 컨테이너 | 코덱 | 쓰이는 곳 |
|---|---|---|---|
| HEIC | HEIF | HEVC (H.265) | Apple 기기 |
| HEIF | HEIF | 여러 가지 | 범용 컨테이너 |
| AVIF | HEIF | AV1 | 웹 (로열티 없음) |
셋 다 같은 ISOBMFF/HEIF 컨테이너 구조를 쓰기 때문에, PicScrub의 방식은 세 형식 모두에 통합니다.