JPEG
제일 많이 새는 놈JPEG 파일은 파일 헤더와 이미지 데이터 사이의 APPn 세그먼트에 메타데이터를 담습니다. 어디에 무엇이 들어 있고, PicScrub이 각 부분을 어떻게 다루는지 살펴보세요.
지워지는 것
- EXIF GPS 좌표, 카메라 제조사와 모델, 촬영 시각, 노출 설정
- XMP 편집 이력, 사용한 소프트웨어, 별점
- IPTC / Photoshop 캡션, 크레딧, 키워드
- 주석과 내장 썸네일 자르고 편집해도 살아남을 수 있는 원본의 작은 사본
남길 수 있는 것
- 이미지 데이터 언제나 그대로, 다시 인코딩하지 않아요
- ICC 색상 프로필 선택 사항, 색이 정확하게 보이도록
- 회전 정보 선택 사항, 세로 사진이 바로 서도록
- 저작권 표기 선택 사항, 좌표 없이 크레딧만 남기고 싶은 사진가를 위해
파일 구조 훑어보기
헥스 에디터로 JPEG을 열어 본 적이 있다면, 파일이 마커로 구분된 세그먼트들로 이루어져 있다는 걸 봤을 거예요. 모든 마커는 0xFF로 시작하고, 그 뒤의 바이트가 어떤 종류의 세그먼트인지 알려 줍니다. 이런 설계 덕분에 JPEG은 비교적 파싱하기 쉬워요. FF 바이트를 찾아 그 뒤에 뭐가 오는지 확인하면 됩니다.
프라이버시 측면에서 중요한 건, 모든 메타데이터(EXIF, GPS, 촬영 시각)가 실제 이미지 데이터와 완전히 분리된 이 세그먼트 안에 있다는 점이에요. 그래서 픽셀을 건드리거나 다시 압축하지 않고도 메타데이터만 지울 수 있습니다.
JPEG 파일 구조
JPEG 헤더 예시
| Offset | Hex | ASCII | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0000 | FFD8FFE000104A464946000101000048 | ......JFIF.....H | |||||||||||||||
| 0010 | 00480000FFE112344578696600000000 | .H.....4Exif.. | |||||||||||||||
마커의 구조
FF xx:마커 (xx가 종류를 나타냄)LL LL:길이 (2바이트, 빅엔디언, 자기 자신 포함)Data...:세그먼트 데이터 (길이 - 2바이트)
JPEG 마커 전체 목록
| 마커 | 이름 | 설명 |
|---|---|---|
| FF D8 | SOI | 이미지 시작 |
| FF D9 | EOI | 이미지 끝 |
| FF C0 | SOF0 | 프레임 시작 (베이스라인 DCT) |
| FF C2 | SOF2 | 프레임 시작 (프로그레시브 DCT) |
| FF C4 | DHT | 허프만 테이블 정의 |
| FF DB | DQT | 양자화 테이블 정의 |
| FF DD | DRI | 재시작 간격 정의 |
| FF DA | SOS | 스캔 시작 (이 뒤로 이미지 데이터) |
| FF FE | COM | 주석 (메타데이터) |
| FF E0 | APP0 | JFIF 마커 |
| FF E1 | APP1 | EXIF / XMP 마커 |
| FF E2 | APP2 | ICC 프로필 / MPF |
| FF ED | APP13 | IPTC / Photoshop |
| FF EE | APP14 | Adobe 색 변환 정보 |
금색 = 메타데이터(지워짐), 그냥 = 남는 구조
JFIF와 EXIF
많은 사람이 헷갈려 하는 부분이 있어요. JPEG 파일에는 서로 다른 메타데이터 표준이 두 가지 동시에 들어 있는 경우가 많습니다. JFIF가 먼저 나와서 해상도 같은 기본 정보를 담당했고, 그다음에 카메라들이 촬영 정보를 자세히 담은 EXIF를 넣기 시작했어요. 요즘 JPEG은 대부분 둘 다 가지고 있고, 그래서 파일 앞부분에 APP0과 APP1 마커가 나란히 보이는 겁니다.
APP0:JFIF
JPEG File Interchange Format. 기본적인 이미지 정보를 담습니다.
- • 버전 번호
- • 픽셀 밀도 (DPI)
- • 화면 비율
- • 선택적 썸네일
APP1:EXIF
Exchangeable Image File Format. 카메라 메타데이터를 담습니다.
- • 카메라 제조사/모델
- • GPS 좌표
- • 촬영 시각
- • 노출 설정
APP 마커 깊이 보기
JPEG 규격은 각 업체가 원하는 대로 쓰라고 "애플리케이션" 마커 16개 (APP0부터 APP15까지)를 비워 뒀습니다. 세월이 흐르면서 여러 단체가 자기 메타데이터 형식으로 서로 다른 마커를 차지했어요. 결과는 좀 뒤죽박죽이지만, 그래도 문서는 잘 되어 있는 뒤죽박죽입니다.
까다로운 점은 같은 마커라도 내용에 따라 의미가 달라진다는 거예요. 예를 들어 APP1은 EXIF일 수도 XMP일 수도 있어서, 안에 들어 있는 식별자 문자열을 봐야 어느 쪽인지 알 수 있습니다.
APP0 (0xFFE0):JFIF
식별자: JFIF\0. 버전, 밀도 단위, X/Y 밀도, 선택적인 내장 썸네일이 들어 있습니다. 대체로 남겨도 안전해요.
APP1 (0xFFE1):EXIF
식별자: Exif\0\0. 카메라 정보, GPS 데이터, 촬영 시각, 썸네일, 메이커 노트를 담는 IFD 항목들이 들어간 완전한 TIFF 구조가 통째로 들어 있습니다. 프라이버시 측면에서 가장 문제가 되는 부분이에요.
APP1 (0xFFE1):XMP
식별자: http://ns.adobe.com/xap/1.0/\0. Adobe가 만든 XML 기반 메타데이터 표준입니다. 편집 이력, 소프트웨어 정보, 확장된 EXIF 데이터가 들어갈 수 있어요.
XMP 네임스페이스
xmp: http://ns.adobe.com/xap/1.0/xmpMM: http://ns.adobe.com/xap/1.0/mm/dc: http://purl.org/dc/elements/1.1/photoshop: http://ns.adobe.com/photoshop/1.0/tiff: http://ns.adobe.com/tiff/1.0/exif: http://ns.adobe.com/exif/1.0/APP1 (0xFFE1):확장 XMP
식별자: http://ns.adobe.com/xmp/extension/\0. 65KB를 넘는 XMP 데이터를 여러 APP1 세그먼트에 나눠 담을 때 씁니다.
APP2 (0xFFE2):MPF
식별자: MPF\0. 입체 이미지와 파노라마를 위한 Multi-Picture Format입니다.
APP2 (0xFFE2):ICC 프로필
식별자: ICC_PROFILE\0. 색 관리 데이터입니다. 여러 APP2 마커에 나뉘어 들어갈 수 있어요. 보통은 남겨도 괜찮습니다.
APP13 (0xFFED):IPTC/Photoshop
식별자: Photoshop 3.0\0. 캡션, 키워드, 저작권, 작성자 정보가 담긴 IPTC-IIM 데이터가 들어 있습니다. 작성자 정보가 포함될 수 있어요.
APP14 (0xFFEE):Adobe
식별자: Adobe\0. 색 변환 플래그(RGB/CMYK)가 들어 있습니다. 색을 제대로 표현하는 데 중요해요.
EXIF의 구조
여기서부터가 재미있고 조금 이상한 부분이에요. EXIF 데이터는 사실 JPEG 안에 들어 있는 아주 작은 TIFF 파일입니다. 정말이에요. 자기만의 헤더와 바이트 순서를 가지고 있고, 태그를 저장하는 데 TIFF의 IFD(Image File Directory) 구조를 씁니다.
"Exif" 식별자 다음에 처음 보이는 건 TIFF 헤더인데, 데이터가 리틀엔디언(Intel, "II")인지 빅엔디언(Motorola, "MM")인지 알려 줍니다. 이걸 잘못 읽으면 모든 숫자가 엉망이 되기 때문에, 어떤 파서든 가장 먼저 확인하는 부분이에요.
TIFF 헤더 (8바이트)
| Offset | Hex | ASCII | |||||||
|---|---|---|---|---|---|---|---|---|---|
| 0000 | 49492A0008000000 | II*..... | |||||||
II = Intel(리틀엔디언), MM = Motorola(빅엔디언)
IFD 항목의 구조 (12바이트)
주요 IFD 항목
0x010F:Make0x0110:Model0x0132:DateTime0x8769:ExifIFDPointer0x8825:GPSInfoIFDPointer0x927C:MakerNotePicScrub이 JPEG을 처리하는 방법
방식은 아주 단순합니다. 파일을 마커 단위로 읽어 나가면서, 이미지를 표시하는 데 꼭 필요한 것은 남기고 메타데이터가 담긴 것은 건너뜁니다. 압축된 이미지 데이터는 아예 건드리지 않으니 화질 손실이 전혀 없어요.
핵심은 JPEG의 마커 기반 구조 덕분에 이 작업이 쉽다는 점입니다. DCT 계수나 허프만 테이블을 이해할 필요가 없어요. 어떤 세그먼트가 메타데이터이고 어떤 게 아닌지만 가려내면 됩니다.
헤더 확인
파일 맨 앞에 SOI 마커(FF D8)가 있는지 검사합니다
마커 파싱
마커를 순서대로 읽으며 종류와 길이를 뽑아냅니다
메타데이터 판별
APP 세그먼트의 식별자를 확인합니다 (EXIF, XMP, IPTC 등)
선별 복사
메타데이터가 아닌 세그먼트만 결과 파일에 옮기고, 메타데이터 세그먼트는 건너뜁니다
남는 것
- • SOI/EOI 마커 (필수)
- • DQT (양자화 테이블)
- • SOF (프레임 헤더)
- • DHT (허프만 테이블)
- • SOS와 스캔 데이터 (실제 이미지)
- • 선택 사항: ICC 색상 프로필 (설정 가능)
지워지는 것
- • APP1 EXIF (카메라, GPS, 촬영 시각)
- • APP1 XMP (편집 메타데이터)
- • APP13 IPTC (캡션, 작성자)
- • COM 마커 (주석)
- • EXIF 썸네일 이미지
EXIF 태그 목록
프라이버시 관점에서 모든 EXIF 태그가 똑같이 위험한 건 아니에요. 노출 설정 같은 건 거의 무해합니다. 반면 일련번호나 소유자 이름은 사용자나 장비를 특정할 수 있어요. 저희가 위험도가 높다고 보는 태그는 다음과 같습니다:
| 태그 ID | 이름 | 프라이버시 위험도 |
|---|---|---|
| 0x9003 | DateTimeOriginal | 높음 |
| 0x9004 | DateTimeDigitized | 높음 |
| 0x9010 | OffsetTime | 보통 |
| 0x9286 | UserComment | 높음 |
| 0x927C | MakerNote | 높음 |
| 0xA420 | ImageUniqueID | 높음 |
| 0xA430 | CameraOwnerName | 높음 |
| 0xA431 | BodySerialNumber | 높음 |
| 0xA434 | LensModel | 보통 |
| 0xA435 | LensSerialNumber | 높음 |
| 0xFDE8 | OwnerName | 높음 |
| 0xFDE9 | SerialNumber | 높음 |
카메라 설정 태그 전체 보기 (신원과 무관)
0x829A ExposureTime0x829D FNumber0x8822 ExposureProgram0x8827 ISOSpeedRatings0x9201 ShutterSpeedValue0x9202 ApertureValue0x9203 BrightnessValue0x9204 ExposureBiasValue0x9207 MeteringMode0x9208 LightSource0x9209 Flash0x920A FocalLength0xA001 ColorSpace0xA002 PixelXDimension0xA003 PixelYDimension0xA402 ExposureMode0xA403 WhiteBalance0xA405 FocalLengthIn35mmFilm0xA406 SceneCaptureTypeGPS 태그 목록
GPS 데이터는 메인 IFD의 0x8825 태그가 가리키는 별도의 하위 IFD에 들어 있습니다. 이 포인터가 있다면 이미지에 위치 정보가 들어 있다는 뜻이에요. 요즘 스마트폰은 특히 적극적으로 이 정보를 넣는데, 어디에 서 있었는지까지 짚어낼 만큼 정밀한 경우도 많습니다.
| 태그 ID | 이름 | 설명 |
|---|---|---|
| 0x0000 | GPSVersionID | GPS 태그 버전 |
| 0x0001 | GPSLatitudeRef | N 또는 S |
| 0x0002 | GPSLatitude | 도, 분, 초 |
| 0x0003 | GPSLongitudeRef | E 또는 W |
| 0x0004 | GPSLongitude | 도, 분, 초 |
| 0x0005 | GPSAltitudeRef | 해수면 위/아래 |
| 0x0006 | GPSAltitude | 미터 |
| 0x0007 | GPSTimeStamp | UTC 시각 |
| 0x001D | GPSDateStamp | UTC 날짜 |
| 0x0012 | GPSMapDatum | 측지 기준계 정보 |
| 0x001B | GPSProcessingMethod | GPS/CELLID/WLAN/MANUAL |
| 0x001C | GPSAreaInformation | 장소 이름 |
IPTC 태그 목록
IPTC는 통신사들이 캡션, 크레딧, 저작권 정보를 사진에 심으려고 만든 표준이에요. "Photoshop 3.0" 식별자와 함께 APP13 안에 저장됩니다 (네, Adobe가 가져다 썼어요). Lightroom이나 Photoshop에서 저작권 정보나 키워드를 넣은 적이 있다면, 그게 바로 여기에 들어갑니다.
0x0250 By-line (작성자)0x0255 By-line Title (작성자 직함)0x025A City (도시)0x025C Sub-location (세부 장소)0x025F Province/State (지역)0x0265 Country Name (국가)0x0274 Copyright Notice (저작권 표기)0x0276 Contact (연락처)0x0237 Date Created (생성 날짜)0x023C Time Created (생성 시각)0x0278 Caption/Abstract (캡션)0x0219 Keywords (키워드)