PNG 형식
Portable Network Graphics
chunk 기반 구조
PNG는 파일 형식 중에서도 손꼽히게 깔끔합니다. 모든 것이 "chunk"로 정리되어 있는데, 종류와 데이터와 체크섬을 스스로 갖춘 독립적인 블록이에요. 우아한 점은 디코더가 모르는 chunk는 그냥 건너뛸 수 있다는 것입니다. 덕분에 예전 소프트웨어를 망가뜨리지 않으면서 메타데이터를 담을 수 있어요.
영리한 부분은 chunk 이름 짓기 규칙이에요. 첫 글자가 대문자면 "critical"(그게 없으면 이미지가 표시되지 않음), 소문자면 "ancillary"(있으면 좋지만 필수는 아님)입니다. 우리가 신경 쓰는 메타데이터 chunk는 전부 ancillary라서 안심하고 지울 수 있어요.
PNG 파일 구조
PNG 시그니처와 IHDR
| Offset | Hex | ASCII | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0000 | 89504E470D0A1A0A0000000D49484452 | .PNG........IHDR | |||||||||||||||
| 0010 | 00000100000001000802000000000000 | ............. | |||||||||||||||
chunk의 구조
chunk 이름 규칙
- • 첫 글자 대문자 = critical chunk (반드시 해석해야 함)
- • 첫 글자 소문자 = ancillary chunk (선택 사항, 무시해도 됨)
- • 두 번째 글자 = 공개(대문자) 또는 비공개(소문자)
critical chunk
이미지가 유효하려면 반드시 있어야 하고, 반드시 해석되어야 하는 chunk입니다. PicScrub은 critical chunk를 항상 그대로 남깁니다.
IHDR:이미지 헤더
시그니처 다음에 오는 첫 chunk입니다. 너비, 높이, 비트 심도, 컬러 타입, 압축 방식, 필터 방식, 인터레이스 방식이 들어 있어요. 데이터는 정확히 13바이트입니다.
IDAT:이미지 데이터
zlib/deflate로 압축된 이미지 데이터가 들어 있습니다. 여러 IDAT chunk로 나뉠 수 있고, 모든 IDAT chunk는 연속으로 놓여야 합니다.
IEND:이미지 끝
PNG 데이터 스트림의 끝을 표시합니다. 반드시 마지막 chunk여야 하고, 데이터 바이트는 하나도 없습니다.
PLTE:팔레트
인덱스 컬러 이미지(컬러 타입 3)에 필요합니다. RGB 팔레트 항목이 1~256개 들어 있어요.
메타데이터 chunk
프라이버시에 민감한 정보가 들어갈 수 있는 ancillary chunk입니다. PicScrub이 지우는 것이 바로 이것들이에요.
tEXt:압축하지 않은 텍스트
Latin-1로 인코딩된 키-값 쌍입니다. 흔한 키로는 Author, Description, Copyright, Creation Time, Software가 있어요.
zTXt:압축된 텍스트
tEXt와 같지만 zlib으로 압축됩니다. 긴 텍스트에 씁니다.
iTXt:다국어 텍스트
선택적으로 압축할 수 있는 UTF-8 텍스트입니다. 언어 태그와 번역된 키워드를 지원하고, XMP 메타데이터에 쓰입니다.
XML:com.adobe.xmp\0eXIf:EXIF 데이터
2017년에 PNG 확장으로 정식 등록되었습니다. JPEG의 EXIF와 같은 구조로, TIFF 형식의 EXIF 데이터가 그대로 들어 있어요. GPS, 촬영 시각, 기기 정보가 들어 있을 수 있습니다.
iCCP:ICC 색상 프로필
파일에 담긴 ICC 색상 프로필로, zlib으로 압축됩니다. PicScrub은 색이 정확하게 보이도록 기본적으로 남겨 둡니다.
tIME:마지막 수정 시각
7바이트로 연도(2바이트), 월, 일, 시, 분, 초가 들어갑니다. 이미지를 마지막으로 수정한 시점이 드러나요.
색과 관련된 chunk
색이 어떻게 보이는지에 영향을 주지만, 보통 개인 정보는 담지 않는 chunk입니다. PicScrub은 기본적으로 그대로 남깁니다.
sRGB
sRGB 색 공간임을 나타냅니다. 렌더링 의도를 1바이트로 담아요.
gAMA
감마 값을 4바이트 부호 없는 정수로 담습니다(100,000배로 표현).
cHRM
기본색의 색도 좌표와 백색점 좌표입니다.
sBIT
각 채널의 원래 샘플 비트 심도입니다.
CRC32 검증
모든 PNG chunk에는 chunk 종류와 데이터로 계산한 CRC32 체크섬이 붙습니다. 이걸로 데이터 무결성을 보장해요.
CRC 계산
CRC32 입력 = chunk_type (4 bytes) + chunk_data (N bytes) CRC32 출력 = chunk 데이터 뒤에 붙는 4 bytes // PNG는 CRC-32 다항식 0xEDB88320을 사용합니다
PicScrub이 CRC를 검사하는 이유
PNG 파일을 읽을 때 PicScrub은 데이터 무결성을 확인하려고 각 chunk의 CRC를 검증합니다. 손상된 chunk는 안전하게 처리해요.
PicScrub이 PNG를 처리하는 방법
시그니처 확인
PNG 시그니처인지 검사합니다: 89 50 4E 47 0D 0A 1A 0A
chunk 파싱
각 chunk의 길이와 종류를 읽고 CRC를 검증합니다
메타데이터 chunk 걸러내기
tEXt, zTXt, iTXt, eXIf, tIME chunk를 찾아 건너뜁니다
파일 다시 조립
시그니처 + 걸러낸 chunk + IEND 순으로 씁니다
남기는 chunk
- • IHDR, PLTE, IDAT, IEND (critical)
- • sRGB, gAMA, cHRM (색 관련)
- • iCCP (색상 프로필, 선택 사항)
- • pHYs (픽셀 크기 정보)
- • tRNS (투명도)
지우는 chunk
- • tEXt (텍스트 메타데이터)
- • zTXt (압축된 텍스트)
- • iTXt (다국어 텍스트, XMP)
- • eXIf (EXIF 데이터)
- • tIME (수정 시각)