또한 번역본을 참고하세요.
Copyright © 1996-2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
이 문서는 PNG(포터블 네트워크 그래픽스, Portable Network Graphics)에 대해 설명합니다. PNG는 손실 없이 확장 가능하며, 휴대할 수 있고, 정적 및 애니메이션 래스터 이미지를 효율적으로 압축하여 저장할 수 있는 파일 포맷입니다. PNG는 특허가 없는 GIF의 대체재를 제공하며, 일반적인 TIFF의 많은 용도도 대체할 수 있습니다. 인덱스 컬러, 그레이스케일, 트루컬러 이미지를 지원하며, 선택적 알파 채널도 포함할 수 있습니다. 샘플 비트 깊이는 1비트에서 16비트까지 지원됩니다.
PNG는 월드 와이드 웹과 같은 온라인 뷰어 애플리케이션에 잘 동작하도록 설계되어, 점진적 표시 옵션을 통해 완전히 스트리밍할 수 있습니다. PNG는 견고하며, 전체 파일 무결성 검사와 일반적인 전송 오류의 간단한 감지를 모두 제공합니다. 또한 PNG는 이기종 플랫폼에서 향상된 색상 일치를 위해 색 공간 데이터 저장이 가능합니다.
이 명세서는 두 가지 인터넷 미디어 타입, image/png와 image/apng를 정의합니다.
이 섹션은 이 문서가 발행 시점에 어떠한 상태였는지 설명합니다. 현재 W3C 발행물과 이 기술 보고서의 최신 개정판 목록은 W3C 표준 및 초안 색인 https://www.w3.org/TR/ 에서 확인할 수 있습니다.
이 명세서는 국제 표준이 되는 것을 목표로 하지만, 아직 국제 표준은 아닙니다. 이 명세서를 국제 표준으로 참조하는 것은 적절하지 않습니다.
이 문서는 포터블 네트워크 그래픽스(PNG) 워킹 그룹에서 권고안 트랙을 이용하여 권고안으로 발행된 것입니다.
W3C 권고안은 광범위한 합의 구축 과정을 거친 후 W3C와 그 회원들에 의해 승인된 명세로, 워킹 그룹 회원들이 구현에 대해 로열티 없는 라이선스를 제공하기로 약속한 문서입니다.
W3C는 이 명세서를 웹 표준으로 널리 배포할 것을 권장합니다.
이 문서는 W3C 특허 정책에 따라 운영되는 그룹에 의해 작성되었습니다. W3C는 해당 그룹 산출물과 관련된 모든 특허 공개 목록을 공개적으로 유지합니다. 해당 페이지에는 특허 공개 방법에 대한 안내도 포함되어 있습니다. 어떤 사람이 특정 특허가 필수 청구항을 포함한다고 믿을 만한 실제 정보를 가지고 있다면, W3C 특허 정책 6조에 따라 정보를 공개해야 합니다.
이 문서는 2023년 11월 3일자 W3C 프로세스 문서의 적용을 받습니다.
이 명세서의 설계 목표는 다음과 같습니다:
이 명세서는 데이터스트림과 연관된 파일 포맷인 포터블 네트워크 그래픽스(PNG, "핑"으로 발음됨)를 정의합니다. PNG는 무손실이며, 이식 가능하고, 압축된 단일 컴퓨터 그래픽 이미지 또는 프레임 기반 애니메이션을 인터넷을 통해 전송하는 데 사용됩니다.
이 명세서에서는 다음과 같은 정의가 적용됩니다.
색도는 밝기와 무관하게 색의 품질을 측정하는 지표입니다.
전경 이미지는 배경에 합성된다고 표현합니다.
출처: [RFC1951]
소프트웨어는 이미지를 프레임 버퍼에 로드하여 화면에 이미지를 표시합니다.
0 및 2bit depth -
1에 해당하는 이미지
휘도와 색도는 함께 측정된 색을 완전히 정의합니다. 공식 정의는 [COLORIMETRY]를 참고하세요.
0 및 2bit depth - 1에 해당하지 않는 이미지
PNG에서는 RGB만 사용할 수 있으며, ICtCp는 지원되지 않습니다.
0에서 231-1 범위의 4바이트 부호 없는 정수
이 제한은 부호 없는 4바이트 값을 다루기 어려운 언어를 고려하여 적용되었습니다.
네트워크 바이트 순서의 2바이트 부호 없는 정수
표준 다이나믹 레인지는 프라이머리(원색)와 무관하며, 따라서 색 영역도 무관합니다. PNG는 광색역 SDR 포맷도 지원합니다.
디플레이트(deflate) 방식의 압축 기법
출처: [rfc1950]
이 방식의 샘플 구현 라이브러리 명칭 또한 zlib입니다.
대부분의 전송 오류를 감지하도록 설계된 체크값 유형
디코더는 수신된 데이터에 대해 CRC를 계산하고, 인코더가 계산해서 데이터에 덧붙인 CRC와 비교하여 검사합니다. 일치하지 않으면 데이터 또는 CRC가 전송 중 손상되었음을 나타냅니다.
모든 PNG 이미지는 하나의 정적 이미지를 포함합니다.
일부 PNG 이미지 — 애니메이션 PNG (APNG) — 는 프레임 기반 애니메이션 시퀀스인 애니메이션 이미지도 포함합니다. 첫 번째 프레임은 정적 이미지일 수도 있고 아닐 수도 있습니다. 프린터와 같은 애니메이션 미지원 디스플레이는 애니메이션 시퀀스 대신 정적 이미지를 표시합니다.
이 명세서는 PNG 데이터스트림을 규정하고, PNG 데이터스트림을 생성하는 PNG 인코더, 해석하는 PNG 디코더, 그리고 하나의 PNG 데이터스트림을 다른 데이터스트림으로 변환하는 PNG 에디터에 대해 일부 요구 사항을 부과합니다. 애플리케이션과 인코더/디코더/에디터 간 인터페이스는 규정하지 않습니다. 인코더에 이미지가 제공되거나 디코더가 이미지를 전달하는 정확한 형식은 규정하지 않습니다. 네 가지 종류의 이미지를 구분합니다.
네 가지 이미지 간의 관계는 Figure 1에 설명되어 있습니다.
샘플, 채널, 픽셀 및 샘플 비트 깊이 간의 관계는 Figure 2에 설명되어 있습니다.
색상 샘플이 위치하는 RGB 색 공간은 다음 네 가지 방법 중 하나로 지정할 수 있습니다:
하이엔드 애플리케이션의 경우 첫 두 방법이 가장 유연하고 제어가 용이합니다. 세 번째 방법은 특정하지만 매우 일반적인 색 공간을 표시할 수 있게 합니다. ICC 프로파일이 널리 채택되기 전에 표준화된 네 번째 방법은 RGB 데이터의 정확한 색도와 적용할 감마 보정을 지정할 수 있습니다(참조: C. 감마와 색도). 다만 색 인지 애플리케이션은 일반적으로 처음 세 방법 중 하나를 선호하고, 색 비인지 애플리케이션은 대개 네 가지 모두를 무시합니다.
Table 1은 색 공간 정보를 제공하는 청크 유형 목록이며, 각 청크에는 우선순위 번호가 있습니다. 하나의 이미지에 이러한 청크 유형이 둘 이상 포함된 경우, 우선순위 번호가 가장 낮은 청크가 우선하며 더 높은 번호의 청크 유형은 무시해야 합니다.
| 청크 유형 | 우선순위 |
|---|---|
| cICP | 1 |
| iCCP | 2 |
| sRGB | 3 |
| cHRM 및 gAMA | 4 |
감마 보정은(존재하는 경우) 알파 채널에는 적용되지 않습니다. 알파 샘플은 항상 풀 레인지이며, 완전 불투명도의 선형 비율을 나타냅니다.
마스터링 메타데이터를 제공할 수도 있습니다.
인코딩할 PNG 이미지를 생성하기 위해 참조 이미지에 여러 변환이 적용됩니다(참조: Figure 3). 변환은 다음 순서로 적용되며, 대괄호는 선택적 변환을 의미합니다:
[alpha separation]
indexing or ( [RGB merging] [alpha compaction] )
sample depth scaling
모든 픽셀이 완전 투명 또는 완전 불투명인 경우, 알파 분리, 알파 압축, 인덱싱 변환으로 인해 복원된 참조 이미지의 알파 샘플 비트 깊이가 원래 참조 이미지와 달라지거나 알파 채널이 없어질 수 있습니다. 이는 어떤 픽셀의 불투명도에도 영향을 주지 않습니다. 두 참조 이미지는 동등한 것으로 간주되며, 변환은 무손실로 간주됩니다. 그럼에도 알파 샘플 비트 깊이를 유지하고자 하는 인코더는 알파 샘플 비트 깊이를 변경시키는 변환을 수행하지 않기로 선택할 수 있습니다.
참조 이미지의 모든 알파 샘플이 최대값인 경우, 알파 채널을 생략할 수 있으며, 이는 더 간결하게 인코딩할 수 있는 동등한 이미지를 생성합니다.
서로 다른 픽셀 값의 개수가 256 이하이고, RGB 샘플 비트 깊이가 8을 초과하지 않으며, 알파 채널이 없거나 정확히 8비트이거나 모든 픽셀이 완전 투명 또는 완전 불투명인 경우, 인덱싱 변환을 통해 달성되는 대안적 인덱스 컬러 표현이 인코딩에 더 효율적일 수 있습니다. 인덱스 컬러 표현에서는 각 픽셀이 팔레트에 대한 인덱스로 대체됩니다. 팔레트 는 각 항목에 8비트 샘플(빨강, 초록, 파랑) 세 개를 포함하는 목록입니다. 알파 채널이 존재하면, 8비트 알파 샘플의 병렬 테이블(알파 테이블)도 있습니다.
일부 뷰어가 표시 가능한 색상 수가 제한적인 경우를 돕기 위해, PNG 이미지가 인덱스 컬러가 아니더라도 권장 팔레트를 구성할 수 있습니다.
인덱스 컬러 이미지의 경우, 인코더는 알파 최대값을 가진 테이블 항목이 끝에 모이도록 팔레트를 재배열할 수 있습니다. 이 경우 해당 항목을 포함하지 않는 단축 형식으로 테이블을 인코딩할 수 있습니다.
인덱스 컬러 PNG를 생성하는 인코더는 팔레트 테이블의 실제 길이를 초과하는 인덱스 값을 삽입해서는 안 됩니다. 그렇게 하면 오류이며, 디코더는 이 오류 처리에서 동작이 상이할 수 있습니다.
빨강, 초록, 파랑 채널의 샘플 비트 깊이가 동일하고, 각 픽셀에서 빨강·초록·파랑 샘플 값이 서로 같다면, 이 세 채널을 단일 그레이스케일 채널로 병합할 수 있습니다.
비인덱스 이미지에서, 특정 RGB(또는 그레이스케일) 값에 해당하는 모든 픽셀이 완전 투명이고 그 외 모든 픽셀이 완전 불투명하다면, 투명한 RGB(또는 그레이스케일) 값을 식별하는 것만으로 알파 채널을 더 간결하게 표현할 수 있습니다.
PNG 이미지에서는 모든 샘플 비트 깊이가 지원되는 것은 아니며(참조: 6.1 색상 타입 및 값), 모든 채널은 동일한 샘플 비트 깊이를 가져야 합니다. PNG 이미지의 모든 채널은 참조 이미지의 어떤 샘플 비트 깊이보다도 작지 않은, 허용되는 가장 작은 샘플 비트 깊이를 사용하며, 참조 이미지에서 가능한 샘플 값은 PNG 이미지의 다음 허용 범위로 선형 매핑됩니다. Figure 5는 비트 깊이 3의 샘플이 비트 깊이 4의 샘플로 매핑될 수 있는 방식을 보여줍니다.
소수의 샘플 비트 깊이만 허용하면 디코더가 처리해야 하는 경우의 수가 줄어듭니다. 샘플 비트 깊이 스케일링은 참조 이미지의 샘플 비트 깊이를 PNG 데이터스트림에 기록할 수 있으므로 데이터 손실 없이 가역적입니다. 기록된 샘플 비트 깊이가 없는 경우, 참조 이미지의 샘플 비트 깊이는 PNG 이미지의 샘플 비트 깊이와 동일합니다. 참조: 12.4 샘플 비트 깊이 스케일링, 13.12 샘플 비트 깊이 재스케일링.
참조 이미지의 변환 결과는 다섯 가지 PNG 이미지 유형 중 하나가 됩니다(참조: Figure 6) :
각 픽셀의 형식은 PNG 이미지 유형과 비트 깊이에 따라 달라집니다. 인덱스 컬러가 아닌 PNG 이미지 유형의 경우, 비트 깊이는 픽셀당 총 비트 수가 아니라 샘플당 비트 수를 지정합니다. 인덱스 컬러 이미지의 경우, 비트 깊이는 팔레트 인덱스의 비트 수를 지정하며, 팔레트나 알파 테이블의 색상 샘플 비트 깊이를 의미하지는 않습니다. 픽셀 내에서 샘플은 PNG 이미지 유형에 따라 다음 순서로 나타납니다.
PNG 이미지 인코딩 과정의 개념적 모델은 Figure 7에 제시됩니다. 단계는 PNG 이미지의 픽셀 또는 인덱스 배열에 대한 작업을 나타냅니다. 팔레트와 알파 테이블은 이 방식으로 인코딩되지 않습니다.
패스 추출(참조: Figure 7)은 PNG 이미지를 일련의 축소 이미지로 분할합니다. 첫 번째 이미지는 거친 뷰를 정의하고, 이후 이미지는 마지막 이미지가 PNG 이미지를 완성할 때까지 이 거친 뷰를 점차 향상시킵니다. 축소 이미지 집합은 인터레이스 PNG 이미지라고도 합니다. 이 명세서에는 두 가지 인터레이스 방식이 정의되어 있습니다. 첫 번째 방식은 널(null) 방식으로, 픽셀은 왼쪽에서 오른쪽으로, 스캔라인은 위에서 아래로 순차적으로 저장됩니다. 두 번째 방식은 이미지를 여러 번 스캔하여 일곱 개의 축소 이미지 시퀀스를 생성합니다. 샘플 이미지에 대한 일곱 개의 패스는 Figure 7에 나와 있습니다. 자세한 내용은 8. 인터레이싱 및 패스 추출을 참조하세요.
스캔라인이라고 불리는 각 픽셀 행은 바이트 시퀀스로 표현됩니다.
PNG는 압축 전에 이미지 데이터를 필터링할 수 있도록 허용합니다. 필터링은 데이터의 압축 가능성을 향상시킬 수 있습니다. 필터 작업은 결정적이며 가역적이고 무손실입니다. 이를 통해 압축 해제된 데이터를 역필터링하여 원본 데이터를 얻을 수 있습니다. 참조: 7.3 필터링.
PNG 이미지의 패스 또는 패스들의 필터링된 스캔라인 시퀀스는 정의된 압축 방식 중 하나로 압축됩니다(참조: Figure 9). 연결(concatenate)된 필터링 스캔라인은 압축 단계의 입력을 이룹니다. 압축 단계의 출력은 단일 압축 데이터스트림입니다. 참조: 10. 압축.
청크 분할은 압축된 데이터스트림을 관리하기 쉬운 청크로 편리하게 분해합니다(참조: Figure 9). 각 청크에는 자체 중복 검사(오류 검출)가 있습니다. 참조: 11. 청크 명세.
보조 정보가 이미지와 연관될 수 있습니다. 디코더는 일부 또는 모든 보조 정보를 무시할 수 있습니다. 제공되는 보조 정보 유형은 Table 2에 설명되어 있습니다.
| 정보 유형 | 설명 |
|---|---|
| 애니메이션 정보 | 뷰어가 표시할 수 있는 경우 표시하도록, 타이밍·위치·처리 정보가 연관된 일련의 프레임으로 정의되는 애니메이션 이미지. 프린터와 같은 다른 경우에는 정적 이미지가 대신 표시됩니다. |
| 배경색 | 이미지를 표시할 때 더 나은 옵션이 없을 경우 사용할 단색 배경색. |
| 코딩 독립 코드 포인트 | 전달 함수 및 원색(primaries) 등 메타데이터를 열거하여 색 공간을 식별합니다. 원래는 SDR 및 HDR 비디오용이었으나, 정지 이미지와 애니메이션 이미지에도 사용됩니다. |
| 콘텐츠 밝기 정보 (CLL/FALL) | 이미지(또는 이미지 시퀀스)에서 가장 밝은 픽셀의 휘도와, 시퀀스에서 가장 밝은 프레임의 평균 휘도 수준. |
| EXIF 정보 | 셔터 속도, 조리개, 방향(orientation) 등 교환 이미지 파일 형식(Exif) 메타데이터 |
| 감마 및 색도 | 원하는 출력 강도에 대한 이미지의 감마 값 및 이미지에서 사용된 RGB 값의 색도 특성. |
| ICC 프로파일 | 이미지의 샘플이 부합하는 색 공간을 설명하는 국제 색상 컨소시엄(ICC) 프로파일. |
| 이미지 히스토그램 | 이미지가 각 팔레트 항목을 얼마나 자주 사용하는지에 대한 추정. |
| 마스터링 디스플레이 색상 볼륨 | 콘텐츠를 제작하는 데 사용된 디스플레이의 절대 3차원 색역 볼륨을 설명하며, 마스터링 디스플레이가 재현할 수 있는 가장 밝고 어두운 색을 포함합니다. 이는 디스플레이 장치에서 이미지를 제시하는 데 도움을 줍니다. |
| 물리적 픽셀 크기 | PNG 이미지를 표시할 때 사용할 의도한 픽셀 크기와 종횡비. |
| 유의 비트 | 샘플에서 의미 있는 비트의 개수. |
| sRGB 색 공간 | 국제 색상 컨소시엄이 정의한 렌더링 인텐트와, 이미지 샘플이 해당 색 공간에 부합함을 나타내는 표시. |
| 권장 팔레트 | 디스플레이 장치가 이미지의 전체 색상 범위를 표시할 수 없을 때 사용할 수 있는 축약 팔레트. |
| 텍스트 데이터 | 이미지와 연관된 텍스트 정보(압축될 수 있음). |
| 시간 | PNG 이미지가 마지막으로 수정된 시간. |
| 투명도 | PNG 이미지에 알파 채널이 유지되지 않는 경우에도 참조 이미지를 재구성할 수 있게 하는 알파 정보. |
PNG 데이터스트림은 PNG 시그니처(참조: 5.2 PNG 시그니처) 다음에 청크 시퀀스가 이어집니다(참조: 11. 청크 명세). 각 청크에는 그 기능을 지정하는 청크 타입이 있습니다.
청크 유형은 ISO 646.IRV:1991 [ISO646] 문자 집합으로 해석할 때 읽을 수 있는 레이블에 대응하도록 선택된 4바이트 시퀀스입니다. 처음 네 개는 필수(critical) 청크로, 이 명세서의 규정에 따라 이해되고 올바르게 해석되어야 합니다. 다음과 같습니다:
나머지 청크 유형은 인코더가 생성할 수 있고 디코더가 해석할 수 있는 보조 청크 유형이라 합니다.
애니메이션 PNG(APNG)는 원래의 정적 전용 PNG 형식을 확장하여, 프레임 기반 애니메이션 이미지를 지원합니다. 이는 전통적으로 GIF 형식[GIF]을 사용하던 단순 애니메이션 이미지의 대체를 목적으로 하며, GIF에 없는 24비트 이미지와 8비트 투명성 지원을 추가합니다.
APNG는 이전 버전의 PNG와 하위 호환됩니다. 비(非)애니메이션 PNG 디코더는 보조 APNG 전용 청크를 무시하고 정적 이미지를 표시합니다.
APNG 스트림은 이전 PNG 명세에서 정의된 일반 PNG 스트림에, 애니메이션을 설명하고 추가 프레임 데이터를 제공하는 세 가지 청크 유형이 추가된 것입니다.
APNG로 인식되려면, 스트림에서 어떤 IDAT 청크보다 먼저 acTL 청크가 나타나야 합니다. acTL 구조는 아래에 설명되어 있습니다.
개념적으로, 각 재생 시작 시 출력 버퍼는 완전히 투명한 검정 사각형으로 완전히 초기화되어야 하며, 그 너비와 높이는 IHDR 청크의 값에서 가져옵니다.
단일 fcTL 청크가 IDAT 이전에 존재하면, 정적 이미지는 애니메이션의 첫 번째 프레임으로 포함될 수 있습니다. 그렇지 않으면 정적 이미지는 애니메이션의 일부가 아닙니다.
이후 프레임은 fdAT 청크에 인코딩되며, 이는 IDAT 청크와 동일한 구조지만 앞에 시퀀스 번호가 추가됩니다. 각 프레임의 배치 및 렌더링에 대한 정보는 fcTL 청크에 저장됩니다. fdAT 및 fcTL 청크의 전체 레이아웃은 아래에 설명되어 있습니다.
기본 이미지가 애니메이션의 일부인지 여부와 관계없이, 전체 애니메이션의 경계는 IHDR 청크의 너비와 높이 매개변수로 지정됩니다. 이후 프레임을 위해 추가 공간이 필요하다면, 기본 이미지는 완전히 투명한 검정 픽셀로 적절히 패딩되어야 합니다.
각 프레임은 각 재생마다 동일하므로, 애플리케이션이 프레임을 캐시해도 안전합니다.
fcTL 및 fdAT 청크에는 0부터 시작하는 4바이트 시퀀스 번호가 있습니다. 두 청크 유형은 동일한 시퀀스를 공유합니다. 이 번호의 목적은, 이 명세서가 보조 청크에 대한 순서 제한을 부과하지 않기 때문에, 애니메이션 PNG에서 시퀀스 오류를 감지(및 선택적으로 수정)하는 것입니다.
첫 번째 fcTL 청크는 시퀀스 번호 0을 가져야 하며, 나머지 fcTL 및 fdAT 청크의 시퀀스 번호는 누락이나 중복 없이 오름차순이어야 합니다.
아래 표는 두 개 이상의 프레임이 있는 이미지 및 두 번째 프레임에 대해 두 개 이상의 fdAT 청크가 있는 경우의 시퀀스 번호 사용 예를 보여줍니다. (명확성을 위해 IHDR 및 IEND 청크는 생략되었습니다.)
| 시퀀스 번호 | 청크 |
|---|---|
| (없음) | acTL |
| 0 | fcTL 첫 번째 프레임 |
| (없음) | IDAT 첫 번째 프레임 / 정적 이미지 |
| 1 | fcTL 두 번째 프레임 |
| 2 | 두 번째 프레임의 첫 번째 fdAT |
| 3 | 두 번째 프레임의 두 번째 fdAT |
| 시퀀스 번호 | 청크 |
|---|---|
| (없음) | acTL |
| (없음) | IDAT 정적 이미지 |
| 0 | fcTL 첫 번째 프레임 |
| 1 | 첫 번째 프레임의 첫 번째 fdAT |
| 2 | 첫 번째 프레임의 두 번째 fdAT |
| 3 | fcTL 두 번째 프레임 |
| 4 | 두 번째 프레임의 첫 번째 fdAT |
| 5 | 두 번째 프레임의 두 번째 fdAT |
출력 버퍼는 PNG IHDR 청크의 너비와 높이 매개변수로 지정된 크기의 픽셀 배열입니다. 개념적으로, 각 프레임은 캔버스에 합성되기 전에 출력 버퍼에서 구성됩니다. 출력 버퍼의 내용은 디코더에서 접근할 수 있습니다. 출력 버퍼의 모서리는 캔버스의 모서리에 매핑됩니다.
캔버스는 프레임이 표시될 출력 장치의 영역입니다. 캔버스의 내용은 디코더에서 반드시 접근 가능하지는 않습니다. bKGD 청크가 존재하면, 더 적합한 배경이 없는 경우 캔버스를 채우는 데 사용할 수 있습니다.
PNG 데이터스트림의 오류는 일반적으로 두 가지 범주로 나뉩니다:
PNG 디코더는 가능한 한 빨리 오류를 감지하고, 가능한 경우 오류로부터 복구하며, 그렇지 못할 경우에도 우아하게 실패해야 합니다. 오류 처리 철학은 13.1 오류 처리에 자세히 설명되어 있습니다.
이 절은 비규범적입니다.
PNG 형식은 여러 확장 지점을 노출합니다:
이 확장 지점 중 일부는 W3C에 의해 예약되어 있으며, 다른 일부는 비공개 용도로 사용 가능합니다.
PNG 데이터스트림은 PNG 시그니처에 이어 청크들의 시퀀스로 구성됩니다. 이는 PNG 이미지를 인코딩한 결과입니다.
"파일"이 아닌 데이터스트림이라는 용어를 사용하는 이유는, 바이트 시퀀스가 파일의 일부에 불과할 수도 있음을 설명하기 위함입니다. 또한 바이트 시퀀스가 저장된 파일에 전혀 나타나지 않고, "온더플라이"로 생성 및 소비될 수 있음을 강조하기 위함이기도 합니다.
PNG 데이터스트림의 처음 8바이트는 항상 다음의 16진수 값을 포함합니다:
89 50 4E 47 0D 0A 1A 0A
이 시그니처는 이어지는 데이터스트림이 단일 PNG 이미지(즉, IHDR 청크로 시작하여 IEND 청크로 끝나는 일련의 청크)임을 나타냅니다.
이 시그니처는 PNG 데이터스트림을 다른 유형의 데이터스트림과 구분하며, 일부 전송 오류를 조기에 탐지할 수 있게 합니다.
각 청크는 세 개 또는 네 개의 필드로 구성됩니다(참조: Figure 10). 각 필드의 의미는 Table 5에 설명되어 있습니다. 청크 데이터 필드는 비어 있을 수도 있습니다.
| 이름 | 설명 |
|---|---|
| Length | 청크의 데이터 필드에 포함된 바이트 수를 나타내는 PNG 4바이트 부호 없는 정수. 길이는 데이터 필드만 계산하며, 길이 필드 자체, 청크 타입, CRC는 포함하지 않습니다. 0도 유효한 길이입니다. 인코더와 디코더는 길이를 부호 없는 값으로 취급해야 하지만, 그 값은 231-1 바이트를 초과해서는 안 됩니다. |
| Chunk Type |
청크 타입을 정의하는 4바이트 시퀀스입니다. 청크 타입의 각 바이트는 16진수 값 41~5A 및 61~7A로 제한됩니다. 이는 설명과 데이터스트림 검토의 편의를 위해
각각 ISO 646 [ISO646]의
대문자와 소문자
문자(A-Z, a-z)에 해당합니다. 인코더와 디코더는 청크 타입을
문자열이 아닌 고정된 바이너리 값으로 취급해야 합니다. 예를 들어, 청크 타입 IDAT을 UCS 2
문자 집합의 해당 문자로 표현하는 것은 올바르지 않습니다. 청크 타입에 대한 추가 명명 규칙은
5.4 청크 명명
규칙에서 논의됩니다.
|
| Chunk Data | 해당 청크 타입에 적합한 데이터 바이트(있을 경우). 이 필드는 길이가 0일 수도 있습니다. |
| CRC | 청크 타입 필드와 청크 데이터 필드를 포함하되 길이 필드는 제외한, 청크 내 앞선 바이트들에 대해 계산된 4바이트 CRC입니다. CRC는 데이터 손상 여부를 확인하는 데 사용할 수 있습니다. 데이터가 없는 청크에도 CRC는 항상 존재합니다. 참조: 5.5 CRC 알고리즘. |
청크 데이터 길이는 최대치까지 임의의 바이트 수가 될 수 있으므로, 구현자는 청크가 바이트보다 큰 경계에 정렬되어 있다고 가정할 수 없습니다.
청크 타입은 그 바이트들을 ISO 646 문자 [ISO646]로 해석했을 때 의미 있는 이름이 되도록 선택됩니다. 청크 타입은 디코더가 해당 타입을 인식하지 못하더라도 청크의 몇 가지 속성을 파악할 수 있도록 할당됩니다. 이러한 규칙은 PNG 디코더가 알려지지 않은 청크를 만났을 때 수행할 동작을 결정할 수 있게 해, PNG 형식의 안전하고 유연한 확장을 가능하게 합니다.
명명 규칙은 보통 13. PNG 디코더 및 뷰어에서 지정한 대로 디코더가 청크 타입을 인식하지 못하는 경우에만 관심 대상이 됩니다.
각 바이트의 5비트(값 32)인 속성 비트, 즉 청크 타입 각 바이트의 5번째 비트가 청크 속성을 전달하는 데 사용됩니다. 이 선택으로 인해, 사람이 청크 타입 각 바이트에 해당하는 문자가 대문자(비트 5가 0)인지 소문자(비트 5가 1)인지에 따라 부여된 속성을 읽어낼 수 있습니다.
속성 비트는 청크 타입의 고유한 일부이며, 따라서 어떤 청크 타입에도 고정됩니다. 그러므로 CHNK와 cHNk는 동일한 청크의 다른 속성이 아니라, 서로 관련 없는 청크 타입입니다.
속성 비트의 의미는 Table 6에 정의되어 있습니다.
| 이름 및 위치 | 정의 | 설명 |
|---|---|---|
| 보조 비트: 첫 번째 바이트 | 0(대문자) = 필수, 1(소문자) = 보조. |
필수 청크는 데이터스트림 내용(예: 이미지 헤더 청크(IHDR))을 성공적으로 표시하는 데
필요합니다.
디코더가 이미지를 추출하려 할 때 보조 비트가 0인 알 수 없는 청크 타입을 만나면, 해당 이미지는 안전하게 해석할 수 없는 정보를 포함하고 있음을 사용자에게 알려야
합니다. 보조 청크는 데이터스트림의 내용을 의미 있게 표시하는 데 반드시 필요하지는 않습니다(예: 시간 청크(tIME)). 보조 비트가 1인 알 수 없는 청크 타입을 만난 디코더는 해당 청크를 안전하게 무시하고 이미지를 계속 표시할 수 있습니다. |
| 프라이빗 비트: 두 번째 바이트 | 0(대문자) = 공용, 1(소문자) = 비공개. |
공용 청크는 W3C가 정의를 위해 예약해 둡니다. 비공개 청크의 정의는 12.10.1 비공개 청크 사용에 규정되어 있습니다. 비공개 청크 이름의 두 번째 글자는 소문자이며, 공용 청크 이름의 두 번째 글자는 대문자입니다. |
| 예약 비트: 세 번째 바이트 | 이 PNG 버전에서는 0(대문자). 예약 비트가 1이면, 해당 데이터스트림은 이 PNG 버전에 부합하지 않습니다. |
청크 이름의 세 번째 글자 대소문자의 의미는 향후 확장을 위해 예약되어 있습니다. 이 국제 표준에서는 모든 청크 이름의 세 번째 글자는 대문자여야 합니다. |
| 복사 안전 비트: 네 번째 바이트 | 0(대문자) = 복사 비안전, 1(소문자) = 복사 안전. |
이 속성 비트는 순수 디코더에는 중요하지 않지만, PNG 에디터에는 필요합니다. 이 비트는 수정 중인 데이터스트림에서 인식되지 않은 청크의 적절한 처리 방식을 정의합니다. PNG 에디터에 대한 규칙은 14.2 PNG 에디터의 동작에서 더 다룹니다. |
가상의 청크 타입 "cHNk"의 속성 비트는 다음과 같습니다:
cHNk <-- 32 bit chunk type represented in text form
||||
|||+- Safe-to-copy bit is 1 (lower case letter; bit 5 is 1)
||+-- Reserved bit is 0 (upper case letter; bit 5 is 0)
|+--- Private bit is 0 (upper case letter; bit 5 is 0)
+---- Ancillary bit is 1 (lower case letter; bit 5 is 1)
따라서, 이 이름은 보조·공용·복사 안전 청크를 의미합니다.
CRC 필드는 [ISO-3309] 및 [ITU-T-V.42]에서 정의한 바와 같이 사전/사후 컨디셔닝을 포함한 표준화된 CRC 방법으로 계산됩니다. 사용되는 CRC 다항식은 GZIP 파일 형식 명세 [RFC1952]과 동일합니다:
x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
PNG에서 32비트 CRC는 모든 비트를 1로 초기화한 후,
각 바이트의 데이터가 최하위 비트(1)에서 최상위 비트(128) 순으로 처리됩니다. 모든 데이터 바이트 처리 후 CRC는 보수(1의 보수)가 취해져 반전됩니다. 이 값은 MSB 우선으로 전송(데이터스트림에 저장)됩니다. 바이트 분리와 순서를 위해,
32비트 CRC의 최하위 비트는 x31 항의 계수로 정의됩니다.
CRC의 실용적인 계산은 연산을 가속하기 위해 미리 계산된 테이블을 사용하는 경우가 많습니다. 참조: D. 샘플 CRC 구현.
개별 청크의 배치 제약은 Table 7에 나열되어 있으며, 정적 이미지의 경우 Figure 11 및 Figure 12에 도식화되어 있습니다. 정적 이미지가 첫 번째 프레임을 구성하는 애니메이션 이미지의 경우 Figure 13 및 Figure 14, 정적 이미지가 애니메이션의 일부가 아닌 경우 Figure 15 및 Figure 16에 도식화되어 있습니다. 이러한 격자 다이어그램은 본 명세가 부과하는 배치 제약을 나타냅니다. 다이어그램의 선은 부분 순서 관계를 정의합니다. 더 위에 있는 청크는 더 아래 청크보다 먼저 나타나야 합니다. 수평으로 정렬되어 있고 두 다른 청크 타입(수직으로 위/아래)에 사이에 나타나는 청크들은, 연결된 더 위/아래 청크 타입 사이에서 어떤 순서로든 나타날 수 있습니다. 청크 타입에 붙은 첨자는 Table 8에 정의되어 있으며, 청크가 필수인지, 선택 사항인지, 여러 번 나타날 수 있는지를 나타냅니다. 두 청크 타입 사이의 세로 막대(|)는 대안을 의미합니다.
| 필수 청크 (이 순서로 나타나야 하며, 단 PLTE는 선택 사항) |
||
|---|---|---|
| 청크 이름 | 중복 허용 | 순서 제약 |
| IHDR | No | 처음에 와야 함 |
| PLTE | No | 첫 번째 IDAT 이전 |
| IDAT | Yes | 여러 IDAT 청크는 연속해야 함 |
| IEND | No | 마지막에 와야 함 |
| 보조 청크 (이 순서일 필요는 없음) |
||
| 청크 이름 | 중복 허용 | 순서 제약 |
| acTL | No | IDAT 이전 |
| cHRM | No | PLTE 및 IDAT 이전 |
| cICP | No | PLTE 및 IDAT 이전 |
| gAMA | No | PLTE 및 IDAT 이전 |
| iCCP | No | PLTE 및 IDAT 이전. iCCP 청크가 존재하면, sRGB 청크는 존재하지 않아야 합니다. |
| mDCV | No | PLTE 및 IDAT 이전. |
| cLLI | No | PLTE 및 IDAT 이전. |
| sBIT | No | PLTE 및 IDAT 이전 |
| sRGB | No | PLTE 및 IDAT 이전. sRGB 청크가 존재하면, iCCP 청크는 존재하지 않아야 합니다. |
| bKGD | No | PLTE 이후; IDAT 이전 |
| hIST | No | PLTE 이후; IDAT 이전 |
| tRNS | No | PLTE 이후; IDAT 이전 |
| eXIf | No | IDAT 이전 |
| fcTL | Yes | 하나는 IDAT 이전에 나타날 수 있으며; 나머지는 모두 IDAT 이후여야 함 |
| pHYs | No | IDAT 이전 |
| sPLT | Yes | IDAT 이전 |
| fdAT | Yes | IDAT 이후 |
| tIME | No | None |
| iTXt | Yes | None |
| tEXt | Yes | None |
| zTXt | Yes | None |
| 기호 | 의미 |
|---|---|
| + | 하나 이상 |
| 1 | 하나만 |
| ? | 0개 또는 1개 |
| * | 0개 이상 |
| | | 대안 |
모든 청크(비공개 및 공용)는 [PNG-EXTENSIONS]에 목록화되어야(SHOULD) 합니다.
공용 청크는 W3C가 정의를 위해 예약합니다.
공용 청크는 PNG의 철학에 부합하는 폭넓은 사용을 의도합니다.
조직과 애플리케이션은 위 기준을 충족하는 어떤 청크든 PNG 워킹 그룹에 공용 청크로 정의하도록 제출할 것을 권장합니다.
공용 청크로의 정의는 자동도, 즉시도 아닙니다. 제안된 공용 청크 타입은 그렇게 정의될 때까지 공개적으로 이용 가능한 소프트웨어나 데이터스트림에서 사용되어서는(SHALL not) 안 됩니다.
새로운 필수(critical) 청크 타입의 정의는 필요한 경우가 아니면 지양됩니다.
조직과 애플리케이션은 비공개 및 실험적 사용을 위해 비공개 청크를 정의할 수(MAY) 있습니다.
비공개 청크는 사람 사용자에게 흥미로운 텍스트 정보를 담기 위해서만 정의되어서는(SHOULD NOT) 안 됩니다. 대신 iTXt 청크를 사용해야(SHOULD BE) 하며, 해당 키워드를 사용해야(SHOULD BE) 하고 적절한 키워드를 정의해야 합니다.
비공개 청크를 [PNG-EXTENSIONS]에 등재하면, 서로 다른 애플리케이션이 동일한 비공개 청크를 호환되지 않는 목적으로 사용하는 가능성을 줄일 수 있으나, 완전히 없애지는 못합니다. 비공개 청크 타입을 사용하는 경우, 충돌 위험을 더 줄이기 위해 추가 식별 정보를 청크 데이터의 시작 부분에 저장해야(SHOULD BE) 합니다.
이미지 표시가 절대적으로 필수적이지 않은 정보를 저장하는 모든 비공개 청크에는 필수 청크 타입이 아닌 보조 청크 타입을 사용해야(SHOULD) 합니다.
비공개 필수 청크는 정의되어서는(SHOULD NOT) 안 되며, 이러한 청크를 포함하는 PNG 데이터스트림은 이식성이 없고, 공개 소프트웨어나 데이터스트림에서 사용되어서도(SHOULD NOT) 안 됩니다. 비공개 필수 청크가 어떤 애플리케이션에 필수적이라면, 표준 디코더가 데이터스트림을 처리할 수 없음을 빨리 파악할 수 있도록, 데이터스트림의 시작 부분 근처에 나타나야(SHOULD) 합니다.
비공개 청크 정의에 대한 추가 지침은 B. 비공개 청크 유형 가이드라인을 참조하십시오.
다음 필드에서 128 이상인 값은 비공개 필드 값입니다:
이러한 비공개 필드 값은 이 명세에 의해 정의되거나 예약되지 않습니다.
비공개 필드 값은 실험적 또는 비공개 의미에 사용할 수(MAY) 있습니다.
비공개 필드 값은 공개적으로 이용 가능한 소프트웨어나 데이터스트림에 나타나지 않아야(SHOULD NOT) 하며, 이는 13. PNG 디코더 및 뷰어에 자세한 바와 같이 PNG 디코더가 읽을 수 없는 데이터스트림을 초래할 수 있기 때문입니다.
4.5 PNG 이미지에서 설명한 바와 같이 PNG 이미지는 다섯 가지 유형이 있습니다. 각 유형에 대응하는 색상 타입은 다음 값의 합입니다: 1(팔레트 사용), 2(트루컬러 사용), 4(알파 사용). 그레이스케일과 트루컬러 이미지는 명시적인 알파 채널을 가질 수 있습니다. PNG 이미지 유형과 해당 색상 타입은 Table 9에 나열되어 있습니다.
| PNG 이미지 유형 | 색상 타입 |
|---|---|
| 그레이스케일 | 0 |
| 트루컬러 | 2 |
| 인덱스 컬러 | 3 |
| 그레이스케일(알파 포함) | 4 |
| 트루컬러(알파 포함) | 6 |
각 PNG 이미지 유형에 대해 허용되는 비트 깊이와 샘플 비트 깊이는 이미지 헤더에 나와 있습니다.
전달 곡선이 표시된 경우(gAMA, sRGB, iCCP 또는 cICP) 그레이스케일 샘플은 휘도를 나타내며, 그렇지 않으면 장치 의존적 그레이스케일을 의미합니다. 색 공간이 표시된 경우(gAMA 및 cHRM, sRGB, iCCP, 또는 cICP) RGB 샘플은 보정된 색상 정보를 나타내며, 그렇지 않으면 보정되지 않은 장치 의존적 색상을 나타냅니다.
샘플 값은 반드시 광 강도에 비례하는 것은 아닙니다. gAMA 청크는 샘플 값과 디스플레이 출력 강도 간의 관계를 지정합니다. 뷰어는 올바르게 보정할 것을 강력히 권장합니다. 4.3 색 공간, 13.13 디코더 감마 처리, C. 감마와 색도를 참조하세요.
PNG 데이터스트림에서 투명성은 PNG 이미지 유형에 따라 네 가지 방법 중 하나로 표현될 수 있습니다(4.4.1 알파 분리 및 4.4.4 알파 압축 참조).
이미지 배열에 포함된 알파 채널은 다른 샘플과 같은 크기인 8비트 또는 16비트 샘플을 가집니다. 각 픽셀의 알파 샘플은 해당 픽셀의 그레이스케일 또는 RGB 샘플 바로 뒤에 저장됩니다. 알파 값 0은 완전 투명, 값 2sampledepth - 1은 완전 불투명을 나타냅니다. 중간 값은 배경 이미지에 합성되어 전달 이미지를 생성할 수 있는 부분 투명 픽셀을 의미합니다.
픽셀의 색상 값은 해당 픽셀에 할당된 알파 값으로 사전 곱셈(premultiplied)되지 않습니다. 이 규칙은 때때로 "unassociated" 또는 "non-premultiplied" 알파라고도 합니다. (다른 일반적인 기법은 샘플 값을 알파 값으로 사전 곱하여 저장하는 것으로, 사실상 이러한 이미지는 이미 검은 배경에 합성된 것입니다. PNG는 사전 곱셈 알파를 사용하지 않습니다. 그 결과 이미지 에디터는 PNG 이미지의 투명도를 쉽게 변경할 수 있습니다.) 12.3 알파 채널 생성 및 13.16 알파 채널 처리를 참조하세요.
두 바이트 이상이 필요한 모든 정수는 네트워크 바이트 순서(Figure 17에 예시됨)여야 합니다. 가장 의미 있는 바이트가 먼저 오고, 그 다음 의미가 낮은 바이트들이 중요도 내림차순으로 옵니다(2바이트 정수의 경우 MSB LSB, 4바이트 정수의 경우 MSB B2 B1 LSB). 바이트의 최상위 비트(값 128)는 비트 7로, 최하위 비트(값 1)는 비트 0으로 번호가 매겨집니다. 달리 명시되지 않는 한 값은 부호 없는 값입니다. 부호 있는 것으로 명시된 값은 2의 보수 표기로 표현됩니다.
PNG 4바이트 부호 없는 정수는 부호 없는 4바이트 값을 다루기 어려운 언어를 고려하여 0에서 231-1 범위로 제한됩니다.
PNG 이미지(또는 패스, 8. 인터레이싱 및 패스 추출 참조)는 직사각형 픽셀 배열이며, 각 스캔라인 내 픽셀은 왼쪽에서 오른쪽으로, 스캔라인은 위에서 아래로 나타납니다. 각 픽셀의 크기는 픽셀당 비트 수에 의해 결정됩니다.
스캔라인 내 픽셀은 항상 픽셀 사이에 낭비되는 비트 없이 바이트 시퀀스로 포장됩니다. 스캔라인은 항상 바이트 경계에서 시작합니다. 허용되는 비트 깊이와 색상 타입은 모든 경우에 포장이 단순하고 효율적이도록 제한됩니다.
색상 타입 0(그레이스케일)의 PNG 이미지에서 각 픽셀은 단일 샘플이며, 바이트보다 작은 정밀도(1, 2, 또는 4비트)를 가질 수 있습니다. 이러한 샘플은 바이트의 상위 비트부터 스캔라인의 다른 샘플들이 뒤따르는 방식으로 바이트에 포장됩니다.
색상 타입 3(인덱스 컬러)의 PNG 이미지에서 각 픽셀은 단일 팔레트 인덱스입니다. 이러한 인덱스는 색상 타입 0의 샘플과 동일한 방식으로 바이트에 포장됩니다.
바이트당 여러 픽셀이 있는 경우, 스캔라인의 마지막 바이트의 일부 하위 비트는 사용되지 않을 수 있습니다. 이러한 미사용 비트의 내용은 정의되지 않습니다.
인덱스 컬러가 아닌 PNG 이미지에서는 샘플 비트 깊이가 16일 수 있습니다. 이러한 샘플 값은 네트워크 바이트 순서(MSB 먼저, LSB 다음)로 저장됩니다. PNG는 다중 샘플 픽셀을 8비트와 16비트 샘플에서만 허용하므로, 한 픽셀의 여러 샘플이 한 바이트에 포장되는 일은 없습니다.
필터 방식은 스캔라인 배열에 적용되어 압축 가능성을 향상시키기 위한 변환입니다.
PNG는 압축을 준비하기 위해 사용할 수 있는 하나의 필터 방식과 여러 필터 타입을 표준화합니다. 이 방식은 바이트 시퀀스를 동등한 길이의 바이트 시퀀스로 변환하되 앞에 필터 타입 바이트를 붙입니다(예시는 Figure 18 참조).
인코더는 인터레이스 PNG 이미지에 대해 단 하나의 필터 방식만 사용해야 하며, 축소 이미지의 각 스캔라인마다 서로 다른 필터 타입을 사용할 수 있습니다. 지능적인 인코더는 스캔라인마다 필터를 전환할 수 있습니다. 어떤 필터를 사용할지 선택하는 방법은 인코더에 맡깁니다.
필터 타입 바이트는 이미지 데이터의 일부로 간주되지 않지만, 압축 단계로 전송되는 데이터스트림에 포함됩니다. 9. 필터링을 참조하세요.
패스 추출(Figure 4.8 참조)은 PNG 이미지를 일련의 축소 이미지(인터레이스 PNG 이미지)로 분할합니다. 첫 번째 이미지는 거친 보기를 정의하고, 이후의 이미지는 마지막 이미지가 PNG 이미지를 완성할 때까지 이 거친 보기를 점차 향상시킵니다. 이는 디코더가 인터레이스 PNG 이미지를 점진적으로 표시할 수 있게 하며, 이미지가 실시간으로 표시될 때 "페이드 인"되도록 합니다. 평균적으로 인터레이싱은 데이터스트림 크기를 약간 증가시키지만, 사용자에게 훨씬 더 빠르게 의미 있는 표시를 제공할 수 있습니다.
이 국제 표준에는 두 가지 인터레이스 방식, 방식 0과 1이 정의됩니다. 다른 값의 인터레이스 방식은 향후 표준화를 위해 예약되어 있습니다.
인터레이스 방식 0(널 방식)에서는 픽셀이 왼쪽에서 오른쪽으로, 스캔라인이 위에서 아래로 순차적으로 추출됩니다. 인터레이스 PNG 이미지는 단일 축소 이미지입니다.
인터레이스 방식 1(Adam7)은 이미지에 대해 서로 다른 일곱 개의 패스를 정의합니다. 각 패스는 참조 이미지의 픽셀 하위집합을 전송합니다. 각 픽셀이 전송되는 패스(1에서 7까지 번호)는 왼쪽 상단 모서리에서 시작하여 다음 8×8 패턴을 전체 이미지에 반복하여 정의됩니다:
1 6 4 6 2 6 4 6
7 7 7 7 7 7 7 7
5 6 5 6 5 6 5 6
7 7 7 7 7 7 7 7
3 6 4 6 3 6 4 6
7 7 7 7 7 7 7 7
5 6 5 6 5 6 5 6
7 7 7 7 7 7 7 7
Figure 4.8은 인터레이스 방식 1의 일곱 패스를 보여줍니다. 각 패스 내에서 선택된 픽셀은 스캔라인 내에서 왼쪽에서 오른쪽으로, 선택된 스캔라인은 위에서 아래로 순차적으로 전송됩니다. 예를 들어, 패스 2는 스캔라인 0, 8, 16, …의 픽셀 4, 12, 20, …을 포함합니다(스캔라인 0, 픽셀 0이 좌상단). 마지막 패스는 스캔라인 1, 3, 5, … 전체를 포함합니다. 전송 순서는 한 패스에서 전송되는 모든 스캔라인이 동일한 픽셀 수를 갖도록 정의되며, 이는 일부 필터를 올바르게 적용하는 데 필요합니다. 인터레이스 PNG 이미지는 일곱 개의 축소 이미지 시퀀스로 구성됩니다. 예를 들어 PNG 이미지가 16×16 픽셀이라면, 세 번째 패스는 각 네 픽셀을 포함하는 두 개의 스캔라인으로 이루어진 축소 이미지가 됩니다(Figure 4.8 참조).
정수 바이트 수를 완전히 채우지 못하는 스캔라인은 7.2 스캔라인에 정의된 대로 패딩됩니다.
참조 이미지의 열이 5 미만이거나 행이 5 미만인 경우, 일부 패스는 비어 있을 수 있습니다.
필터링은 압축 향상을 목표로 PNG 이미지를 변환합니다. 전체 흐름은 Figure 7에, 스캔라인 직렬화와 필터링의 세부는 Figure 18에 나타나 있습니다.
PNG는 여러 필터 방식을 허용합니다. 인터레이스 이미지의 모든 축소 이미지는 단일 필터 방식을 사용해야 합니다. 이 명세에서 정의된 것은 필터 방식 0뿐입니다. 다른 필터 방식은 향후 표준화를 위해 예약됩니다. 필터 방식 0은 다섯 가지 필터 타입을 제공하며, 각 축소 이미지의 스캔라인은 서로 다른 필터 타입을 사용할 수 있습니다.
PNG는 인터레이스 PNG 이미지에 적용할 수 있는 필터 타입에 추가 제약을 두지 않습니다. 그러나 필터 타입은 모든 데이터 유형에서 동일하게 효과적이지는 않습니다. 12.7 필터 선택을 참조하세요.
필터링은 스캔라인의 바이트 시퀀스를 동일 길이의 바이트 시퀀스로 변환하되, 앞에 필터 타입을 붙입니다. 필터 타입 바이트는 비어 있지 않은 스캔라인에만 연결되며, 비어 있는 패스에는 필터 타입 바이트가 없습니다. 13.10 인터레이싱 및 점진적 표시를 참조하세요.
이미지의 비트 깊이나 색상 타입과 무관하게 필터는 픽셀이 아니라 바이트에 적용됩니다. 필터는 7.2 스캔라인에 설명된 대로 표현된 스캔라인의 바이트 시퀀스에서 동작합니다. 이미지에 알파 채널이 포함된 경우, 알파 데이터는 이미지 데이터와 동일한 방식으로 필터링됩니다.
필터는 새로운 바이트 값을 생성하기 위해 다음 바이트들의 원래 값을 사용할 수 있습니다:
| 이름 | 정의 |
|---|---|
| x | 필터링 중인 바이트; |
| a | x가 포함된 픽셀의 바로 이전 픽셀에서 x에 해당하는 바이트(또는 비트 깊이가 8 미만일 때는 x 바로 이전 바이트); |
| b | 이전 스캔라인에서 x에 해당하는 바이트; |
| c | b가 포함된 픽셀의 바로 이전 픽셀에서 b에 해당하는 바이트(또는 비트 깊이가 8 미만일 때는 b 바로 이전 바이트). |
Figure 19는 바이트 x, a, b, c의 상대적 위치를 보여줍니다.
필터 방식 0은 Table 11에 나열된 다섯 가지
기본 필터 타입을 정의합니다. Orig(y)는 바이트 y의 원래(필터 적용 전) 값을, Filt(y)는 필터 타입 적용
후의 값을, Recon(y)는 대응하는 재구성 함수를 적용한 후의 값을 나타냅니다. Paeth 필터 타입의 PaethPredictor
[Paeth]는 아래에
정의되어 있습니다.
필터 방식 0은 정확히 이 다섯 가지 필터 타입 집합만을 지정하며, 이는 확장되어서는 안 됩니다. 이는 디코더가 데이터에 지원되지 않는 필터 타입이 포함되는지 확인하기 위해 압축을 해제할 필요가 없도록 보장합니다. 11.2.1 IHDR 이미지 헤더의 필터 방식을 확인하는 것만으로 충분합니다.
| 타입 | 이름 | 필터 함수 | 재구성 함수 |
|---|---|---|---|
| 0 | None | Filt(x) = Orig(x)
|
Recon(x) = Filt(x)
|
| 1 | Sub | Filt(x) = Orig(x) - Orig(a)
|
Recon(x) = Filt(x) + Recon(a)
|
| 2 | Up | Filt(x) = Orig(x) - Orig(b)
|
Recon(x) = Filt(x) + Recon(b)
|
| 3 | Average | Filt(x) = Orig(x) - floor((Orig(a) + Orig(b)) / 2)
|
Recon(x) = Filt(x) + floor((Recon(a) + Recon(b)) / 2)
|
| 4 | Paeth | Filt(x) = Orig(x) - PaethPredictor(Orig(a), Orig(b), Orig(c))
|
Recon(x) = Filt(x) + PaethPredictor(Recon(a), Recon(b), Recon(c))
|
모든 필터에서, 스캔라인의 첫 픽셀 "왼쪽"의 바이트는 0으로 간주해야 합니다. 이전 스캔라인을 참조하는 필터의 경우, 축소 이미지의 첫 스캔라인에 대해서는 이전 스캔라인 전체와 첫 픽셀 "왼쪽"의 바이트들이 모두 0으로 간주되어야 합니다.
필터의 효과를 되돌리기 위해서는 같은 스캔라인의 이전 픽셀에 대한 디코딩 값, 이전 스캔라인에서 현재 픽셀 바로 위 픽셀의 값, 그리고 그 위 픽셀의 왼쪽 픽셀의 값이 필요합니다.
입출력이 모두 바이트에 맞도록 256을 법으로 하는 부호 없는 산술을 사용합니다. 필터는 비트 깊이와 무관하게 각 바이트에 적용됩니다. Filt 값들의 시퀀스가
필터링된 스캔라인으로 전송됩니다.
Orig(a) + Orig(b)의 합은 오버플로 없이(최소 9비트 산술을 사용하여) 수행되어야 합니다. floor()는 나눗셈의 결과가
유리수일 경우 아래쪽 정수로 내림된다는 것을 나타내며, 즉 정수 나눗셈 또는 오른쪽 시프트 연산입니다.
Paeth 필터 타입은 세 이웃 픽셀(왼쪽, 위, 좌상단)의 단순 선형 함수를 계산한 다음, 계산된 값에 가장 가까운 이웃 픽셀을 예측값으로 선택합니다. 이 명세에서 사용되는 알고리즘은 Alan W. Paeth의 기법을 변형한 것입니다 [Paeth].
PaethPredictor 함수는 아래 코드에서 정의됩니다. 함수의 논리와 바이트 a, b, c, x의 위치는 Figure 20에 나타나 있습니다. Pr은 바이트 x의 예측값입니다.
p = a + b - c
pa = abs(p - a)
pb = abs(p - b)
pc = abs(p - c)
if pa <= pb and pa <= pc then Pr = a
else if pb <= pc then Pr = b
else Pr = c
return Pr
PaethPredictor 함수 내 계산은 오버플로 없이 정확하게 수행되어야 합니다.
비교가 수행되는 순서는 매우 중요하며 변경되어서는 안 됩니다. 이 함수는 세 방향(수직, 수평, 대각선) 중 어느 방향으로 이미지의 기울기가 가장 작은지를 판단하려고 시도합니다.
완전히 동일한 PaethPredictor 함수가 인코더와 디코더 모두에서 사용됩니다.
이 국제 표준에서는 PNG 압축 방식 0만 정의됩니다. 다른 값의 압축 방식은 향후 표준화를 위해 예약되어 있습니다. PNG 압축 방식 0은 최대 32768 바이트의 슬라이딩 윈도우(이는 deflate 스트림에 나타나는 거리의 상한)와 함께 사용하는 deflate 압축입니다. Deflate 압축은 LZ77에서 파생되었습니다.
Deflate로 압축된 PNG 내부 데이터스트림은 zlib 형식으로 저장되며, 구조는 다음과 같습니다:
| zlib 압축 방식/플래그 코드 | 1 바이트 |
| 추가 플래그/검사 비트 | 1 바이트 |
| 압축 데이터 블록 | n 바이트 |
| 검사 값 | 4 바이트 |
PNG 압축 방식 0의 경우, zlib 압축 방식/플래그 코드는 방식 코드 8(deflate 압축)과 32768 바이트를 넘지 않는 LZ77 윈도우 크기를 지정해야 합니다. zlib의 압축 방식 번호는 IHDR 청크의 PNG 압축 방식 번호와 동일하지 않습니다. 추가 플래그에는 프리셋 사전이 지정되지 않아야 합니다.
압축할 데이터가 16384 바이트 이하이면, PNG 인코더는 윈도우 크기를 2의 거듭제곱(최소 256)으로 올림하여 설정할 수 있습니다. 이는 압축률에 나쁜 영향을 주지 않으면서 인코딩과 디코딩 모두에 필요한 메모리를 줄여줍니다.
zlib 데이터스트림 내부의 압축 데이터는 일련의 블록으로 저장되며, 각 블록은 원시(비압축) 데이터, 고정 허프만 코드로 인코딩된 LZ77 압축 데이터, 또는 사용자 정의 허프만 코드로 인코딩된 LZ77 압축 데이터 중 하나를 나타낼 수 있습니다. 마지막 블록의 마커 비트는 그것이 최종 블록임을 식별하여, 디코더가 압축 데이터스트림의 끝을 인식할 수 있게 합니다. 압축 알고리즘과 인코딩에 대한 자세한 내용은 deflate 명세 [rfc1951]에 나와 있습니다.
zlib 데이터스트림 끝에 저장되는 검사 값은 그 데이터스트림이 나타내는 비압축 데이터에 대해 계산됩니다. 이를 계산하는 알고리즘은 PNG 청크의 CRC 필드 값에 사용되는 CRC 계산과 동일하지 않습니다. zlib 검사 값은 주로 deflate 알고리즘이 올바르게 구현되었는지 교차 확인하는 데 유용합니다. 개별 PNG 청크의 CRC를 검증하면 PNG 데이터스트림이 손상 없이 전송되었음을 확인할 수 있습니다.
필터링된 스캔라인의 시퀀스를 압축하고, 결과 데이터 스트림을 IDAT 청크로 분할합니다. 모든 IDAT 청크의 내용들을 연결하면 하나의 zlib 데이터스트림을 이루게 됩니다. 이 데이터스트림을 압축 해제하면 필터링된 이미지 데이터가 됩니다.
IDAT 청크 간 경계는 임의적이며 zlib 데이터스트림의 어느 위치에든 놓일 수 있음을 강조하는 것이 중요합니다. IDAT 청크 경계와 deflate 블록 경계 또는 zlib 데이터의 다른 요소들 사이에는 반드시 상관관계가 있는 것은 아닙니다. 예를 들어, 마지막의 zlib 검사 값이 IDAT 청크 간에 분할되어 있을 수도 있습니다.
마찬가지로, 이미지 데이터의 구조(예: 스캔라인 경계)와 deflate 블록 경계 또는 IDAT 청크 경계 사이에도 요구되는 상관관계는 없습니다. 완전한 필터링 PNG 이미지는 여러 개의 IDAT 청크에 저장된 하나의 zlib 데이터스트림으로 표현됩니다.
PNG는 iTXt, iCCP, 그리고 zTXt 청크에서도 압축 방식 0을 사용합니다. 이미지 데이터와 달리 이러한 데이터스트림은 청크 간에 분할되지 않습니다. 각 청크는 독립적인 하나의 zlib 데이터스트림을 포함합니다(10.1 압축 방식 0 참조).
이 절에서는 본 명세에서 사용되는 청크를 정의합니다.
필수 청크(critical chunk)는 PNG 데이터스트림에서 PNG 이미지를 성공적으로 디코드하는 데 절대적으로 필요한 청크입니다. 확장 청크는 필수 청크로 정의될 수 있습니다(14. 에디터 참조)지만, 이 관행은 강력히 권장되지 않습니다.
유효한 PNG 데이터스트림은 PNG 시그니처로 시작하여 즉시 IHDR 청크가 뒤따르고, 그 다음 하나 이상의 IDAT 청크가 있으며, IEND 청크로 끝나야 합니다. PNG 데이터스트림에는 IHDR 청크와 IEND 청크가 각각 하나만 허용됩니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다.
49 48 44 52
IHDR 청크는 PNG 데이터스트림에서 첫 번째 청크여야 합니다. 이 청크에는 다음이 포함됩니다:
| Width | 4 바이트 |
| Height | 4 바이트 |
| Bit depth | 1 바이트 |
| Color type | 1 바이트 |
| Compression method | 1 바이트 |
| Filter method | 1 바이트 |
| Interlace method | 1 바이트 |
Width와 Height는 픽셀 단위의 이미지 크기를 나타냅니다. 이 값들은 PNG 4바이트 부호 없는 정수입니다. 0은 유효하지 않은 값입니다.
비트 깊이는 각 샘플 또는 팔레트 인덱스(픽셀당이 아님)의 비트 수를 나타내는 1바이트 정수입니다. 유효한 값은 1, 2, 4, 8, 16이지만, 모든 값이 모든 색상 타입에서 허용되는 것은 아닙니다. 6.1 색상 타입 및 값을 참조하세요.
색상 타입은 1바이트 정수입니다.
각 색상 타입에 대한 비트 깊이 제한은 구현을 단순화하고 압축 효율이 좋지 않은 조합을 금지하기 위해 부과됩니다. 허용되는 조합은 Table 12에 정의되어 있습니다.
| PNG 이미지 유형 | 색상 타입 | 허용 비트 깊이 | 해석 |
|---|---|---|---|
| 그레이스케일 | 0 | 1, 2, 4, 8, 16 | 각 픽셀은 그레이스케일 샘플 |
| 트루컬러 | 2 | 8, 16 | 각 픽셀은 R,G,B 삼중항 |
| 인덱스 컬러 | 3 | 1, 2, 4, 8 | 각 픽셀은 팔레트 인덱스이며, PLTE 청크가 나타나야 함 |
| 그레이스케일(알파 포함) | 4 | 8, 16 | 각 픽셀은 그레이스케일 샘플 뒤에 알파 샘플 |
| 트루컬러(알파 포함) | 6 | 8, 16 | 각 픽셀은 R,G,B 삼중항 뒤에 알파 샘플 |
샘플 비트 깊이는 인덱스 컬러 PNG 이미지(색상 타입 3)의 경우를 제외하면 비트 깊이와 동일합니다. 인덱스 컬러의 경우 샘플 비트 깊이는 항상 8비트입니다(4.5 PNG 이미지 참조).
압축 방식은 이미지 데이터를 압축할 때 사용된 방식을 나타내는 1바이트 정수입니다. 본 명세에서는 방식 0(deflate, 최대 32768 바이트의 슬라이딩 윈도우)만 정의됩니다. 모든 적합 PNG 이미지는 이 방식으로 압축되어야 합니다.
필터 방식은 압축 전에 이미지 데이터에 적용된 전처리 방식을 나타내는 1바이트 정수입니다. 본 명세에서는 필터 방식 0(5가지 기본 필터 타입을 사용하는 적응형 필터링)만 정의됩니다. 자세한 내용은 9. 필터링을 참조하세요.
인터레이스 방식은 이미지 데이터의 전송 순서를 나타내는 1바이트 정수입니다. 본 명세에서는 두 값이 정의됩니다: 0(인터레이스 없음), 1(Adam7 인터레이스). 자세한 내용은 8. 인터레이싱 및 패스 추출을 참조하세요.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다.
50 4C 54 45
PLTE 청크에는 1개에서 256개까지의 팔레트 항목이 포함되며, 각 항목은 다음 형태의 3바이트 시리즈입니다:
| Red | 1 바이트 |
| Green | 1 바이트 |
| Blue | 1 바이트 |
항목 수는 청크 길이에서 결정됩니다. 청크 길이가 3으로 나누어떨어지지 않으면 오류입니다.
이 청크는 색상 타입 3의 경우 나타나야 하며, 색상 타입 2와 6의 경우 나타날 수 있습니다. 색상 타입 0과 4에서는 나타나면 안 됩니다. PLTE 청크는 하나를 초과할 수 없습니다.
색상 타입 3(인덱스 컬러)의 경우, PLTE 청크가 필요합니다. PLTE의 첫 번째 항목은 픽셀 값 0이, 두 번째는 픽셀 값 1이 참조합니다. 팔레트 항목 수는 이미지 비트 깊이로 표현 가능한 범위를 초과해서는 안 됩니다(예: 비트 깊이 4라면 24 = 16). 비트 깊이가 허용하는 것보다 적은 항목 수를 가질 수는 있습니다. 그런 경우, 이미지 데이터에서 범위를 벗어난 픽셀 값이 발견되면 오류입니다.
색상 타입 2와 6(트루컬러와 트루컬러(알파 포함))의 경우, PLTE 청크는 선택 사항입니다. 존재하는 경우, 직접 표시할 수 없을 때 트루컬러 이미지를 양자화할 때 사용할 1~256개의 권장 색상 집합을 제공합니다. 그러나 이 목적에는 sPLT 청크를 사용하는 것이 PLTE 청크를 사용하는 것보다 권장됩니다. PLTE 청크와 sPLT 청크가 모두 없고 이미지를 직접 표시할 수 없다면, 양자화는 뷰잉 시스템에서 수행해야 합니다. 하지만 색상 선택은 종종 PNG 인코더가 한 번 수행하는 것이 바람직합니다(12.5 권장 팔레트 참조).
팔레트는 이미지 비트 깊이와 상관없이 샘플당 8비트(1 바이트)를 사용한다는 점에 주의하세요. 특히, 팔레트는 16비트 트루컬러 이미지의 권장 양자화일 때도 8비트 깊이입니다.
팔레트 항목이 모두 이미지에서 사용되어야 한다는 요구 사항은 없으며, 모두 달라야 한다는 요구 사항도 없습니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다.
49 44 41 54
IDAT 청크에는 압축 알고리즘의 출력 스트림인 실제 이미지 데이터가 들어 있습니다. 자세한 내용은 9. 필터링 및 10. 압축을 참조하세요.
IDAT 청크는 여러 개 있을 수 있으며, 이 경우 다른 청크가 사이에 끼지 않고 연속해서 나타나야 합니다. 압축 데이터스트림은 모든 IDAT 청크의 데이터 필드 내용들을 연결한 것입니다(데이터 필드가 길이 0일 수 있음에 유의).
일부 이미지에서는 마지막 IDAT 청크의 끝에 사용되지 않은 후행 바이트가 존재합니다. 이는 사용된 버퍼의 일부만이 아니라 전체 버퍼가 저장될 때 발생할 수 있습니다. 바람직하지 않은 동작입니다. 가능하면 인코더는 이러한 미사용 바이트를 포함하지 않는 것이 좋습니다. 만약 포함해야 한다면, 바이트를 0으로 설정하면 우발적인 데이터 공유를 방지할 수 있습니다. 디코더는 이러한 후행 바이트를 무시해야 합니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다.
49 45 4E 44
IEND 청크는 PNG 데이터스트림의 끝을 나타냅니다. 이 청크의 데이터 필드는 비어 있습니다.
이 명세에서 정의된 보조 청크는 4.8.2 청크 유형에 나열된 순서대로 정리되어 있습니다. 이는 PNG 데이터스트림에 나타나는 실제 순서와는 다릅니다. 보조 청크는 디코더가 무시할 수 있습니다. 각 보조 청크에 대해, 아래에 서술된 동작은 디코더가 해당 청크를 무시하지 않는다는 가정 하에서 기술됩니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
74 52 4E 53
tRNS 청크는 팔레트 항목과 연관된 알파 값(인덱스 컬러 이미지의 경우) 또는 단일 투명 색상(그레이스케일 및 트루컬러 이미지의 경우)을 지정합니다. tRNS 청크에는 다음이 포함됩니다:
| 색상 타입 0 | |
|---|---|
| 그레이 샘플 값 | 2 바이트 |
| 색상 타입 2 | |
| 빨강 샘플 값 | 2 바이트 |
| 초록 샘플 값 | 2 바이트 |
| 파랑 샘플 값 | 2 바이트 |
| 색상 타입 3 | |
| 팔레트 인덱스 0의 알파 | 1 바이트 |
| 팔레트 인덱스 1의 알파 | 1 바이트 |
| ...등등... | 1 바이트 |
색상 타입 3(인덱스 컬러)의 경우, tRNS 청크에는 PLTE 청크의 항목에 대응하는 1바이트 알파 값의 시퀀스가 들어 있습니다. 각 항목은 해당 팔레트 인덱스의 픽셀을 지정된 알파 값으로 취급해야 함을 나타냅니다. 알파 값의 해석은 8비트 완전 알파 채널과 동일합니다: 0은 완전 투명, 255는 완전 불투명이며, 이는 이미지 비트 깊이와 무관합니다. tRNS 청크는 팔레트 항목 수보다 많은 알파 값을 포함해서는 안 되지만, 팔레트 항목 수보다 적은 값을 포함할 수는 있습니다. 이 경우 나머지 팔레트 항목의 알파 값은 255로 간주합니다. 일반적으로 팔레트 인덱스 0만 투명해야 하는 경우에는 1바이트짜리 tRNS 청크면 충분하며, 모든 팔레트 인덱스가 불투명한 경우에는 tRNS 청크를 생략할 수 있습니다.
색상 타입 0 또는 2의 경우, 이미지 비트 깊이와 관계없이 샘플당 2바이트를 사용합니다(7.1 정수와 바이트 순서 참조). 지정된 그레이 샘플 값 또는 RGB 샘플 값과 일치하는 픽셀은 투명(알파 값 0과 동등)으로 취급되며; 그 외 모든 픽셀은 완전 불투명(알파 값 2bitdepth-1)으로 취급됩니다. 이미지 비트 깊이가 16보다 작으면 하위 유효 비트만 사용됩니다. 인코더는 나머지 비트를 0으로 설정해야 하며, 디코더는 값을 사용하기 전에 나머지 비트를 0으로 마스킹해야 합니다.
tRNS 청크는 이미 완전한 알파 채널이 존재하는 색상 타입 4 및 6에 대해서는 나타나면 안 됩니다.
참고 16비트 그레이스케일 또는 트루컬러 데이터의 경우, 13.12 샘플 비트 깊이 재스케일링에 설명된 바와 같이, tRNS 청크에서 전체 16비트 값이 정확히 일치하는 픽셀만 투명합니다. 디코더는 투명성 테스트가 끝날 때까지 샘플 비트 깊이 재스케일링을 지연해야 합니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
63 48 52 4D
cHRM 청크는 PNG 이미지에서 사용된 디스플레이 기본색(빨강, 초록, 파랑)의 1931 CIE x,y 색도와 참조 화이트 포인트를 지정하는 데 사용할 수 있습니다. 자세한 내용은 C. 감마와 색도를 참조하십시오. iCCP 및 sRGB 청크는 색 관리와 제어에 대해 더 정교한 지원을 제공합니다.
cHRM 청크에는 다음이 포함됩니다:
| 이름 | 크기 |
|---|---|
| 화이트 포인트 x | 4 바이트 |
| 화이트 포인트 y | 4 바이트 |
| Red x | 4 바이트 |
| Red y | 4 바이트 |
| Green x | 4 바이트 |
| Green y | 4 바이트 |
| Blue x | 4 바이트 |
| Blue y | 4 바이트 |
각 값은 PNG 4바이트 부호 없는 정수로 인코딩되며, x 또는 y 값에 100000을 곱한 값을 나타냅니다.
예: 0.3127은 정수 31270으로 저장됩니다.
cHRM 청크는 모든 PNG 데이터스트림에서 허용되지만, 그레이스케일 이미지에서는 유용성이 낮습니다.
이 청크는 디코더가 이해하는 최우선 색상 청크가 아닌 경우 무시됩니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
67 41 4D 41
실제로 원하는 디스플레이 출력 강도를 지정하는 것만으로는 충분하지 않습니다. 또한 출력이 원하는 시청 조건을 지정할 필요가 있습니다. gAMA에 대해서는 sRGB 명세의 기준 시청 조건을 사용합니다 [SRGB]. 서로 다른 시청 조건에 대한 보정은 일반적으로 색 관리 시스템이 처리합니다. 보정이 수행되지 않더라도 오차는 보통 작습니다. 높은 색 충실도를 원하는 애플리케이션은 sRGB 또는 iCCP 청크 사용을 고려할 수 있습니다.
gAMA 청크에는 다음이 포함됩니다:
| 이미지 감마 | 4 바이트 |
값은 PNG 4바이트 부호 없는 정수로 인코딩되며, 감마 값에 100000을 곱한 값을 나타냅니다.
감마 값 1/2.2는 정수 45455로 저장됩니다.
12.1 인코더 감마 처리와 13.13 디코더 감마 처리를 참조하십시오.
이 청크는 디코더가 이해하는 최우선 색상 청크가 아닌 경우 무시됩니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
69 43 43 50
iCCP 청크에는 다음이 포함됩니다:
| 프로파일 이름 | 1-79 바이트(문자열) |
| 널 구분자 | 1 바이트(널 문자) |
| 압축 방식 | 1 바이트 |
| 압축된 프로파일 | n 바이트 |
프로파일 이름은 프로파일을 지칭하기 위한 임의의 편리한 이름일 수 있습니다. 대소문자를 구분합니다. 프로파일 이름에는 출력 가능한 Latin-1 문자와 공백만 포함되어야 합니다(코드 포인트 0x20-7E 및 0xA1-FF만 허용). 앞/뒤/연속된 공백은 허용되지 않습니다. 이 명세에서 정의된 유일한 압축 방식은 방식 0(zlib 데이터스트림 + deflate 압축, 10.3 압축의 기타 사용 참조)입니다. 압축 방식 뒤에는 청크의 나머지를 구성하는 압축된 프로파일이 옵니다. 이 데이터스트림을 압축 해제하면 내장 ICC 프로파일이 생성됩니다.
iCCP 청크가 존재하는 경우, 이미지 샘플은 국제 색상 컨소시엄이 정의한 내장 ICC 프로파일이 나타내는 색 공간을 준수합니다 [ICC][ISO_15076-1]. ICC 프로파일의 색 공간은 컬러 이미지(색상 타입 2, 3, 6)에서는 RGB 색 공간이어야 하며, 그레이스케일 이미지(색상 타입 0, 4)에서는 그레이스케일 색 공간이어야 합니다. iCCP 청크를 기록하는 PNG 인코더는, iCCP 청크를 사용하지 않는 애플리케이션과의 호환성을 위해, ICC 프로파일을 근사하는 gAMA 및 cHRM 청크도 함께 기록하는 것이 권장됩니다.
이 청크는 디코더가 이해하는 최우선 색상 청크가 아닌 경우 무시됩니다.
cICP 청크가 존재하지 않는 한, PNG 데이터스트림은 iCCP로 명시적으로 지정하든 sRGB 청크로 암묵적으로 지정하든 내장 프로파일을 최대 하나만 포함해야 합니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
73 42 49 54
디코더를 단순화하기 위해, PNG는 특정 샘플 비트 깊이만 사용하도록 규정하고, 추가로 샘플 값이 해당 비트 깊이에서 가능한 전체 범위로 스케일되어야 한다고 규정합니다. sBIT 청크는 원래의 유의 비트 수(샘플 비트 깊이 이하일 수 있음)를 정의합니다. 이는 데이터의 샘플 비트 깊이가 PNG에서 직접 지원하지 않는 경우라도 PNG 디코더가 원본 데이터를 무손실로 복원할 수 있게 합니다.
sBIT 청크에는 다음이 포함됩니다:
| 색상 타입 0 | |
|---|---|
| 그레이스케일 유의 비트 | 1 바이트 |
| 색상 타입 2 및 3 | |
| 빨강 유의 비트 | 1 바이트 |
| 초록 유의 비트 | 1 바이트 |
| 파랑 유의 비트 | 1 바이트 |
| 색상 타입 4 | |
| 그레이스케일 유의 비트 | 1 바이트 |
| 알파 유의 비트 | 1 바이트 |
| 색상 타입 6 | |
| 빨강 유의 비트 | 1 바이트 |
| 초록 유의 비트 | 1 바이트 |
| 파랑 유의 비트 | 1 바이트 |
| 알파 유의 비트 | 1 바이트 |
sBIT에서 지정되는 각 비트 깊이는 0보다 커야 하고 해당 샘플 비트 깊이 이하이어야 합니다(인덱스 컬러 이미지에서는 8, 그 외 색상 타입에서는 IHDR에 지정된 비트 깊이). sBIT는 tRNS 청크로 암시되는 알파 채널의 샘플 비트 깊이를 제공하지 않는다는 점에 유의하십시오; 이 경우 알파 채널의 모든 샘플 비트는 유의하다고 간주해야 합니다. sBIT 청크가 없는 경우, 모든 채널의 모든 샘플 비트는 유의하다고 간주합니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
73 52 47 42
sRGB 청크가 존재하면, 이미지 샘플은 sRGB 색 공간을 준수해야 하며 [SRGB] 국제 색상 컨소시엄이 정의한 지정된 렌더링 인텐트를 사용하여 표시되어야 합니다 [ICC] 또는 [ICC-2].
sRGB 청크에는 다음이 포함됩니다:
| 이름 | 크기 |
|---|---|
| 렌더링 인텐트 | 1 바이트 |
렌더링 인텐트에 대해 다음 값이 정의됩니다:
| 값 | 이름 | 설명 |
|---|---|---|
| 0 | Perceptual | 사진과 같이 색도 정확도를 일부 희생하더라도 출력 장치 색역에 잘 적응하는 것이 중요한 이미지에 적합 |
| 1 | Relative colorimetric | 로고와 같이 출력 장치의 화이트 포인트에 상대적인 색 외관 매칭이 필요한 이미지에 적합 |
| 2 | Saturation | 도표/그래프와 같이 색상과 명도의 일부를 희생하더라도 채도를 보존하는 것이 중요한 이미지에 적합 |
| 3 | Absolute colorimetric | 다른 출력 장치를 대상으로 하는 이미지(교정 인쇄물 등)의 사전보기처럼 절대 색도 보존이 필요한 이미지에 적합 |
PNG 인코더가 sRGB 청크를 기록하는 경우, gAMA 청크(및 선택적으로 cHRM 청크)를 함께 기록하는 것이 권장됩니다. 이는 sRGB 청크를 사용하지 않는 디코더와의 호환성을 위한 것입니다. 사용해야 하는 값은 다음만 허용됩니다.
| gAMA | |
|---|---|
| 감마 | 45455 |
| cHRM | |
| 화이트 포인트 x | 31270 |
| 화이트 포인트 y | 32900 |
| Red x | 64000 |
| Red y | 33000 |
| Green x | 30000 |
| Green y | 60000 |
| Blue x | 15000 |
| Blue y | 6000 |
이 청크는 디코더가 이해하는 최우선 색상 청크가 아닌 경우 무시됩니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
63 49 43 50
존재하는 경우, cICP 청크는 [ITU-T-H.273]에 지정된 코드 포인트를 사용하여 이미지의 색 공간(프라이머리), 전달 함수, 매트릭스 계수 및 스케일링 팩터를 지정합니다. 비디오 포맷 시그널링은 디코더나 렌더링 등 이미지 처리 시에 사용되는 것이 바람직합니다(SHOULD).
cICP 청크는 위 특성을 식별하는 네 개의 1바이트 부호 없는 정수로 구성됩니다.
cICP 청크의 문법은 다음과 같습니다:
| 이름 | 크기 |
|---|---|
| Color Primaries | 1 바이트 |
| Transfer Function | 1 바이트 |
| Matrix Coefficients | 1 바이트 |
| Video Full Range Flag | 1 바이트 |
cICP 청크의 각 필드는 [ITU-T-H.273]의 동일 명칭 파라미터에 대응합니다.
현재 PNG에서 지원되는 유일한 색 모델은 RGB이므로,
Matrix Coefficients는 0으로 설정해야 합니다.
Video Full Range Flag가 0
(즉, 내로우 레인지 이미지)인 경우,
권장 관행은 EOTF 또는
역 OETF와 같은
전달 함수를 확장 범위(음수 포함)까지 정의하는 것입니다.
이는 다음과 같이 수행됩니다:
out = sign(in) * TransferFunction(abs(in))
cICP 청크는 PLTE 및 IDAT 청크보다 앞서 와야 합니다(MUST).
이 청크가 디코더에 의해 이해된다면, 최우선 색상 청크입니다.
sRGB 이미지를 간결하게 신호화하기 위해 sRGB 청크를 사용하는 방식과 유사하게, cICP를 사용하여 Display P3 이미지를 간결하게 신호화할 수 있습니다 [Display-P3].
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
6D 44 43 56
존재하는 경우, mDCV 청크는 콘텐츠 제작 시점에 사용된 마스터링 디스플레이 색상 볼륨(mDCV)을 [SMPTE-ST-2086]에 따라 특성화합니다. mDCV 청크는 정적 메타데이터를 제공하여 대상(소비자) 디스플레이가 자신의 고유 능력과 원래 마스터링 디스플레이의 능력을 비교하여 톤 매핑 결정을 최적화할 수 있도록 합니다.
mDCV는 일반적으로 PQ [ITU-R-BT.2100] 전달 함수 및 추가 cLLI 메타데이터와 함께 사용되며, 흔히 [HDR10] (PQ + ST 2086 정적 메타데이터, MaxFALL, MaxCLL)로 불립니다. mDCV 청크는 HLG [ITU-R-BT.2100] 및 SDR 이미지 형식(예: [ITU-R-BT.709])에도 포함될 수 있습니다.
mDCV는 원래 비디오 디스플레이 대상에서의 이미지 톤 매핑을 최적화하기 위한 보조 정적 메타데이터로 만들어졌기 때문에, 이미지 콘텐츠의 기본 특성을 확립하기 위해 mDCV 사용 시에는 cICP 청크가 함께 있어야 합니다. 색 프라이머리와 화이트 포인트 특성은 cICP 청크 형식에서 도출할 수 있습니다. HDR [ITU-R-BT.2100] 및 SDR [ITU-R-BT.709] 이미지를 사용하는 가장 일반적인 사용 사례의 구체적인 예는 [ITU-T-Series-H-Supplement-19]에서 확인할 수 있습니다. 기본(cICP) 특성 + 보조(mDCV) 정적 메타데이터는 톤 매핑 결정을 최적화하는 데 유용한 정보를 제공할 수 있습니다.
Issue #319는 mDCV 청크가 존재할 때의 톤 매핑 동작을 논의합니다.
SDR 이미지의 경우, mDCV 디스플레이 최소/최대 휘도를 알 수 없으면, [ITU-T-Series-H-Supplement-19]의 표 11 값 또는 관련 SDR 명세에서 기본 특성을 도출할 수 있습니다. 현재로서는 SDR 이미지 신호를 기본 시청 조건(디스플레이 휘도와 주변 조명)에서 mDCV 청크로 신호화된 조건으로 변환하는 표준화된 방법은 공개되어 있지 않습니다.
mDCV 청크의 문법은 다음과 같습니다:
| 이름 | 크기 | 나눗값(divisor) |
|---|---|---|
| 마스터링 디스플레이 색상 기본 색도(CIE 1931 x,y of R,G,B ) | 12 바이트 | 0.00002 |
| 마스터링 디스플레이 화이트 포인트 색도(CIE 1931 x,y) | 4 바이트 | 0.00002 |
| 마스터링 디스플레이 최대 휘도(cd/m2) | 4 바이트 | 0.0001 |
| 마스터링 디스플레이 최소 휘도(cd/m2) | 4 바이트 | 0.0001 |
색 프라이머리는 세 쌍의 PNG 2바이트 부호 없는 정수로 인코딩되며, 순서는 x 다음 y이고, 각 값은 x 또는 y 기본 색도 값을 나눗값으로 나눈 값을 나타냅니다. 정렬은 x 색도가 가장 큰 프라이머리, 그 다음 y 색도가 가장 큰 프라이머리, 그 다음 나머지 프라이머리 순으로 합니다. RGB 색 공간의 경우 이는 R, G, B 순서에 해당합니다.
화이트 포인트는 PNG 2바이트 부호 없는 정수 한 쌍으로 인코딩되며, 순서는 x 다음 y이고, 각 값은 화이트 색도의 x 또는 y 값을 나눗값으로 나눈 값을 나타냅니다.
최대/최소 휘도 값은 PNG 4바이트 부호 없는 정수로 인코딩되며, cd/m2의 절대 휘도 값을 나눗값으로 나눈 값을 나타냅니다.
나눗값은 실제 값에서 저장 값으로의 변환에 사용됩니다. 예를 들어, 프라이머리와 화이트 포인트에 대한 0.00002라는 무단위 나눗값은 (0.6800, 0.3200) 색도를 {34000, 16000}으로 저장합니다.
mDCV 청크는 PLTE 및 IDAT 청크보다 앞서 와야 합니다(MUST).
아래는 [ITU-R-BT.2100] HDR용 mDCV 예시입니다.
아래는 [Display-P3] SDR용 mDCV 예시입니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
63 4C 4C 49
존재하는 경우, cLLI 청크는 HDR 콘텐츠의 두 가지 특성을 식별합니다:
cLLI 청크는 정적 메타데이터를 추가하여, 관련 콘텐츠의 톤 매핑을 특정 대상 디스플레이에 최적화할 기회를 제공합니다. 이는 콘텐츠 자체의 톤 매핑을 대상 디스플레이의 최대 밝기 능력에 맞추어 클리핑을 방지하도록 조정함으로써 이루어집니다. 현재 톤 매핑 최적화 방법은 주관적입니다.
MaxCLL(최대 콘텐츠 광도)은 전체 재생 시퀀스에서 단일 픽셀의 최대 광도(cd/m2, nits라고도 함)를 나타내기 위해 정적 메타데이터 값을 사용합니다. 의도하지 않은 다운스트림 톤 매핑에 영향을 줄 수 있는 처리가공이나 노이즈로 인한 잘못된 값을 제거하기 위해 종종 알고리즘 필터가 사용됩니다.
MaxFALL(최대 프레임 평균 광도)은 전체 재생 시퀀스에서 프레임 평균 광도(cd/m2, nits)의 최대 값을 나타내기 위해 정적 메타데이터 값을 사용합니다. MaxFALL은 먼저 각 프레임에서 모든 픽셀의 디코딩된 휘도 값을 평균내고, 그 중 가장 큰 값을 가지는 프레임의 값을 사용하는 방식으로 계산됩니다.
MaxCLL 및 MaxFALL 값은 PNG 4바이트 부호 없는 정수로 인코딩됩니다.
[CTA-861.3-A] 는 cLLI 값을 생성하기 위한 계산 방법을 설명하지만, 필터링에 대해서는 지정하지 않습니다. [HDR-Static-Meta] 는 통계적 이상치, 노이즈, 리샘플링 필터의 링잉 등으로 인한 극단값을 배제하는 개선된 방법을 설명하며, 실제 구현에 권장됩니다.
[SMPTE-ST-2067-21] 7.5절은 cLLI 값을 알 수 없거나 아직 계산되지 않은 경우에 대한 추가 정보를 제공합니다.
Issue #319는 cLLI 청크가 존재할 때의 톤 매핑 동작을 논의합니다.
각 프레임이 분석됩니다.
MaxCLL 또는 MaxFALL 값이 0이면, 해당 값이 알려지지 않았거나 현재 계산할 수 없음을 의미합니다.
이 값을 계산할 수 없는 예로는 실시간 애니메이티드 PNG 스트림을 생성하는 경우가 있습니다. 스트림이 끝날 때까지 모든 프레임이 가용하지 않아 값을 계산할 수 없습니다. 인코더는 초기에는 0 값을 사용하고 스트림 종료 시 계산된 값으로 교체할 수 있습니다.
cLLI 청크의 문법은 다음과 같습니다:
| 이름 | 크기 | 나눗값(divisor) |
|---|---|---|
| Maximum Content Light Level (MaxCLL) | 4 바이트 | 0.0001 cd/m2 |
| Maximum Frame-Average Light Level (MaxFALL) | 4 바이트 | 0.0001 cd/m2 |
PNG는 이미지 설명 또는 저작권 고지와 같은 이미지에 연관된 텍스트 문자열을 저장하기 위해 tEXt, iTXt, 및 zTXt 청크를 제공합니다. 키워드는 각 텍스트 문자열이 무엇을 나타내는지 표시하는 데 사용됩니다. 이러한 텍스트 청크는 원하는 만큼 나타날 수 있으며, 동일한 키워드를 가진 청크가 여러 개 있어도 허용됩니다.
다음 키워드는 미리 정의되어 있으며 적절한 경우 사용되어야 합니다.
| 키워드 값 | 설명 |
|---|---|
| Title | 이미지의 짧은(한 줄) 제목 또는 캡션 |
| Author | 이미지 작성자 이름 |
| Description | 이미지 설명(길 수 있음) |
| Copyright | 저작권 고지 |
| Creation Time | 원본 이미지 생성 시각 |
| Software | 이미지 생성에 사용된 소프트웨어 |
| Disclaimer | 법적 면책 문구 |
| Warning | 내용의 성격에 대한 경고 |
| Source | 이미지 생성에 사용된 장치 |
| Comment | 기타 코멘트 |
| XML:com.adobe.xmp | Extensible Metadata Platform (XMP) 정보로, XMP 명세가 요구하는 형식으로 포맷됩니다 [XMP]. XMP 호환을 위해서는 Compression Flag를 0으로 설정하고 Language Tag 및 Translated Keyword를 널 문자열로 설정한 상태의 iTXt 사용이 권장됩니다. |
| Collection | 이미지가 속한 컬렉션의 이름. 이미지 하나가 하나 이상의 컬렉션에 속할 수 있으며, 각 컬렉션은 별도의 텍스트 청크로 명명됩니다. |
다른 키워드는 사적 또는 일반적 관심을 위해 어떤 애플리케이션에 의해서든 정의될 수 있습니다(MAY).
키워드는 SHOULD 다음과 같아야 합니다.
일반적 관심을 가지는 키워드는 [PNG-EXTENSIONS]에 등재되어야 합니다(SHOULD).
키워드는 출력 가능한 Latin-1 [ISO_8859-1] 문자 및 공백만 포함해야 합니다; 즉 코드 포인트 0x20-7E 및 0xA1-FF만 허용됩니다. 사람의 오독 가능성을 줄이기 위해 키워드에는 선행 공백, 후행 공백 및 연속 공백을 허용하지 않으며, 시각적으로 일반 공백과 구분되지 않는 U+00A0 NON-BREAKING SPACE도 허용하지 않습니다.
키워드는 등록된 대로 정확히 철자되어야 하며, 디코더가 특정 키워드를 찾을 때 단순한 리터럴 비교를 사용할 수 있어야 합니다. 특히 키워드는 대소문자를 구분합니다. 키워드 길이는 1에서 79바이트로 제한됩니다.
Creation Time 키워드의 경우, 날짜 형식은 RFC 3339 [rfc3339] 날짜-시간 형식 또는 RFC 1123의 섹션 5.2.14에 정의된 날짜 형식 중 하나여야 합니다(SHOULD). RFC3339 날짜-시간 형식이 선호됩니다. 이 필드의 실제 형식은 정의되어 있지 않습니다.
iTXt 청크는 UTF-8 인코딩 [rfc3629]을 사용하며, 모든 언어의 문자를 전달하는 데 사용할 수 있습니다. iTXt 청크에는 텍스트 문자열을 압축할 수 있는 옵션이 있습니다. 유니코드를 지원하므로 모든 텍스트 문자열에 대해 iTXt 사용이 권장됩니다. 또한 내용이 출력 가능한 Latin-1 문자 집합과 U+000A LINE FEED(LF)으로 제한되는 tEXt 및 zTXt 청크도 있습니다. zTXt의 텍스트 문자열은 zlib 데이터스트림으로 압축되며 deflate 압축을 사용합니다(자세한 내용은 10.3 Other uses of compression 참조).
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
74 45 58 74
각 tEXt 청크는 키워드와 텍스트 문자열을 다음 형식으로 포함합니다:
| Keyword | 1-79 바이트 (문자열) |
| Null separator | 1 바이트 (널 문자) |
| Text string | 0 또는 그 이상의 바이트 (문자열) |
키워드와 텍스트 문자열은 0 바이트(널 문자)로 구분됩니다. 키워드나 텍스트 문자열 어느 쪽에도 널 문자를 포함할 수 없습니다. 텍스트 문자열은 널로 종료되지 않습니다(청크 길이가 종료를 정의함). 텍스트 문자열의 길이는 0바이트부터 키워드와 널 문자 구분자 길이를 뺀 최대 허용 청크 크기까지 가능합니다.
키워드는 11.3.3.1 Keywords and text strings에 기술된 대로 텍스트 문자열이 나타내는 정보의 유형을 가리킵니다.
텍스트는 Latin-1 문자 집합에 따라 해석됩니다 [ISO_8859-1]. 텍스트 문자열은 어떤 Latin-1 문자도 포함할 수 있습니다. 텍스트 문자열의 줄바꿈은 단일 라인피드 문자(십진수 10)로 표시해야 합니다. Latin-1과 라인피드 문자를 제외한 문자는 tEXt 청크에서 정의된 의미가 없습니다. ISO/IEC 8859-1 범위를 벗어나는 문자를 포함한 텍스트는 iTXt 청크를 사용해 인코딩해야 합니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
7A 54 58 74
zTXt 청크와 tEXt 청크는 의미적으로 동일하지만, 큰 텍스트 블록을 저장할 때는 zTXt 청크를 권장합니다.
zTXt 청크는 다음을 포함합니다:
| Keyword | 1-79 바이트 (문자열) |
| Null separator | 1 바이트 (널 문자) |
| Compression method | 1 바이트 |
| Compressed text datastream | n 바이트 |
키워드와 널 문자는 tEXt 청크와 동일합니다. 키워드는 압축되지 않습니다. 압축 방식 항목은 사용된 압축 방식을 정의합니다. 이 국제 표준에서 정의된 유일한 값은 0(deflate 압축)입니다. 다른 값은 향후 표준화를 위해 예약되어 있습니다. 압축 방식 항목 다음에는 청크의 나머지를 구성하는 압축된 텍스트 데이터스트림이 옵니다. 방식 0의 경우 이 데이터스트림은 zlib 데이터스트림이며 deflate 압축을 사용합니다(자세한 내용은 10.3 Other uses of compression 참조). 이 데이터스트림을 압축 해제하면 동등한 tEXt 청크에 저장되었을 텍스트와 동일한 Latin-1 텍스트가 생성됩니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
69 54 58 74
각 iTXt 청크는 다음을 포함합니다:
| Keyword | 1-79 바이트 (문자열) |
| Null separator | 1 바이트 (널 문자) |
| Compression flag | 1 바이트 |
| Compression method | 1 바이트 |
| Language tag | 0 또는 그 이상의 바이트 (문자열) |
| Null separator | 1 바이트 (널 문자) |
| Translated keyword | 0 또는 그 이상의 바이트 |
| Null separator | 1 바이트 (널 문자) |
| Text | 0 또는 그 이상의 바이트 |
키워드는 11.3.3.1 Keywords and text strings에 설명되어 있습니다.
Compression flag는 비압축 텍스트의 경우 0, 압축 텍스트의 경우 1입니다. 오직 text 필드만 압축될 수 있습니다. 압축 방식 항목은 사용된 압축 방법을 정의합니다. 이 명세에서 정의된 유일한 압축 방식은 0(zlib 데이터스트림 + deflate 압축)입니다(자세한 내용은 10.3 Other uses of compression 참조). 비압축 텍스트의 경우 인코더는 압축 방식을 0으로 설정해야 하고 디코더는 이를 무시해야 합니다.
Language tag는 [BCP47]에 의해 정의된 잘-형성된 언어 태그입니다. 키워드와 달리
language tag는 대소문자를 구분하지 않습니다. 하위 태그는 IANA 언어 하위 태그 레지스트리에 나타나야 합니다. 언어 태그가 비어 있으면 언어가 지정되지 않은
것입니다. 언어 태그의 예로는 en, en-GB, es-419, zh-Hans,
zh-Hans-CN, tlh-Cyrl-AQ, ar-AE-u-nu-latn, 및
x-private 등이 있습니다.
Translated keyword와 text는 모두 UTF-8 인코딩을 사용하며 [rfc3629] 이며, 둘 다 널 바이트(널 문자)를 포함해서는 안 됩니다. 이 청크의 다른 텍스트 데이터와 달리 text는 널로 종료되지 않으며 길이는 청크 길이에서 파생됩니다.
Translated keyword에는 줄바꿈이 나타나지 않아야 합니다. text에서는 줄바꿈이 단일 라인피드 문자(16진수 0A)로 표시되어야 합니다. 나머지 제어 문자들(01-09, 0B-1F, 7F-9F)은 번역된 키워드와 텍스트 모두에서 권장되지 않습니다. UTF-8에서는 권장되지 않는 문자 80-9F(문자)와 종종 필요한 바이트 80-9F(바이트) 사이에 차이가 있음을 유의하십시오.
Translated keyword가 비어 있지 않다면, 그것은 language tag가 가리키는 언어로의 키워드 번역을 포함해야 하며, 키워드를 표시하는 애플리케이션은 번역된 키워드도 함께 표시하는 것이 좋습니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
62 4B 47 44
bKGD 청크는 이미지를 표시할 때 사용할 기본 배경 색을 지정합니다. 사용자 지정 배경이 있거나 더 큰 페이지(예: 브라우저)의 일부로서 다른 우선 배경이 있는 경우에는 bKGD 청크를 무시해야 합니다. bKGD 청크는 다음을 포함합니다:
| 색상 타입 0 및 4 | |
|---|---|
| 그레이스케일 | 2 바이트 |
| 색상 타입 2 및 6 | |
| Red | 2 바이트 |
| Green | 2 바이트 |
| Blue | 2 바이트 |
| 색상 타입 3 | |
| 팔레트 인덱스 | 1 바이트 |
color type 3(indexed-color)의 경우, 값은 배경으로 사용할 색의 팔레트 인덱스입니다.
color types 0 및 4(greyscale, greyscale with alpha)의 경우, 값은 배경으로 사용할 회색 수준이며 범위는 0에서 (2bitdepth)-1입니다. color types 2 및 6(truecolor, truecolor with alpha)의 경우, 값은 배경으로 사용할 색을 RGB 샘플로 주며 범위는 0에서 (2bitdepth)-1입니다. 각 경우에 대해 일관성을 위해 샘플당 두 바이트가 사용됩니다(이미지 비트 깊이와 관계없이). 이미지 비트 깊이가 16 미만인 경우에는 최하위 유효 비트가 사용됩니다. 인코더는 나머지 비트를 0으로 설정해야 하고 디코더는 값이 사용되기 전에 나머지 비트를 0으로 마스킹해야 합니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
68 49 53 54
hIST 청크는 일련의 2바이트 부호 없는 정수를 포함합니다:
| Frequency | 2 바이트 (부호 없는 정수) |
| ...등등... |
hIST 청크는 팔레트의 각 색상 사용 빈도의 대략적 분포를 제공합니다. 히스토그램 청크는 PLTE 청크가 있을 때만 나타날 수 있습니다. 뷰어가 팔레트에 나열된 모든 색을 제공할 수 없는 경우, 히스토그램은 표시할 색의 부분 집합을 선택하는 데 도움이 될 수 있습니다.
PLTE 청크의 각 항목에 대해 정확히 하나의 항목이 있어야 합니다. 각 항목은 해당 팔레트 인덱스를 가진 이미지 픽셀의 분수에 비례하며; 정확한 스케일 팩터는 인코더가 선택합니다.
히스토그램 항목은 근사값이며, 예외적으로 0 항목은 해당 팔레트 항목이 이미지에서 전혀 사용되지 않음을 명시합니다. 어떤 색의 픽셀이 존재하면 해당 히스토그램 항목은 0이 아니어야 합니다.
참고: 팔레트가 truecolor 이미지의 권장 양자화인 경우, 디코더가 인코더와 다르게 픽셀을 팔레트 항목에 매핑할 수 있으므로 히스토그램은 필연적으로 근사값입니다. 이 경우에는 어떤 항목도 보통 0으로 나타나지 않아야 합니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
70 48 59 73
pHYs 청크는 이미지 표시를 위한 의도된 픽셀 크기 또는 종횡비를 지정합니다. 이 청크는 다음을 포함합니다:
| Name | Size |
|---|---|
| Pixels per unit, X axis | 4 바이트 (PNG four-byte unsigned integer) |
| Pixels per unit, Y axis | 4 바이트 (PNG four-byte unsigned integer) |
| Unit specifier | 1 바이트 |
Unit specifier에 대해 다음 값들이 정의됩니다:
| 값 | 설명 |
|---|---|
| 0 | 단위는 알 수 없음 |
| 1 | 단위는 미터 |
Unit specifier가 0인 경우, pHYs 청크는 픽셀 종횡비만 정의하며 실제 픽셀 크기는 지정되지 않습니다.
pHYs 청크가 없으면 픽셀은 정사각형으로 가정되며 각 픽셀의 물리적 크기는 지정되지 않습니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
73 50 4C 54
sPLT 청크는 다음을 포함합니다:
| Name | Size |
|---|---|
| Palette name | 1-79 바이트 (문자열) |
| Null separator | 1 바이트 (널 문자) |
| Sample depth | 1 바이트 |
| Red | 1 또는 2 바이트 |
| Green | 1 또는 2 바이트 |
| Blue | 1 또는 2 바이트 |
| Alpha | 1 또는 2 바이트 |
| Frequency | 2 바이트 |
| ...등등... |
각 팔레트 항목은 빨강, 파랑, 초록, 알파 및 빈도를 포함하는 5개의 부호 없는 정수로 구성된 6바이트 또는 10바이트입니다.
항목 수는 임의일 수 있습니다. PNG 디코더는 샘플 깊이 바이트 이후 남은 청크 길이로 항목 수를 결정합니다. sPLT 샘플 깊이가 8이면 남은 길이는 6으로 나누어져야 하고, 샘플 깊이가 16이면 10으로 나누어져야 합니다. 항목은 빈도 내림차순으로 나타나야 합니다. 모든 항목이 이미지에서 사용되어야 하거나 모두 달라야 한다는 요구는 없습니다.
팔레트 이름은 팔레트를 참조하기 위한 임의의 편리한 이름일 수 있습니다(예: "256 color including Macintosh default", "256 color including Windows-3.1 default", "Optimal 512"). PNG 데이터스트림에 여러 권장 팔레트가 나타나는 경우 적절한 권장 팔레트를 선택하는 데 팔레트 이름이 도움이 될 수 있습니다.
팔레트 이름은 대소문자를 구분하며, tEXt 청크의 키워드 매개변수와 동일한 제한을 받습니다. 팔레트 이름은 출력 가능한 Latin-1 문자와 공백(코드 포인트 0x20-7E 및 0xA1-FF)만 포함해야 합니다. 선행, 후행 및 연속 공백은 허용되지 않습니다.
sPLT 샘플 깊이는 8 또는 16이어야 합니다.
빨강, 초록, 파랑 및 알파 샘플은 sPLT 샘플 깊이에 따라 각각 1바이트 또는 2바이트입니다(이미지 비트 깊이와 관계없이). 색 샘플은 알파에 의해 사전 곱해져 있지 않으며 어떤 배경에 대해 미리 합성되어 있지도 않습니다. 알파 값 0은 완전 투명을 의미합니다. 알파 값 255(sPLT 샘플 깊이 8의 경우) 또는 65535(sPLT 샘플 깊이 16의 경우)는 완전 불투명을 의미합니다. sPLT 청크는 어떤 color type에 대해서도 나타날 수 있습니다. sPLT 항목은 PNG 이미지와 동일한 감마 값 및 색도 값을 사용하지만, PNG 이미지의 색 공간에서 사용되는 값 범위를 벗어날 수 있습니다; 예를 들어 greyscale PNG 이미지에서는 각 sPLT 항목이 일반적으로 동일한 R, G, B 값을 갖지만 이는 필수는 아닙니다. 마찬가지로 PNG 이미지가 투명도를 사용하지 않더라도 sPLT 항목은 불투명하지 않은 알파 값을 가질 수 있습니다.
각 빈도 값은 해당 팔레트 항목이 RGBA 공간에서 가장 근접한 일치 항목인 픽셀의 분수에 비례합니다(아직 어떤 배경과도 합성 되기 이전). 정확한 스케일 팩터는 PNG 인코더가 선택하며, 개별 값의 결과 범위가 0에서 65535 범위를 합리적으로 채우도록 하는 것이 권장됩니다. PNG 인코더는 로고나 인물의 얼굴 특징 등 "중요한" 색상에 대해 빈도를 인위적으로 부풀릴 수 있습니다. 0은 해당 색이 "덜 중요"하거나 거의 사용되지 않음을 의미하는 유효한 빈도입니다. 모든 빈도가 0이면 그것들은 의미가 없으며, 즉 색상이 실제로 이미지에서 얼마나 자주 나타나는지에 대해 아무것도 추론할 수 없습니다.
여러 sPLT 청크가 허용되지만, 각 청크는 서로 다른 팔레트 이름을 가져야 합니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
65 58 49 66
eXIf 청크의 데이터 세그먼트는 "4.7.2 Interoperability Structure of APP1 in Compressed Data"에 지정된 형식의 Exif 프로파일을 포함하지만, JPEG APP1 마커, 길이, 그리고 4.7.2(C)에 설명된 "Exif ID code"(즉 "Exif", NULL, 패딩 바이트)는 포함하지 않습니다 [CIPA-DC-008].
eXIf 청크의 크기는 PNG 명세가 부과하는 231-1 바이트의 최대치에 의해서만 제한됩니다. PNG 데이터스트림에는 오직 하나의 eXIf 청크만 허용됩니다.
eXIf 청크는 원래의 이미지 데이터에 관한 메타데이터를 포함합니다. 이미지가 Exif 프로파일 생성 이후 편집된 경우, 이 데이터는 더 이상 PNG 이미지 데이터에 적용되지 않을 수 있습니다. 디코더가 Exif 데이터의 유효성에 대한 독립적인 지식을 가지지 않는 한, 그 데이터는 역사적 가치로 간주되어야 한다고 권장됩니다. eXIf 청크와 다른 PNG 청크의 데이터 간의 잠재적 충돌을 해결하는 것은 이 명세의 범위를 벗어납니다.
PNG 명세는 청크 크기를 231-1 바이트까지 허용하지만, 애플리케이션 작성자는 Exif 프로파일을 JPEG [JPEG] 데이터스트림에 쓰려고 하는 경우, 전체 eXIf 청크 데이터의 길이를 JPEG APP1 마커(Exif) 세그먼트에 맞추기 위해 216-9 바이트를 초과하지 않도록 조정해야 할 수 있음을 유의해야 합니다.
데이터의 처음 두 바이트는 리틀엔디안(Intel)을 나타내는 "II"이거나 빅엔디안(Motorola)을 나타내는 "MM"입니다. 디코더는 처음 네 바이트를 확인하여 다음 16진수 값을 가져야 함을 확인해야 합니다:
49 49 2A 00 (ASCII "II", 16-bit little-endian integer 42)
또는
4D 4D 00 2A (ASCII "MM", 16-bit big-endian integer 42)
다른 모든 값은 향후 정의를 위해 예약되어 있습니다.
이미지 편집 애플리케이션은 Exif 명세의 부록 E.3을 고려해야 하며 [CIPA-DC-008]는 이미지가 변경될 때 Exif 데이터를 업데이트하기 위한 요구사항을 논의합니다. 인코더는 이러한 요구사항을 따르는 것이 좋지만, 디코더는 그것이 수행되었다고 가정해서는 안 됩니다.
인코더가 썸네일을 업데이트하도록 선택할 수는 있지만, 메인 이미지가 변경된 경우 Exif 프로파일 내의 썸네일이 업데이트되었는지 여부에 대한 기대는 없습니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
74 49 4D 45
tIME 청크는 이미지의 최종 수정 시각(초기 생성 시각이 아님)을 제공합니다. 이 청크는 다음을 포함합니다:
| Name | Size |
|---|---|
| Year | 2 bytes (완전 표기; 예: 1995, 95가 아님) |
| Month | 1 byte (1-12) |
| Day | 1 byte (1-31) |
| Hour | 1 byte (0-23) |
| Minute | 1 byte (0-59) |
| Second | 1 byte (0-60) (윤초를 허용하기 위함) |
지역 시각보다 협정 세계시(UTC)를 지정하는 것이 좋습니다.
tIME 청크는 image data가 변경될 때마다 자동으로 적용되고 갱신되는 타임스탬프로 사용되도록 의도되었습니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
61 63 54 4C
acTL 청크는 이 이미지가 애니메이션 PNG임을 선언하고 프레임 수와 반복 횟수를 제공합니다. 이 청크는 다음을 포함합니다:
num_frames |
4 bytes |
num_plays |
4 bytes |
각 값은 PNG four-byte unsigned integer로 인코딩됩니다.
num_frames는 애니메이션의 총 프레임 수를 나타냅니다. 이는 fcTL
청크의 수와 같아야 합니다. 0은 유효하지 않으며, 1은 단일 프레임 PNG의 유효한 값입니다. 이 값이 실제 프레임 수와 다르면 오류로 처리해야 합니다.
num_plays는 이 애니메이션이 재생되어야 할 횟수를 나타냅니다; 0이면 애니메이션은 무한 반복되어야 합니다. 0이 아닌 경우, 마지막 재생이 끝난
뒤 애니메이션은 마지막 프레임에서 정지해야 합니다.
acTL 청크는 유효한 PNG 스트림 내에서 첫 번째 IDAT 청크 앞에 나타나야 합니다.
웹 호환성을 위해, 이 청크의 개발과 배포 사이에 긴 시간이 있었고 PNG 명세에 통합된 시점의 역사적 사정으로 인해, 이 청크 이름은 예외적으로 비공개(private) 청크인 것처럼 정의되어 있습니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
66 63 54 4C
fcTL 청크는 개별 프레임의 크기, 위치, 지연 시간 및 폐기(disposal)를 정의합니다. 각 프레임마다 정확히 하나의 fcTL 청크가 필요합니다. 이 청크는 다음을 포함합니다:
| Name | Size |
|---|---|
sequence_number |
4 bytes |
width |
4 bytes |
height |
4 bytes |
x_offset |
4 bytes |
y_offset |
4 bytes |
delay_num |
2 bytes |
delay_den |
2 bytes |
dispose_op |
1 byte |
blend_op |
1 byte |
sequence_number는 애니메이션 청크의 시퀀스 번호(0부터 시작)를
정의합니다. 이는 PNG four-byte unsigned integer로
인코딩됩니다.
width와 height는 다음 프레임의 너비와 높이를 정의합니다. 이들은 PNG four-byte unsigned integers로
인코딩되며 0보다 커야 합니다.
x_offset와 y_offset는 다음 프레임의 x 및 y 위치를 정의합니다. 이들은 PNG four-byte unsigned integers로
인코딩되며 0은 유효한 값입니다.
프레임은 x_offset, y_offset, width, height로 정의된
영역 내에서 렌더링되어야 합니다. 이 영역은 기본 이미지 범위를 벗어나면 안 되므로 x_offset + width는 IHDR의 너비보다 클 수 없고, y_offset +
height는 IHDR의 높이보다 클 수 없습니다.
delay_num와 delay_den는 지연 분수의 분자와 분모를 정의하여 현재 프레임을 표시할 시간을 초 단위로 나타냅니다.
분모가 0이면 100으로 처리됩니다(즉 delay_num가 1/100초 단위를 지정). 분자가 0이면 디코더는 가능한 한 빨리 다음 프레임을
렌더링해야 하지만, 뷰어는 합리적인 하한을 둘 수 있습니다. 이들은 2바이트 부호 없는 정수로 인코딩됩니다.
프레임 타이밍은 디코딩 및 표시 시간과 독립적이어야 하므로 디코더 구현 성능에 관계없이 애니메이션이 동일한 속도로 재생됩니다.
dispose_op는 이 프레임을 렌더링한 후(즉 다음 프레임 렌더링 전) 수행할 출력 버퍼 영역 폐기 유형을 정의합니다. 이는 출력 버퍼를 다음
프레임 전에 어떻게 변경할지 지정합니다. 하나의 바이트 부호 없는 정수로 인코딩됩니다.
dispose_op의 유효한 값은 다음과 같습니다:
| 0 | APNG_DISPOSE_OP_NONE |
| 1 | APNG_DISPOSE_OP_BACKGROUND |
| 2 | APNG_DISPOSE_OP_PREVIOUS |
APNG_DISPOSE_OP_NONEAPNG_DISPOSE_OP_BACKGROUNDAPNG_DISPOSE_OP_PREVIOUS첫 번째 fcTL 청크가 APNG_DISPOSE_OP_PREVIOUS를 사용하는 경우에는
APNG_DISPOSE_OP_BACKGROUND로 처리해야 합니다.
blend_op는 프레임을 현재 출력 버퍼 내용에 알파 블렌딩할지, 아니면 출력 버퍼의 해당 영역을 완전히 대체할지를 지정합니다. 하나의 바이트 부호
없는 정수로 인코딩됩니다.
blend_op의 유효한 값은 다음과 같습니다:
| 0 | APNG_BLEND_OP_SOURCE |
| 1 | APNG_BLEND_OP_OVER |
blend_op가 APNG_BLEND_OP_SOURCE이면 알파를 포함한 프레임의 모든 색 구성 요소가 프레임의 출력 버퍼
영역의 현재 내용을 덮어씁니다. blend_op가 APNG_BLEND_OP_OVER이면 프레임은 그 알파를 기반으로 출력
버퍼에 composited되어야 하며, 이는 Alpha Channel Processing에 설명된 단순 OVER 연산을 사용합니다. 샘플
코드의 두 번째 변형이 적용 가능함을 유의하세요.
첫 번째 프레임의 경우, 출력 버퍼가 각 재생의 시작에서 지워지기 때문에 두 블렌드 모드가 기능적으로 동일합니다.
기본 이미지에 해당하는 fcTL 청크(존재하는 경우)는 다음 제한을 가집니다:
x_offset와 y_offset 필드는 0이어야 합니다.width와 height 필드는 IHDR 청크의 해당
필드와 같아야 합니다.
앞서 언급한 바와 같이, 출력 버퍼는 각 재생의 시작 시 완전 투명한 검은색으로 완전히 초기화되어야 합니다. 이는 재생마다 동일한 결과가 보장되도록 하기 위함입니다. 디코더는
결과가 동일하게 보장되는 한 명시적 지우기 단계를 피할 수 있습니다. 예를 들어 기본 이미지가 애니메이션에 포함되어 있고 blend_op가
APNG_BLEND_OP_SOURCE인 경우, 출력 버퍼 전체가 덮어써지므로 지우기가 필요하지 않습니다.
웹 호환성을 위해, 이 청크의 개발과 배포 사이에 긴 시간이 있었고 PNG 명세에 통합된 시점의 역사적 사정으로 인해, 이 청크 이름은 예외적으로 비공개(private) 청크인 것처럼 정의되어 있습니다.
4바이트 청크 타입 필드에는 다음 16진수 값이 들어 있습니다
66 64 41 54
fdAT 청크는 정적 이미지를 위한 IDAT 청크가 하는 것과 동일한 목적을 애니메이션에 대해 수행합니다; 즉 fdAT 청크 집합은 모든 프레임(또는 정적 이미지가 첫 프레임으로 포함된 애니메이션의 경우 첫 프레임 이후의 모든 프레임)에 대한 image data를 포함합니다. 이 청크는 다음을 포함합니다:
| Name | Size |
|---|---|
sequence_number |
4 bytes |
frame_data |
n bytes |
각 프레임에는 적어도 하나의 fdAT 청크가 필요합니다. 단, 해당 프레임이 IDAT 청크로 표현된 첫 번째 프레임인 경우는 예외입니다.
각 프레임의 압축된 데이터스트림은 그 프레임 내 모든 fdAT 청크의 frame_data 필드 내용을
시퀀스 번호 오름차순으로 연결한 것입니다.
시퀀스 번호 때문에 fdAT 청크는 길이 0일 수 없습니다; 그러나
frame_data 필드는 0바이트일 수 있습니다.
압축 해제되면, 이 데이터스트림은 각 스캔라인 시작의 필터 바이트를 포함한 PNG 이미지의 완전한 픽셀 데이터이며, 모든 IDAT 청크의 비압축 데이터와 유사합니다. 이는 정적 이미지와 동일한 비트 깊이, color type, 압축 방식,
filter
method, 인터레이스 방식, 및 팔레트(있을 경우)를 사용합니다.
각 프레임은 파일 내 첫 번째 IDAT 청크보다 이전에 지정된 모든 필수 또는 보조 청크에 의해 지정된 모든 속성을 상속합니다. 단, 너비와 높이는 fcTL 청크에서 가져옵니다.
PNG에 pHYs 청크가 있는 경우, APNG 이미지와 그들의 x_offset 및
y_offset 값은 메인 이미지와 동일한 방식으로 스케일링되어야 합니다. 개념적으로 이러한 스케일링은 출력 버퍼를 canvas에 매핑하는 동안 발생합니다.
웹 호환성을 위해, 이 청크의 개발과 배포 사이에 긴 시간이 있었고 PNG 명세에 통합된 시점의 역사적 사정으로 인해, 이 청크 이름은 예외적으로 비공개(private) 청크인 것처럼 정의되어 있습니다.
이 절에서는 인코더 동작에 대한 요구사항과 권장사항을 제공합니다. PNG 인코더는 앞선 절들에서 규정된 형식에 부합하는 PNG 이미지를 입력으로 하여 PNG 데이터스트림을 생성해야 합니다. 추가로 이곳에 제시된 권장사항을 따르면 보통 최상의 결과를 얻을 수 있습니다.
감마 문제에 대한 간단한 소개는 C. 감마와 색도를 참고하세요.
완전한 색 관리가 가능한 PNG 인코더는 여기서 설명한 것보다 더 정교한 계산을 수행할 수 있으며 iCCP 청크를 사용할 수 있습니다. 이미지 샘플이 sRGB 규격을 준수하는 것으로 알려진 경우 [SRGB] 인코더는 추가적인 감마 처리 없이 sRGB 청크를 쓰는 것을 강력히 권장합니다. 두 경우 모두, iCCP 또는 sRGB 청크를 인식하지 못하는 PNG 디코더에서 사용할 수 있도록 적절한 gAMA 청크를 생성하는 것이 권장됩니다.
PNG 인코더는 다음을 결정해야 합니다:
gAMA 청크에 쓸 값은 PNG 디코더가 원하는 방식으로 동작하도록 만드는 값입니다. 자세한 사항은 13.13 디코더 감마 처리를 보십시오.
적용할 변환은 이미지 샘플의 성격과 정밀도에 따라 달라집니다. 샘플이 부동소수점 또는 고정밀 정수 형태로 광 강도를 나타낸다면(예: 컴퓨터 그래픽 렌더러 출력), 인코더는 정수를 PNG 데이터스트림에 포함하기 전에 감마 인코딩(지수값이 1보다 작은 거듭제곱 함수 적용)을 수행할 수 있습니다. 이는 주어진 샘플 깊이에서 밴딩 아티팩트를 줄이거나 동일한 시각적 품질을 유지하면서 샘플을 작게 유지할 수 있게 합니다. 범위 0에서 1의 부동소수점 intensity 값은 다음과 같이 데이터스트림 이미지 샘플로 변환할 수 있습니다:
integer_sample = floor((2sampledepth-1) * intensityencoding_exponent + 0.5)
만약 식의 intensity가 원하는 출력 휘도라면, encoding exponent는 gamma value로서 gAMA 청크에 사용됩니다.
만약 인코더에 주어진 intensity가 원래 장면의 휘도라면, 다른 변환이 필요할 수 있습니다. 때때로 표시된 이미지는 원본보다 더 높은 대비를 가지도록 요구됩니다. 이는 원장(scene)에서 표시 출력까지의 end-to-end 전달 함수가 1보다 큰 지수를 갖는 경우에 해당합니다. 이 경우:
gamma = encoding_exponent/end_to_end_exponent
원래 이미지가 캡처되거나 계산된 조건이 그러한 대비 변화를 정당화하는지 알 수 없으면, 표시 휘도가 원래 장면 휘도에 비례한다고 가정할 수 있습니다. 즉 end-to-end exponent를 1로 가정하면:
gamma = encoding_exponent
이미지가 데이터스트림으로만 기록되는 경우, 인코더는 인코딩 지수를 자유롭게 선택할 수 있습니다. 그 값이 감마 값이 gAMA 청크에서 1/2.2가 되도록 하는 선택은 전형적인 비디오 모니터에 이미지를 표시하는 PNG 디코더의 작업을 최소화하므로 종종 합리적인 선택입니다.
어떤 이미지 렌더러는 이미지를 PNG 데이터스트림에 쓰는 동시에 화면에 표시할 수 있습니다. 표시되는 픽셀은 사용 중인 표시 시스템과 시청 조건에 대해 감마 보정되어야 하며, 사용자가 의도한 장면을 적절히 보도록 해야 합니다.
렌더러가 화면에 표시된 샘플 값을 그대로 PNG 데이터스트림에 쓰고 데이터스트림에 대한 별도의 감마 인코딩 단계를 피하려면, 렌더러는 표시 시스템의 전달 함수를 거듭제곱 함수로 근사하고, 지수의 역수를 gAMA 청크에 기록해야 합니다. 이렇게 하면 PNG 디코더가 렌더링 중에 원작자가 화면에서 본 것을 재현할 수 있습니다.
그러나 렌더러가 표시 장치에 적합한 표시 픽셀을 계산하고 데이터 저장 및 전송을 위해 별도의 감마 인코딩을 수행하여 나중에 이미지를 사용할 때 더 적절한 gAMA 값을 갖게 하는 것도 합리적입니다.
컴퓨터 그래픽 렌더러는 종종 감마 인코딩을 수행하지 않고 샘플 값을 장면 광 강도에 비례하도록 만듭니다. PNG 인코더가 이미 정수로 양자화된 샘플 값을 받으면, 그 값에 대해 감마 인코딩을 수행하는 것은 추가적인 정보 손실만 초래하므로 의미가 없습니다. 인코더는 단순히 샘플 값을 PNG 데이터스트림에 기록해야 합니다. 이는 gAMA 청크의 값이 1.0이어야 함을 의미하지는 않습니다. 장면 휘도에서 표시 출력까지의 원하는 end-to-end 전달 함수가 반드시 선형인 것은 아니기 때문입니다. 그러나 원하는 gamma value는 아마 1.0에 그리 멀지 않을 것입니다. 이는 렌더링된 장면이 야외 일광 장면인지 실내 장면인지 등에 따라 달라질 수 있습니다.
샘플 값이 하드웨어에서 직접 나오는 경우, 올바른 gAMA 값은 원칙적으로 하드웨어의 전달 함수와 장면의 조명 조건으로부터 추론될 수 있습니다. 비디오 디지타이저("프레임 그래버")의 경우 샘플은 대개 sRGB 색 공간에 있을 가능성이 높습니다. 이미지 스캐너는 덜 예측 가능합니다. CCD 센서는 본래 선형이므로 출력 샘플이 입력 광 강도에 비례할 수 있고, 또는 스캐너 하드웨어가 인쇄의 도트게인을 보정하기 위해 약한 거듭제곱 함수를 이미 적용했을 수도 있으며(지수 약 0.57), 혹은 스캐너가 표시를 위해 샘플을 보정했을 수도 있습니다. 특정 스캐너의 특성을 알기 위해서는 스캐너 매뉴얼을 참고하거나 교정 대상(caledibrated target)을 스캔해야 할 수도 있습니다. 감마는 샘플과 원하는 표시 출력 간의 관계를 다룬다는 점을 기억하세요.
데이터스트림 형식 변환기는 일반적으로 공급된 이미지를 다른 감마로 변환하려고 시도해서는 안 됩니다. 데이터는 변환 없이 PNG 데이터스트림에 저장되어야 하며, 가능한 경우 원본 데이터스트림의 정보를 바탕으로 gamma value를 유추해야 합니다. 데이터스트림 변환 시의 감마 변경은 표현되는 강도 수준 집합의 재양자화를 초래하여 거의 이득 없이 반올림 오차를 추가합니다. 따라서 입력에서 출력으로 샘플 값을 그대로 복사하는 것이 거의 항상 바람직합니다.
원본 데이터스트림이 이미지의 감마 특성을 설명하는 경우, 데이터스트림 변환기는 gAMA 청크를 쓰는 것이 강력히 권장됩니다. 일부 데이터스트림 형식은 표시 지수(이미지 샘플을 표시 출력으로 매핑하는 함수의 지수)를 명시합니다. 원본 파일의 gamma value가 1.0보다 크다면, 이는 아마도 표시 지수일 가능성이 높고, PNG의 gamma value로는 그 역수를 사용해야 합니다. 원본 파일 형식이 이미지 샘플과 표시 출력 이외의 양 사이의 관계를 기록한다면, PNG gamma value를 유추하는 과정은 이보다 복잡할 것입니다.
PNG 인코더나 데이터스트림 변환기가 표시 시스템의 전달 함수를 display_exponent로 근사할 수 있고 그 시스템에서 만족스럽게 이미지가 표시되었음을 알고 있다면, 이미지는 다음과 같은 gamma value로 표시할 수 있습니다:
gamma = 1/display_exponent
정확히 맞는 값을 쓰는 것보다 근사치라도 gAMA 청크를 쓰는 편이 낫습니다. 디코더가 근사값을 추측하도록 강요하는 것보다는 낫습니다. PNG 인코더가 gamma value를 유추할 수 없다면 gAMA 청크를 생략하는 것이 바람직합니다. 만약 추측을 해야 한다면, 이는 PNG 디코더에 맡기는 것이 좋습니다.
감마는 알파 샘플에는 적용되지 않습니다; 알파는 항상 선형으로 표현됩니다.
또한 13.13 디코더 감마 처리를 보십시오.
색 문제에 관한 참조는 C. 감마와 색도를 보십시오.
완전한 색 관리를 수행할 수 있는 PNG 인코더는 여기에서 설명한 것보다 더 정교한 계산을 수행할 수 있으며 iCCP 청크를 사용할 수 있습니다. 이미지 샘플이 sRGB 규격을 준수하는 것으로 알려진 경우 [SRGB] PNG 인코더는 sRGB 청크를 사용하는 것이 강력히 권장됩니다.
인코더가 소스 디스플레이 프라이머리의 색도(chromaticities)를 결정할 수 있거나 이미지의 출처나 실행 중인 하드웨어에 근거하여 강한 추정을 할 수 있다면, 인코더는 cHRM 청크를 출력하는 것이 강력히 권장됩니다. 그렇게 한다면 gAMA 청크도 함께 써야 합니다; gAMA 청크가 없으면 디코더는 cHRM 청크로 할 수 있는 것이 거의 없습니다.
프라이머리와 화이트 포인트에 대한 여러 권장 사항과 표준이 있으며, 일부는 특정 기술과 연관됩니다. 예를 들어 CCIR 709 표준 [ITU-R-BT.709] 및 SMPTE-C 표준 [SMPTE-170M] 등이 있습니다.
고려해야 할 경우는 세 가지입니다:
손으로 그리거나 디지털로 편집된 이미지의 경우, 제작 시 어떤 모니터에서 보았는지를 결정할 필요가 있습니다. 많은 이미지 편집 프로그램은 사용 중인 모니터 유형을 지정할 수 있게 합니다. 이는 내부적으로 장치 독립적인 공간에서 작업하기 때문인 경우가 많습니다. 그러한 프로그램은 유효한 cHRM 및 gAMA 청크를 쓸 수 있는 충분한 정보를 가지고 있으므로 자동으로 작성하는 것이 강력히 권장됩니다.
인코더가 전체 스펙트럼 렌더링을 수행하는 컴퓨터 이미지 렌더러의 일부로 컴파일되어 있다면, 내부의 장치 독립 색 공간에서 RGB로 변환할 때 사용된 모니터 값을 cHRM 청크에 기록해야 합니다. 선택된 RGB 장치의 색역 밖에 있는 색상은 색역 내로 매핑되어야 합니다; PNG는 색역 밖 색상을 저장하지 않습니다.
컴퓨터 이미지 렌더러가 장치 종속 RGB 공간에서 직접 계산을 수행하는 경우, 장면 설명 및 렌더링 매개변수가 특정 모니터에 맞게 조정되지 않았다면 cHRM 청크는 작성해서는 안 됩니다. 그런 경우 해당 모니터에 대한 데이터를 사용하여 cHRM 청크를 구성해야 합니다.
몇몇 이미지 형식은 보정(calibration) 정보를 저장할 수 있으며, 이를 사용해 cHRM 청크를 채울 수 있습니다. 예를 들어 TIFF 6.0 파일 [TIFF-6.0]는 선택적으로 보정 정보를 저장할 수 있으며, 존재한다면 이를 사용하여 cHRM 청크를 구성해야 합니다.
최근 비디오 장비로 생성된 비디오는 대개 CCIR 709 프라이머리와 D65 화이트 포인트를 사용하며 [ITU-R-BT.709] 이 값들은 Table 29에 제공됩니다.
| R | G | B | White | |
|---|---|---|---|---|
| x | 0.640 | 0.300 | 0.150 | 0.3127 |
| y | 0.330 | 0.600 | 0.060 | 0.3290 |
오래되었지만 여전히 널리 사용되는 비디오 표준으로 SMPTE-C [SMPTE-170M]가 있으며, 이는 Table 30에 나와 있습니다.
| R | G | B | White | |
|---|---|---|---|---|
| x | 0.630 | 0.310 | 0.155 | 0.3127 |
| y | 0.340 | 0.595 | 0.070 | 0.3290 |
데이터스트림 형식 변환기가 공급된 이미지를 다른 RGB 색 공간으로 변환하려고 시도하는 것은 권장되지 않습니다. 데이터는 변환 없이 PNG 데이터스트림에 저장되어야 하며, 알려진 경우 원본 프라이머리 색도를 기록해야 합니다. 데이터스트림 변환 시의 색 공간 변환은 색역 불일치와 반올림 오류 때문에 나쁜 아이디어입니다. 감마 변환과 마찬가지로, 데이터는 무손실로 저장하고 최종적으로 이미지를 표시할 때 한 번의 변환만 하는 것이 낫습니다.
또한 13.14 디코더 색상 처리를 보십시오.
알파 채널은 투명한 부분을 일시적으로 숨기는 마스크로 보거나 비직사각형 이미지를 구성하는 수단으로 볼 수 있습니다. 첫 번째 경우에는 완전 투명한 픽셀의 색상 값은 향후 사용을 위해 보존되어야 합니다. 두 번째 경우에는 투명 픽은 유용한 데이터를 가지지 않으며 PNG가 요구하는 직사각형 이미지 영역을 채우기 위해 단순히 존재합니다. 이 경우에는 최적의 압축을 위해 모든 완전 투명 픽에 동일한 색상 값을 할당해야 합니다.
이미지 작성자는 디코더가 투명도 처리를 완전히 지원하지 않을 가능성을 염두에 두어야 합니다(참조: 13.16 알파 채널 처리). 따라서 가능하다면 투명 픽에 지정된 색상은 합리적인 배경 색상이어야 합니다.
완전한 알파 채널이 필요 없거나 압축 효율상 비용을 감당할 수 없는 응용을 위해 tRNS 투명도 청크도 사용할 수 있습니다.
이미지에 알려진 배경 색이 있다면 이 색은 bKGD 청크에 기록해야 합니다. 투명도를 무시하는 디코더도 bKGD 색을 사용해 남는 화면 영역을 채울 수 있습니다.
원래 이미지가 사전 곱해진(premultiplied, associated) 알파 데이터를 가지고 있다면, 각 샘플 값을 해당 알파 값으로 나눈 다음 이미지 비트 깊이에 대한 최대값을 곱하고 가장 가까운 정수로 반올림하여 PNG의 비사전곱(non-premultiplied) 형식으로 변환할 수 있습니다. 유효한 사전 곱 데이터에서는 샘플 값이 해당 알파 값을 초과하지 않으므로 나눗셈 결과는 항상 0에서 1 범위여야 합니다. 알파 값이 0이면 출력은 검정(0)으로 합니다.
PNG에서 직접 표현할 수 없는 샘플 비트 깊이를 가진 입력 샘플을 인코딩할 때, 인코더는 샘플을 PNG에서 허용되는 샘플 비트 깊이로 스케일 업해야 합니다. 가장 정확한 스케일 방법은 다음의 선형 방정식입니다:
output = floor((input * MAXOUTSAMPLE / MAXINSAMPLE) + 0.5)
여기서 입력 샘플은 0에서 MAXINSAMPLE 범위이고 출력은 0에서 MAXOUTSAMPLE 범위입니다(후자는 2sampledepth-1임).
"왼쪽 비트 복제(left bit replication)"는 선형 스케일 방법을 근사하는 방법으로, 유효한 비트들을 최상위 비트부터 이동시키고 최상위 비트를 빈 비트에 반복하여 채웁니다. 이 방법은 선형 스케일보다 계산이 빠른 경우가 많습니다.
예를 들어 5비트 샘플을 8비트로 스케일한다고 가정합니다. 소스 샘플 값이 27(0-31 범위)이라면 원래 비트는:
4 3 2 1 0
---------
1 1 0 1 1
왼쪽 비트 복제는 222의 값을 줍니다:
7 6 5 4 3 2 1 0
----------------
1 1 0 1 1 1 1 0
|=======| |===|
| Leftmost Bits Repeated to Fill Open Bits
|
Original Bits
이는 선형 방정식으로 계산한 값과 일치합니다. 왼쪽 비트 복제는 보통 선형 스케일과 동일한 값을 주며, 절대 오차는 1을 넘지 않습니다.
덜 정확한 근사는 입력 값을 왼쪽으로 이동시키고 낮은 자리 비트를 0으로 채우는 방법입니다. 이 방식은 최대값에 해당하는 전부 1 비트를 생성하지 못하므로 정확한 흰색을 재현하지 못해 이미지가 약간 어두워지는 효과가 있습니다. 일반적으로 권장되지는 않지만, 특히 8비트 초과 샘플 깊이를 다룰 때 압축을 개선하는 효과가 있습니다. 높은 샘플 깊이에서는 zero-fill로 인한 상대 오차가 작으므로 일부 인코더는 이를 선택할 수 있습니다. 그러나 zero-fill은 많은 디코더가 알파 값이 전부 0이거나 전부 1인 경우를 특수 처리하기 때문에 알파 채널 데이터에 대해서는 사용해서는 안 됩니다. 스케일된 데이터에서 이 값들을 정확히 표현하는 것이 중요합니다.
인코더가 sBIT 청크를 쓸 때는 저장된 샘플의 최상위 비트가 원본 데이터와 일치하도록 스케일링해야 합니다. 즉, sBIT가 S를 지정하면 저장된 데이터의 최상위 S비트는 원래 S비트 데이터 값과 일치해야 합니다. 이는 디코더가 오른쪽으로 시프트하여 원본 데이터를 복원할 수 있게 합니다. 추가된 저위 비트들은 제약을 받지 않습니다. 앞서 언급한 모든 스케일링 방법은 이 제약을 만족합니다.
소스 이미지 데이터를 스케일 업할 때, 저위 비트는 모든 샘플에 대해 일관되게 채우는 것이 권장됩니다; 즉 동일한 소스 값은 모든 픽 위치에서 동일한 샘플 값을 생성해야 합니다. 이는 서로 다른 샘플 값의 수를 줄여 압축을 개선합니다. 이는 필수는 아니며 일부 인코더는 이를 따르지 않을 수 있습니다. 예를 들어 인코더는 저위 비트를 디더링하여 표시 품질을 향상시키는 대신 파일 크기를 증가시킬 수 있습니다.
일부 응용에서는 원본 소스 데이터 범위가 2의 거듭제곱이 아닐 수 있습니다. 이 경우에도 선형 스케일 방정식은 작동하지만 비트 시프트 방식은 작동하지 않습니다. 이러한 이미지에 대해 sBIT 청크를 쓰지 않는 것이 권장됩니다. sBIT는 원본 데이터 범위가 정확히 0..2S-1이었음을 암시하기 때문입니다.
제안된 팔레트는 어떤 PNG 데이터스트림에서는 sPLT 청크로, 또는 PLTE 청크로 truecolor PNG 데이터스트림에 나타날 수 있습니다. 어느 경우든 제안된 팔레트는 image data의 필수 구성 요소는 아니지만, 인덱스-컬러 디스플레이 하드웨어에서 이미지를 표시하는 데 사용될 수 있습니다. 제안된 팔레트는 truecolour 하드웨어에서 실행되는 뷰어에는 관련이 없습니다.
sPLT 청크로 권장 팔레트를 제공할 경우, 인코더는 빈도 필드(frequency fields)를 모두 0으로 두지 말고 팔레트 항목의 상대적 중요도를 나타내도록 사용하는 것이 권장됩니다. 빈도 값은 근사적으로 "최근접 이웃" 카운트로 계산하는 것이 가장 쉬운데, 즉 디더링이 적용되지 않았을 때 각 RGBA 팔레트 항목의 사용량을 근사하는 값입니다(이 값들은 권장 팔레트를 개발할 때 종종 "무료로" 얻을 수 있습니다). 권장 팔레트는 투명 정보를 포함하므로 합성되지 않은(un-composited) 이미지에 대해 계산해야 합니다.
인덱스 컬러 이미지의 경우에도 sPLT는 모든 색을 표시할 수 없는 뷰어를 위해 대체 축소 팔레트를 정의하는 데 사용할 수 있습니다. PLTE 청크가 나타나되 bKGD 청크가 없는 경우, 색 팔레트가 계산된 상황은 명시되지 않습니다.
truecolor PNG 데이터스트림에 권장 팔레트를 포함하는 오래된 방법은 PLTE 청크를 사용하는 것입니다. 이 방법을 사용할 경우 히스토그램(빈도)은 별도의 hIST 청크에 나타나야 합니다. PLTE 청크는 투명 정보를 포함하지 않으므로, color type 6(truecolor with alpha) 이미지의 경우 bKGD 청크가 나타나고 팔레트와 히스토그램은 지정된 배경 색으로 합성된 이미지에 기초하여 계산되는 것이 권장됩니다. 이는 분수 알파 값을 가지는 픽셀에 대해 유용한 팔레트 항목이 생성되도록 하기 위해 필요합니다. 생성된 팔레트는 동일한 배경 색을 사용하는 뷰어에만 유용할 가능성이 높습니다. PNG 편집기가 bKGD 청크를 변경하거나 삭제하면 해당 팔레트를 삭제하거나 재계산하는 것이 권장됩니다.
color type 2(truecolor) 이미지의 경우, PLTE 및 hIST 청크는 투명-색 지정은 무시하고 RGB 데이터만을 기준으로 계산하는 것이 권장됩니다. 데이터스트림이 투명도를 사용하면(tRNS 청크가 있는 경우) 뷰어는 생성된 팔레트를 의도한 배경 색에 맞게 쉽게 조정할 수 있습니다(참조: 13.17 히스토그램 및 권장 팔레트 사용).
권장 팔레트를 제공할 때 sPLT 청크는 다음과 같은 점에서 PLTE 청크보다 유연합니다:
sPLT 청크를 사용하는 PNG 인코더는, sPLT를 인식하지 못하는 디코더와의 호환성을 위해 PLTE 및 hIST 청크로 표현된 권장 팔레트를 함께 쓸 수 있습니다.
이 명세는 두 가지 인터레이스 방식을 정의하며 그중 하나는 인터레이스 없음입니다. 인터레이싱은 디코더가 이미지를 점진적으로 표시할 수 있는 편리한 기초를 제공합니다(참조: 13.10 인터레이싱 및 점진적 표시).
color type 3(인덱스 컬러) 이미지의 경우, 필터 타입 0(None)이 보통 가장 효과적입니다. 색상이 256개 이하인 컬러 이미지는 거의 항상 인덱스 컬러 형식으로 저장하는 것이 좋습니다; truecolor 형식은 훨씬 더 커질 가능성이 큽니다.
비트 깊이가 8 미만인 이미지에는 필터 타입 0이 권장됩니다. 저비트 깊이 그레이스케일 이미지의 드문 경우에는 먼저 이미지를 8비트로 확장한 다음 필터링을 적용하면 더 나은 압축을 얻을 수 있습니다.
truecolor 및 그레이스케일 이미지의 경우 다섯 가지 필터 중 어느 것이 가장 효과적일지 상황에 따라 다릅니다. 인코더가 고정 필터를 사용할 경우 Paeth 필터 타입이 보통 가장 좋습니다.
truecolor 및 그레이스케일 이미지의 최적 압축을 위해, 그리고 압축 효율을 속도보다 우선시하는 경우에는 스캔라인마다 필터 타입을 선택하는 적응형 필터링이 권장됩니다. 각 이미지는 최적으로 작동하는 서로 다른 필터 집합을 가집니다. 인코더는 주어진 이미지에 대해 압축이 가장 좋은 모든 필터 조합을 시도할 수 있습니다. 그러나 전수 탐색이 허용되지 않는 경우, 다음과 같은 일반적 휴리스틱이 충분히 잘 동작할 수 있습니다: 다섯 가지 필터로 출력 스캔라인을 계산하고 출력 바이트의 절대값 합이 가장 작은 필터를 선택합니다(이 테스트에서는 출력 바이트들을 부호 있는 차이로 간주). 이 방법은 보통 단일 고정 필터를 선택하는 것보다 더 나은 성능을 냅니다.
이 권장에 따른 필터링은 이 명세에서 정의한 두 가지 인터레이스 방법 중 어느 것과도 함께 효과적입니다.
인코더는 압축된 데이터스트림을 원하는 방식으로 IDAT 청크로 분할할 수 있습니다. (여러 IDAT 청크는 인코더가 고정된 메모리 양으로 작업할 수 있게 허용합니다; 보통 청크 크기는 인코더의 버퍼 크기에 대응합니다.) 각 IDAT 청크가 단 하나의 데이터 바이트만 포함하는 PNG 데이터스트림도 유효하지만 공간을 극도로 낭비합니다. (제로 길이 IDAT 청크도 유효하지만 더 많이 낭비됩니다.)
각 텍스트 청크에는 비어 있지 않은 키워드가 제공되어야 합니다. 더 나은 설명이 없다면 일반 키워드 "Comment"를 사용할 수 있습니다. 사용자 제공 키워드를 사용하는 경우 인코더는 해당 키워드가 키워드 제한을 충족하는지 확인해야 합니다.
iTXt 청크는 유니코드의 UTF-8 인코딩을 사용하므로 어떤 언어의 텍스트도 저장할 수 있습니다. tEXt 및 zTXt 청크는 Latin-1(ISO 8859-1) 문자 인코딩을 사용하여 이들 청크에서 사용 가능한 문자의 범위를 제한합니다. 인코더는 데이터 손실 없이 넓은 문자 범위를 허용하기 위해 iTXt를 tEXt 및 zTXt보다 선호해야 합니다. 인코더는 로컬 레거시 문자 인코딩을 사용하는 문자를 저장할 때 적절한 인코딩으로 변환해야 합니다.
iTXt 청크를 생성할 때 인코더는 Encoding Standard의 UTF-8 encode를 따라야 합니다.
인코더는 읽기 편의를 돕기 위해 79 유니코드 코드 포인트보다 긴 단일 라인의 텍스트 생성을 억제해야 합니다. 길이 1024 바이트 미만의 텍스트 항목은 비압축 텍스트 청크로 출력하는 것이 권장됩니다. 기본 제목과 작성자 키워드는 비압축 텍스트 청크로 출력하는 것이 권장됩니다. 큰 텍스트 청크를 이미지 데이터(IDAT 청크 이후)에 배치하면 몇몇 상황에서 이미지 표시 속도를 높일 수 있습니다. 디코더가 먼저 이미지 데이터를 디코딩하기 때문입니다. 이미지 제목과 같은 작은 텍스트 청크는 IDAT 청크 앞에 위치시키는 것이 권장됩니다.
인코더는 다른 애플리케이션이 이해할 필요가 없는 정보를 담기 위해 비공개 청크를 사용할 수 있습니다(MAY).
인코더는 실험적 또는 비공개 용도로 비예약된 필드 값을 사용할 수 있습니다(MAY).
모든 보조 청크는 선택 사항이며, 인코더가 반드시 작성할 필요는 없습니다. 그렇지만 정보가 이용 가능할 때 표준 보조 청크를 작성하는 것이 권장됩니다.
이 절은 PNG 디코더 동작과 뷰어 동작에 대한 몇 가지 요구사항과 권장사항을 제공합니다. 뷰어는 디코딩된 PNG 이미지를 사용자에게 표시합니다. 뷰어와 디코더 동작은 밀접하게 연결되어 있으므로 여기에서는 디코더와 뷰어를 함께 다룹니다. PNG 디코더에 대한 유일한 절대적 요구사항은 앞 장들에서 규정한 형식에 부합하는 모든 데이터스트림을 성공적으로 읽을 수 있어야 한다는 것입니다. 그러나 보통 최상의 결과는 아래의 추가 권장사항을 따름으로써 얻을 수 있습니다.
PNG 디코더는 이 국제 표준에서 명시적으로 정의된 모든 유효한 비트 깊이, color type, 압축 방식, filter method, 및 인터레이스 방식을 지원해야 합니다.
PNG 데이터스트림의 오류는 일반적으로 전송 오류와 구문 오류의 두 가지 일반적인 분류로 나뉩니다(자세한 내용은 4.10 Error handling 참조).
전송 오류의 예로는 "text" 또는 "ascii" 모드로의 전송으로 인해 바이트 코드 13 및/또는 10이 데이터스트림 전체에서 추가되거나 삭제되거나 변환되는 경우, 데이터스트림이 잘려 예기치 않게 종료되는 경우, 또는 저장 장치의 물리적 오류로 인해 하나 이상의 블록(보통 512바이트 단위)이 손상되거나 무작위 값으로 채워지는 경우 등이 있습니다. 구문 오류의 예로는 행 필터의 잘못된 값, 잘못된 압축 방식, 잘못된 청크 길이, 인덱스 이미지에서 첫 번째 IDAT 청크 이전에 PLTE 청크가 없는 경우, 또는 여러 개의 gAMA 청크가 존재하는 경우 등이 있습니다. PNG 디코더는 다음과 같이 오류를 처리해야 합니다:
이 철학과 관련된 PNG 청크의 세 가지 분류가 있습니다. 이 분류의 목적상 "알려지지 않은 청크"는 디코더 작성자가 실제로 유형을 알지 못한 청크이거나, 해당 청크 유형의 기본 처리가 프로그램 목적에 충분하다고 작성자가 판단하여 알지 못하는 것으로 처리한 청크를 의미합니다. 나머지 청크는 "알려진 청크"라고 합니다. 이 정의에 따라 세 가지 클래스는 다음과 같습니다:
청크 명명 규칙에 대한 설명은 5.4 Chunk naming conventions을 참조하세요.
PNG 청크 타입은 이미지 추출에 필수적인지 여부(예: IHDR, PLTE, IDAT) 또는 데이터스트림 구조를 이해하는 데 필수적인지 여부(예: IEND)에 따라 "critical" 또는 "ancillary"로 표시됩니다. 이는 특정한 종류의 중요성으로 모든 디코더에 반드시 관련되는 것은 아닙니다. 예를 들어 저작권 정보 같은 텍스트 주석만 추출하는 프로그램은 보기 가능한 이미지가 필요 없지만 UTF-8을 올바르게 디코드해야 합니다. 또 다른 디코더는 tRNS 및 gAMA 청크를 자신의 적절한 실행에 필수적이라고 간주할 수 있습니다.
구문 오류는 항상 알려진 청크와 관련됩니다. 알려지지 않은 청크의 구문 오류는 감지할 수 없기 때문입니다. PNG 디코더는 구문 오류가 치명적(복구 불가)인지 여부를 자신의 요구와 상황에 따라 결정해야 합니다. 예를 들어 대부분의 디코더는 잘못된 IEND 청크를 무시할 수 있고, 텍스트 추출 프로그램은 IDAT의 부재를 무시할 수 있지만, 이미지 뷰어는 인덱스 이미지에서 비어 있는 PLTE 청크로부터 복구할 수 없습니다. 반면 truecolor 이미지의 잘못된 PLTE 청크는 무시할 수 있습니다. 알파 채널을 추출하는 프로그램은 잘못된 gAMA 청크를 무시할 수 있지만, 두 개의 tRNS 청크가 존재하는 것을 치명적 오류로 간주할 수 있습니다. 구문 오류 이외의 이상한 상황은 다음과 같이 처리되어야 합니다:
치명적 조건이 발생하면 디코더는 즉시 실패하고, 적절하다면 사용자에게 오류를 알리며, 선택적으로 이미 사용자에게 표시된 image data를 계속 표시해야 합니다(즉 "우아하게 실패"). 애플리케이션 전체가 종료될 필요는 없습니다.
비치명적 오류가 발생하면 디코더는 적절하면 사용자에게 경고를 알리고 오류에서 복구하여 정상 처리를 계속해야 합니다.
인덱스 컬러 PNG를 디코딩할 때 범위를 벗어난 인덱스가 발견되면, 과거의 디코더들은 이를 처리하는 방식이 다양했습니다. 픽셀을 불투명한 검정으로 표시하는 것은 일반적인 오류 복구 전술 중 하나이며 이 명세에서는 이제 요구됩니다. 오래된 구현은 달라질 수 있으므로 인코더는 이 동작을 신뢰해서는 안 됩니다.
CRC를 계산하지 않는 디코더는 명백한 구문 오류를 손상 표시로 해석해야 합니다(자세한 내용은 13.2 Error checking 참조).
압축된 청크(IDAT, zTXt, iTXt, iCCP)의 오류는 버퍼 오버런으로 이어질 수 있습니다. deflate 압축 해제기 구현자는 이 가능성에 대비해야 합니다.
APNG는 전체 데이터스트림을 모두 읽기 전에 프레임을 점진적으로 표시할 수 있도록 설계되었습니다. 이는 일부 오류가 애니메이션 진행 중에야 감지될 수 있음을 의미합니다. 어떤 오류가 발견되면 디코더는 이후의 모든 프레임을 폐기하고 애니메이션을 중지하며 정적 이미지를 표시하도록 되돌리는 것이 강력히 권장됩니다. 애니메이션이 시작되기 전에 오류를 감지한 디코더는 정적 이미지를 표시해야 합니다. 적절하다면 사용자에게 오류 메시지를 표시할 수 있습니다.
디코더는 순서가 뒤바뀐 APNG 청크를 오류로 처리해야 합니다. APNG-인식 PNG 편집기는 시퀀스 번호를 사용하여 이들을 올바른 순서로 복원해야 합니다.
PNG 오류 처리 철학은 13.1 Error handling에 설명되어 있습니다.
알려지지 않은 청크 타입은 필수(critical) 청크가 아닌 한 오류로 취급되어서는 안 됩니다.
청크 타입은 네 바이트가 모두 41-5A 및 61-7A(16진수) 범위에 속하는지 확인하여 타당성을 검사할 수 있습니다. 이 검사는 인식되지 않은 청크 타입에 대해서만 수행하면 됩니다. 전체 데이터스트림 크기(파일 시스템 정보, HTTP 프로토콜 등에서 얻음)가 알려진 경우 청크 길이도 타당성 검사할 수 있습니다. CRC를 검사하지 않으면 누락되거나 추가된 바이트 또는 잘못된 청크 길이로 인해 디코더가 동기에서 벗어나 이후 데이터를 청크 헤더로 잘못 해석할 수 있습니다.
IHDR과 같은 고정 길이 청크의 경우, 예상치 못한 청크 길이는 오류로 처리해야 합니다. 이 명세의 향후 확장에서는 기존 청크에 새 필드를 추가하지 않고, 대신 새로운 정보는 새로운 청크 타입을 추가하여 전달할 것입니다.
알려진 청크의 필드에서 예상치 못한 값(예: IHDR 청크의 예기치 않은 압축 방식)은 검사되어 오류로 처리되어야 합니다. 그러나 예상치 못한 필드 값은 critical 청크에서만 치명적 오류로 처리하는 것이 권장됩니다. 보조(ancillary) 청크의 예상치 못한 값은 해당 청크 전체를 알려지지 않은 청크 타입처럼 무시하여 처리할 수 있습니다. (이 권장은 해당 청크의 CRC가 검증되었다고 가정합니다. CRC를 검사하지 않는 디코더에서는 예상치 못한 값을 손상된 데이터스트림의 징후로 처리하는 것이 더 안전합니다.)
표준 PNG 이미지는 압축 방식 0으로 압축되어야 합니다. IHDR 청크의 압축 방식 필드는 향후 표준화 또는 독점 변형을 위해 제공됩니다. 디코더는 이 바이트를 검사하고 인식할 수 없는 코드이면 오류를 보고해야 합니다. 자세한 내용은 10. Compression을 참조하세요.
PNG 데이터스트림은 명시적으로 타입이 지정된 청크들의 모음으로 구성됩니다. 명세에서 내용이 정의된 청크는 실제로 어떤 것이든 포함할 수 있으며 악의적인 코드도 포함할 수 있습니다. 마찬가지로 IEND 청크 이후의 데이터는 어떤 것이든 포함할 수 있으며 악성 코드를 포함할 수 있습니다. 이러한 악성 코드가 PNG 이미지를 디코딩한 결과로 수신자 컴퓨터에서 실행될 위험이 알려진 바는 없습니다. 그러나 악의적 애플리케이션이 무해해 보이는 이미지 파일 속에 이러한 코드를 숨기고 이후 실행할 수는 있습니다.
향후 정의될 청크 타입과 관련된 잠재적 보안 위험은 현재 시점에서 명시하기 어렵습니다. 향후 공개 청크를 정의할 때 보안 문제를 고려할 것입니다. 알려지지 않았거나 구현되지 않은 청크 타입과 관련된 추가 보안 위험은 없습니다. 그러한 청크는 무시되거나 많아야 다른 PNG 데이터스트림에 복사될 뿐입니다.
iTXt, tEXt, 및 zTXt 청크는 키워드와 평문으로 표시될 데이터들을 포함합니다. iCCP 및 sPLT 청크도 평문으로 표시될 키워드를 포함합니다. 디코더가 이러한 텍스트를 제어 문자(특히 ESC(escape) 문자)를 필터링하지 않고 그대로 표시하면 일부 시스템이나 터미널이 바람직하지 않거나 안전하지 않은 방식으로 동작할 수 있습니다. 이 위험을 피하기 위해 디코더는 제어 문자를 필터링하는 것이 권장됩니다. 관련 내용은 13.7 Text chunk processing을 참조하세요.
eXIf 청크의 경우 Exif 명세는 태그 "value offset" 포인터가 반드시 파일 내의 유효한 주소를 가리켜야 한다고 명시적으로 요구하지 않습니다. 이 요구는 암묵적입니다. (Exif IFD 구조를 설명하는 4.6.2항을 보십시오.) 그럼에도 불구하고 디코더는 잘못된 포인터를 만날 준비를 하고 이를 적절히 처리해야 합니다.
모든 청크는 길이 필드로 시작하므로 버퍼 오버플로우를 방지하는 디코더를 작성하기가 더 쉽습니다. 모든 청크 끝의 CRC는 우발적 손상 데이터에 대해 강력한 방어책을 제공합니다. PNG 시그니처 바이트는 일반적인 파일 전송 오류를 조기에 감지하게 합니다.
CRC를 검사하지 않는 디코더는 데이터 손상에 취약할 수 있습니다. 그러한 손상의 유일한 가능성 있는 결과는 이미지 내의 픽셀 표시 오류일 것입니다. 더 심각한 문제는 IHDR 청크의 CRC를 검사하지 않아 width나 height 필드가 손상되는 경우입니다. 자세한 내용은 13.2 Error checking을 참조하세요.
잘못 작성된 디코더는 청크가 최대 231-1 바이트까지 매우 클 수 있기 때문에 버퍼 오버플로우에 노출될 수 있습니다. 그러나 적절히 작성된 디코더는 큰 청크도 문제없이 처리할 것입니다.
일부 이미지 편집 도구는 과거에 단순히 편집된 영역의 알파 채널을 0으로 설정하여 삭제(redaction)를 수행했으며, 실제 이미지 데이터를 제거하지 않았습니다. 이러한 이미지를 시각적으로만 신뢰하는 사용자는 실제 이미지 데이터를 쉽게 복구할 수 있으므로 개인정보 위험이 있습니다.
마찬가지로 일부 이미지 편집 도구는 IHDR에서 너비와 높이만 다시 써서 잘라내기(clipping)를 수행했으며, 이미지 데이터는 새 너비와 높이를 넘어 확장되어 복구될 수 있습니다.
eXIf 청크를 포함한 이미지는 자동으로 포함된 데이터(예: 사진의 GPS 좌표)를 포함할 수 있으며, 사용자가 PNG 이미지에 이러한 데이터가 포함되어 있다는 사실을 모를 경우 개인정보 위험이 될 수 있습니다. (Exif를 포함하는 다른 이미지 형식들, 예: JPEG/JFIF도 동일한 개인정보 위험을 가집니다.)
디코더는 단순한 네 바이트 리터럴 비교로 청크 타입을 인식해야 합니다; 청크 타입에 대해 대소문자 변환을 수행하는 것은 잘못된 방법입니다. 보조 비트(ancillary bit)가 1인 알려지지 않은 청크를 만나는 디코더는 안전하게 그 청크를 무시하고 이미지를 계속 표시할 수 있습니다. 반면 보조 비트가 0인 알려지지 않은 청크(필수 청크)를 만나는 이미지를 추출하려는 디코더는 해당 이미지를 안전하게 해석할 수 없다는 것을 사용자에게 알려야 합니다.
디코더는 지정된 비트들을 수치적으로 검사하여 알려지지 않은 청크 타입의 속성을 검증해야 합니다. 문자가 대문자인지 소문자인지를 테스트하는 것은 비효율적이며, 로케일별 대소문자 정의를 사용하면 잘못될 수 있습니다.
예약 비트(reserved bit)가 1로 설정되어 있다고 해서 디코더가 오류를 표시해서는 안 됩니다. 향후 PNG 명세의 어떤 버전에서 이 비트에 의미를 부여할 수 있기 때문입니다. 이 비트가 설정된 청크는 다른 알려지지 않은 청크 타입과 동일하게 처리하면 됩니다.
청크 타입의 개인 비트(private bit)는 기능적 의미가 없고 W3C가 정의한 청크와 개인 정의된 청크 간의 충돌을 피하기 위해 사용되므로 디코더가 이를 검사할 필요는 없습니다.
모든 보조(ancillary) 청크는 선택 사항이며 디코더는 이를 무시할 수 있습니다. 그러나 디코더는 적절하고 가능하면 이러한 청크를 해석하는 것이 권장됩니다.
비정사각형 픽셀은 표현될 수 있습니다(참조: 11.3.4.3 pHYs Physical pixel dimensions), 그러나 뷰어가 이를 반드시 반영해야 하는 것은 아닙니다. 뷰어는 PNG 데이터스트림의 픽셀을 정사각형인 것처럼 표시할 수 있습니다.
디스플레이의 픽셀 종횡비가 PNG 데이터스트림에 정의된 물리적 픽셀 치수의 종횡비와 다를 경우, 뷰어는 올바른 표시를 위해 이미지를 재스케일하는 것이 강력히 권장됩니다.
pHYs 청크의 단위 지정자(unit specifier)가 0(단위 불명)인 경우, 디코더의 동작은 두
픽스-퍼-유닛(pixels-per-unit) 값의 비율에 따라 달라질 수 있지만 그 크기 자체에는 의존해서는 안 됩니다. 예를 들어 pHYs 청크에 (ppuX, ppuY, unit) = (2, 1, 0)가 들어 있는 것은
(1000, 500, 0)가 들어 있는 것과 동등합니다. 둘 다 이미지 픽셀이 너비의 두 배 높이임을 나타내는 유효한 신호입니다.
이미지와 디스플레이의 픽셀 종횡비 차이를 처리하는 합리적인 방법 중 하나는 가로 또는 세로 방향 중 하나만 이미지를 확장하는 것입니다. 스케일 팩터는 다음과 같은 부동소수점 계산으로 얻을 수 있습니다:
image_ratio = pHYs_ppuY / pHYs_ppuX
display_ratio = display_ppuY / display_ppuX
scale_factor_X = max(1.0, image_ratio/display_ratio)
scale_factor_Y = max(1.0, display_ratio/image_ratio)
이미지 영역을 유지하는 등의 다른 방법도 합리적일 수 있고 pHYs 청크를 무시하는 것도 허용되므로, 작성자는 모든 뷰잉 애플리케이션이 이 스케일링 방법을 사용할 것이라고 가정해서는 안 됩니다.
픽셀 종횡비 보정 외에도 뷰어는 가로 및 세로 방향 모두에서 추가적인 스케일링을 수행할 이유가 있을 수 있습니다. 예를 들어 표시 장치에 맞지 않을 정도로 큰 이미지를 축소하거나, 고해상도 프린터에 전송되는 이미지를 표시할 때와 같은 크기로 보이게 하기 위해 확장할 수 있습니다.
가능하면 PNG 디코더는 데이터스트림에서 발견된 모든 iTXt, tEXt, 및 zTXt 청크를 사용자에게 표시하는 방법을 제공해야 합니다. 디코더가 특정 텍스트 키워드를 인식하지 못하더라도 사용자가 이해할 수 있을 수 있습니다.
tEXt 및 zTXt 청크를 처리할 때 허용된 문자 이외의
문자를 만날 수 있습니다. 일부 문자는 안전하게 표시할 수 있지만(예: TAB, FF, CR — 16진수 09, 0C, 0D), 다른 문자들, 특히 ESC(16진수 1B) 문자는
디스플레이 하드웨어나 소프트웨어에 의해 예기치 않은 동작을 유발하여 보안 위험을 초래할 수 있습니다. 디코더는 tEXt
또는 zTXt 청크에서 발견되는 비Latin-1 문자를(개행 및 경우에 따라 TAB, FF를 제외하고) 직접 표시하려고
시도해서는 안 됩니다. 대신 무시하거나 "\nnn" 같은 가시적 표기법으로 표시해야 합니다. 관련 내용은 13.3 Security
considerations를 참조하세요.
iTXt 청크를 처리할 때 디코더는 Encoding Standard의 UTF-8 decode를 따라야 합니다.
인코더가 개행을 라인피드(16진수 0A)로 표현하는 것이 권장되지만, 디코더는 이에 의존하지 않는 것이 권장됩니다. CR, LF, CR-LF 등 일반적인 모든 개행 조합을 인식하여 각각을 단일 개행으로 표시하는 것이 가장 좋습니다. TAB은 적절한 수의 공백으로 확장하여 8의 배수 열로 맞출 수 있습니다.
비Latin-1 레거시 문자 인코딩을 사용하는 시스템에서 실행되는 디코더는 Latin-1 문자가 올바르게 표시되도록 문자 코드를 재매핑해야 합니다. 지원되지 않는 문자는 시스템에 적합한
대체 문자(U+FFFD REPLACEMENT CHARACTER, U+003F QUESTION MARK, 또는 U+001A SUB 등)로 교체하거나 "\nnn" 같은
가시 표기법으로 매핑해야 합니다. 문자는 디코딩 시스템에서 인쇄 가능한 문자일 때만 표시되어야 합니다. 일부 바이트 값은 디코딩 시스템에서 제어 문자로 해석될 수 있으므로 보안을 위해
그러한 시스템에서 실행되는 디코더는 이러한 제어 문자를 표시해서는 안 됩니다.
디코더는 인코더가 79자 초과의 라인을 생성하지 않도록 권장되더라도, 개행 문자 사이에 임의 개수의 인쇄 가능한 문자가 포함된 텍스트 청크를 표시할 준비가 되어 있어야 합니다.
이 명세에서 사용하는 압축 기법은 전체 압축 데이터스트림이 준비되기 전에 압축 해제를 시작할 수 있도록 요구하지 않습니다. 따라서 전체 압축 해제 데이터스트림이 준비되기 전에 표시를 시작할 수 있습니다. 향후 버전의 이 명세에서 사용되는 일반 목적 압축 방식이 이 특성을 갖지 않을 가능성은 극히 낮습니다.
IDAT 청크 경계는 의미론적 의미가 없으며 압축 데이터스트림의 어느 지점에나 나타날 수 있다는 점을 강조하는 것이 중요합니다. image data(예: 스캔라인 경계)와 deflate 블록 경계 또는 IDAT 청크 경계 사이에 필수적인 상관관계는 없습니다. 전체 image data는 하나의 zlib 데이터스트림으로 나타나며 이는 여러 개의 IDAT 청크에 저장될 수 있습니다. 디코더가 이것 이상을 가정하는 것은 잘못입니다. 일부 인코더 구현은 이러한 구조들 사이에 실제로 관계를 만들 수 있지만 디코더는 이에 의존해서는 안 됩니다.
필터의 효과를 되돌리기 위해 디코더는 같은 행의 이전 픽셀, 바로 위의 이전 행의 현재 픽셀, 그리고 위쪽 픽의 왼쪽 픽의 디코딩된 값을 사용할 필요가 있습니다. 이는 적어도 한 행 분량의 image data를 디코더가 항상 저장해야 함을 의미합니다. 일부 필터 타입은 이전 스캔라인을 참조하지 않더라도 디코더는 다음 스캔라인이 그것을 참조할 수 있으므로 각 스캔라인을 디코딩하면서 항상 저장해야 합니다. 자세한 내용은 7.3 Filtering을 참조하세요.
디코더는 인터레이스된 이미지를 읽을 수 있어야 합니다. 참조 이미지가 5열 미만 또는 5행 미만이면 일부 패스가 비어 있을 수 있습니다. 인코더와 디코더는 이 경우를 올바르게 처리해야 합니다. 특히 필터 타입 바이트는 비어 있지 않은 스캔라인에만 연관되며, 비어 있는 축소 이미지에는 필터 타입 바이트가 존재하지 않습니다.
느린 전송 링크에서 이미지를 수신할 때, 뷰어는 인터레이스 이미지를 점진적으로 표시하여 체감 성능을 향상시킬 수 있습니다. 이는 각 축소 이미지가 수신될 때까지 수신된 데이터를 기반으로 전체 이미지의 근사치를 표시하는 것을 의미합니다. 각 수신된 픽을 아직 전송되지 않은 아래쪽 및 오른쪽 픽 위치를 채우는 사각형으로 확장하여 표시하는 간단하지만 보기 좋은 효과를 얻을 수 있습니다. 이 과정은 다음의 ISO C 코드로 설명될 수 있습니다 [ISO_9899]:
/*
variables declared and initialized elsewhere in the code:
height, width
functions or macros defined elsewhere in the code:
visit(), min()
*/
int starting_row[7] = { 0, 0, 4, 0, 2, 0, 1 };
int starting_col[7] = { 0, 4, 0, 2, 0, 1, 0 };
int row_increment[7] = { 8, 8, 8, 4, 4, 2, 2 };
int col_increment[7] = { 8, 8, 4, 4, 2, 2, 1 };
int block_height[7] = { 8, 8, 4, 4, 2, 2, 1 };
int block_width[7] = { 8, 4, 4, 2, 2, 1, 1 };
int pass;
long row, col;
pass = 0;
while (pass < 7)
{
row = starting_row[pass];
while (row < height)
{
col = starting_col[pass];
while (col < width)
{
visit(row, col,
min(block_height[pass], height - row),
min(block_width[pass], width - col));
col = col + col_increment[pass];
}
row = row + row_increment[pass];
}
pass = pass + 1;
}
함수 visit(row,column,height,width)는 다음 전송된 픽셀을 얻어 지정된 행과 열의 좌상단 코너를 갖는 지정된 높이와 너비의 사각형을 픽셀의
색으로 칠합니다. 행과 열은 좌상단을 0,0으로 측정한다는 점을 유의하세요.
뷰어가 수신된 이미지를 배경 이미지와 병합하고 있다면, 받은 픽 위치만 칠하는 것이 더 편리할 수 있습니다(visit() 함수는 지정된 행과 열의 픽 하나만 설정하고
전체 사각형을 설정하지 않습니다). 이는 새 이미지가 점차적으로 기존 이미지를 대체하면서 "페이드 인" 효과를 생성합니다. 이 접근의 장점은 각 픽이 교체될 때 적절한 알파 또는 투명도
처리를 수행할 수 있다는 것입니다. 위에서 설명된 대로 사각형을 칠하면 나중에 해당 위치에 수신될 픽들이 완전 또는 부분적으로 투명한 것으로 판명될 경우 필요할 수 있는 배경 이미지 픽을
덮어써 버릴 수 있습니다. 이 문제는 배경 이미지가 오프스크린에 저장되지 않은 경우에만 발생합니다.
PNG의 보편적 교환성 목표를 달성하기 위해, 디코더는 모든 유형의 PNG 이미지를 수용해야 합니다: indexed-color, truecolor, 및 greyscale. 인덱스-컬러 디스플레이 하드웨어에서 실행되는 뷰어는 truecolor 이미지를 보기 위해 인덱스-컬러로 축소할 수 있어야 합니다. 이 과정을 "색상 양자화(color quantization)"라고 합니다.
색상 양자화의 간단하고 빠른 방법은 이미지를 고정 팔레트로 축소하는 것입니다. 균일한 색상 간격("color cubes")의 팔레트는 픽셀당 계산을 최소화하기 위해 보통 사용됩니다. 사진과 같은 이미지의 경우, 매끄러운 그라데이션에서 보기 흉한 계단 현상을 피하기 위해 디더링이 권장되지만, 디더링은 눈에 거슬리는 입자감을 도입할 수 있습니다.
렌더링 품질은 이미지에 특화된 팔레트를 사용하는 것으로 크게 향상될 수 있습니다. 색상 큐브는 특정 이미지에서 사용되지 않는 항목이 많은 편이기 때문입니다. 이 접근법은 먼저 팔레트를 선택하는 작업과, 다음으로 개별 픽셀을 가장 가까운 사용 가능한 색상으로 매핑하는 작업에서 더 많은 노력을 요구합니다. PNG는 인코더가 제안 팔레트를 제공하는 것을 허용하지만, 모든 인코더가 이를 수행하는 것은 아니며 제안 팔레트가 적합하지 않을 수도 있습니다(색상이 너무 많거나 너무 적을 수 있음). 따라서 고품질 뷰어는 팔레트 선택 루틴을 갖추고 있어야 합니다. 개별 픽셀을 적절한 속도로 팔레트 항목에 매핑하는 가장 현실적인 방법은 대규모 룩업 테이블인 경우가 많습니다.
색상 양자화의 구현은 수없이 많이 존재합니다. PNG 샘플 구현인 libpng (http://www.libpng.org/pub/png/libpng.html)에는
이를 위한 코드가 포함되어 있습니다.
디코더는 표시를 위해 PNG 데이터를 더 낮은 샘플 깊이(데이터 정밀도)로 축소하고자 할 수 있습니다. 예를 들어, 16비트 데이터는 현재 대부분의 디스플레이 하드웨어에서 사용하기 위해 8비트로 축소될 필요가 있습니다. 8비트 데이터를 5비트로 축소하는 것도 흔합니다.
가장 정확한 스케일링은 다음의 선형 방정식으로 달성됩니다
output = floor((input * MAXOUTSAMPLE / MAXINSAMPLE) + 0.5)
여기서
MAXINSAMPLE = (2sampledepth)-1
MAXOUTSAMPLE = (2desired_sampledepth)-1
약간 덜 정확한 변환은 단순히 (sampledepth - desired_sampledepth)만큼 오른쪽으로 시프트하는 것입니다. 예를 들어 16비트 샘플을 8비트로
줄이려면 저위 바이트를 버리면 됩니다. 많은 상황에서 시프트 방식은 표시 목적에 충분히 정확하며 확실히 훨씬 빠릅니다. (그러나 gamma 보정이 수행되는 경우, 샘플 재스케일링은
gamma 보정 룩업
테이블에 통합될 수 있으며, 이는 13.13
Decoder gamma handling에 예시되어 있습니다.)
디코더가 샘플을 확대해야 하는 경우(예: frame buffer가 PNG 이미지보다 더 큰 샘플 깊이를 가질 때)에는 12.4 Sample depth scaling에 설명된 것처럼 선형 스케일링 또는 왼쪽 비트 복제(left-bit-replication)를 사용해야 합니다.
sBIT 청크가 존재할 때는, 참조 image data를 sBIT에 지정된 샘플 깊이로 오른쪽 시프트하여 복원할 수 있습니다. 선형 스케일링이 원래 데이터를 반드시 재현하지는 않는다는 점에 유의하세요. 인코더가 데이터를 스케일 업할 때 선형 스케일링을 사용하도록 요구되지 않았기 때문입니다. 그러나 인코더는 최상위 비트를 보존하는 방법을 사용해야 하므로 시프트는 항상 작동합니다. 이는 시프트가 선형 스케일링보다 더 정확하다고 할 수 있는 유일한 경우입니다. 디코더는 sBIT 청크를 무시해도 됩니다; 저장된 이미지는 IHDR 청크에 표시된 샘플 깊이를 가진 유효한 PNG 데이터스트림입니다. 그러나 표시를 위해 원래 샘플을 복원한 다음 디스플레이에 맞게 스케일하는 데 sBIT를 사용하는 것이 무시하는 것보다 더 정확한 표시를 제공하는 경우가 많습니다.
투명 픽셀을 감지하기 위해 tRNS 청크 값과 픽셀 값을 비교할 때, 비교는 정확히 수행되어야 합니다. 따라서 투명 픽 검사(transparent pixel detection)는 샘플 정밀도를 줄이기 전에 수행되어야 합니다.
감마 문제에 대한 간단한 소개는 C. Gamma and chromaticity를 참조하십시오.
완전한 색 관리를 수행할 수 있는 뷰어는 여기서 설명된 것보다 더 정교한 계산을 수행할 것입니다.
이미지 표시 프로그램이 정확한 톤 재현을 생성하려면 샘플과 표시 출력 간의 관계 및 표시 시스템의 전달 함수를 고려해야 합니다. 이는 다음을 계산함으로써 수행할 수 있습니다:
sample = integer_sample / (2sampledepth - 1.0)
display_output = sample1.0/gamma
display_input = inverse_display_transfer(display_output)
framebuf_sample = floor((display_input * MAX_FRAMEBUF_SAMPLE)+0.5)
여기서 integer_sample은 데이터스트림의 샘플 값이고, framebuf_sample은 frame buffer에 쓸 값이며, MAX_FRAMEBUF_SAMPLE은 프레임 버퍼 샘플의 최대값(8비트의 경우 255, 5비트의 경우 31 등)입니다. 첫 줄은 정수 샘플을 0.0에서 1.0 범위의 정규화된 부동소수점 값으로 변환하고, 둘째 줄은 원하는 표시 출력 밝기에 비례하는 값으로 변환하며, 셋째 줄은 표시 시스템의 전달 함수를 고려하고, 넷째 줄은 정수 프레임 버퍼 샘플로 변환합니다. 0을 양의 지수로 거듭제곱하면 0입니다.
둘째와 셋째 줄 사이에 단계(step)를 삽입하여 실제 시청 조건과 기준 시청 조건 간의 차이를 조정할 수 있습니다. 그러나 이 조정은 베일링 글레어(veiling glare), 블랙 매핑, 색상 외관 모델을 고려해야 하므로 단일 거듭제곱 함수로 잘 근사할 수 없습니다. 이러한 계산은 여기서 설명하지 않습니다. 시청 조건을 무시하면 오차는 보통 작습니다.
표시 전달 함수는 보통 지수 display_exponent을 갖는 거듭제곱 함수로 근사될 수 있으며, 이 경우 둘째와 셋째 줄은 병합되어:
display_input = sample1.0/(gamma * display_exponent) = sampledecoding_exponent
으로 하여 하나의 거듭제곱 계산만 수행할 수 있습니다. 컬러 이미지의 경우 R, G, B 각각에 대해 전체 계산을 수행합니다.
gamma value는 gAMA 청크에서 직접 가져올 수 있습니다. 또는 애플리케이션은 사용자가 표시된 이미지의 외관을 조정할 수 있도록 gamma value에 영향을 주게 할 수 있습니다. 예를 들어 사용자가 기본값 1.0인 매개변수 user_exponent을 수동으로 설정하고 애플리케이션은 다음과 같이 설정할 수 있습니다:
gamma = gamma_from_file / user_exponent
decoding_exponent = 1.0 / (gamma * display_exponent)
= user_exponent / (gamma_from_file * display_exponent)
사용자는 중간 톤을 어둡게 하려면 user_exponent를 1보다 크게, 밝게 하려면 1보다 작게 설정할 것입니다.
값이 0인 gAMA 청크는 의미가 없지만 실수로 나타날 수 있습니다. 디코더는 이를 무시해야 하며, 편집기는 이를 폐기하고 사용자에게 경고를 발행할 수 있습니다.
모든 픽셀마다 초월 함수 계산을 수행할 필요는 없습니다. 대신 모든 가능한 샘플 값에 대해 올바른 출력 값을 제공하는 룩업 테이블을 계산할 수 있습니다. 이것은 이미지당 8비트 정확도의 경우 256번의 계산만 필요하며, 픽셀당 계산을 여러 번 하는 것보다 훨씬 효율적입니다. 인덱스-컬러 이미지의 경우 팔레트에 대한 일회성 보정으로 충분하며, 투명도를 사용하고 있고 비균일한 배경에 대해 표시하는 경우가 아니라면 그 정도의 처리로 충분합니다.
부동소수점 계산이 불가능한 경우에도 gamma 보정 테이블은 정수 산술과 미리 계산된 로그 테이블을 사용하여 생성할 수 있습니다. 예시 코드는 [PNG-EXTENSIONS]에 나와 있습니다.
들어오는 이미지의 gamma value(gAMA, sRGB, 및 iCCP가 모두 없는 경우)가 알려지지 않은 경우, 단독 이미지 뷰어는 가능성 있는 기본 gamma value를 선택하되, 결과가 너무 어둡거나 너무 밝으면 사용자가 새 값을 선택할 수 있게 해야 합니다. 기본 gamma value는 이미지가 인터넷에서 왔는지 로컬 시스템에서 왔는지 등의 다른 정보에 따라 달라질 수 있습니다. 일관성을 위해 HTML과 같은 문서 형식이나 SVG 같은 벡터 그래픽의 뷰어는 알 수 없는 gamma value를 가진 포함 또는 연결된 PNG 이미지를 다른 태그 없는 이미지들과 동일하게 처리해야 합니다.
실무에서는 어떤 표시 지수(display exponent)를 사용해야 하는지 결정하기 어려운 경우가 많습니다. 내장된 gamma 보정이 없는 시스템에서는 표시 지수가 전적으로 CRT에 의해 결정됩니다. 상세한 보정 측정값이 없는 한 표시 지수로 2.2를 사용해야 합니다.
많은 현대 프레임 버퍼는 gamma 보정을 수행하는 룩업 테이블을 가지고 있으며, 이러한 시스템에서는 표시 지수 값은 룩업 테이블과 CRT의 지수의 결합입니다. 뷰어 애플리케이션 내부에서 룩업 테이블의 내용을 알 수 없을 수도 있으므로 사용자가 표시 시스템의 지수 값을 제공하도록 요청해야 할 수 있습니다. 불행히도 제조사마다 룩업 테이블에 무엇을 넣을지 지정하는 방식이 다르므로 시스템 gamma value 해석은 시스템에 따라 달라집니다.
실제 디스플레이의 응답은 표시 지수 하나로 완전히 설명될 수 없을 만큼 더 복잡합니다. 만약 전압 입력에 따른 모니터의 광 출력에 대한 실제 측정값이 있다면 위 계산의 셋째와 넷째 줄을 이러한 측정값 룩업으로 대체하여 원하는 밝기를 가장 가깝게 제공하는 실제 frame buffer 값을 찾을 수 있습니다.
색 문제에 대한 참조는 C. Gamma and chromaticity를 보십시오.
많은 경우 PNG 데이터스트림의 image data는 장치 종속 RGB 값으로 취급되어 적절한 gamma 보정만을 적용한 채 그대로 표시됩니다. 이는 PNG 이미지를 가장 빠르게 표시하는 방법입니다. 그러나 뷰어가 원저작자가 사용한 정확히 동일한 표시 하드웨어를 사용하지 않는 한, 특히 어두운 색상이나 중립에 가까운 색상에서는 원저작자가 본 것과 정확히 동일한 색상이 나오지 않을 수 있습니다. cHRM 청크는 단지 gamma 보정만으로 제공되는 것보다 더 밀접한 색상 매칭을 가능하게 합니다.
cHRM 데이터는 이미지 데이터를 RGB에서 XYZ로 변환하고 이어서 CIE LAB 같은 지각적으로 선형인 색 공간으로 변환하는 데 사용될 수 있습니다. 색상들은 분할되어 최적의 팔레트를 생성할 수 있는데, 이는 CIE LAB에서 두 색상 간의 기하학적 거리가 사람들이 인식하는 색상 차이와 강하게 관련이 있기 때문입니다(예: RGB나 XYZ 공간과는 달리). 생성된 팔레트를 다시 RGB 색 공간으로 변환하면 표시하거나 PLTE 청크에 쓸 수 있습니다.
이미지 처리 애플리케이션의 일부인 디코더는 또한 분석을 위해 이미지 데이터를 CIE LAB 공간으로 변환할 수 있습니다.
제품 설계, 과학적 시각화, 의학, 건축, 광고 등 색상 충실도가 중요한 응용에서는 PNG 디코더가 소스 RGB에서 이미지가 표시될 모니터의 디스플레이 RGB 공간으로 이미지를 변환할 수 있습니다. 이는 소스 RGB → XYZ 행렬과 XYZ → 디스플레이 RGB 행렬을 계산한 다음 이들을 결합하여 전체 변환을 생성하는 것을 포함합니다. PNG 디코더는 가멧 매핑을 구현할 책임이 있습니다.
Color Management System(CMS)을 갖춘 플랫폼에서 실행되는 디코더는 image data, gAMA, 및 cHRM 값을 CMS에 전달하여 표시 또는 추가 처리를 할 수 있습니다.
색상 인쇄 기능을 제공하는 PNG 디코더는 Level 2 PostScript의 기능을 사용하여 보정된 RGB 공간 또는 XYZ와 같은 장치 독립 색 공간에서 이미지 데이터를 지정할 수 있습니다. 이는 단순한 RGB→CMYK 변환보다 더 나은 색상 충실도를 제공합니다. PostScript Language Reference 매뉴얼은 예시를 제공합니다. 그러한 디코더는 소스 RGB( cHRM 청크에 명시된)와 대상 프린터 사이의 가멧 매핑을 구현할 책임이 있으며, PostScript 인터프리터가 필요한 색상을 생성할 책임을 집니다.
PNG 디코더는 cHRM 데이터를 사용하여 컬러 이미지의 정확한 그레이스케일 표현을 계산할 수 있습니다. RGB에서 그레이로의 변환은 XYZ의 Y(휘도) 성분을 계산하는 것과 같으며, 이는 R, G, B 값의 가중 합입니다. 가중치는 모니터 유형, 즉 cHRM 청크의 값에 따라 달라집니다. 디코더는 cHRM 청크가 없는 PNG 데이터스트림에 대해서도 이 작업을 수행할 수 있습니다. 이 경우 합리적인 기본값으로는 CCIR 709 프라이머리를 사용하는 것이 권장됩니다. 원래의 NTSC 프라이머리는 PNG 이미지가 실제로 그러한 모니터에 맞춰 색 보정된 경우가 아니라면 사용해서는 안 됩니다.
bKGD 청크로 지정된 배경 색은 일반적으로 이미지 주변의 사용되지 않는 화면 공간을 채우는 데 사용되며, 이미지 내의 투명 픽셀도 채우는 데 사용됩니다. (따라서 이미지가 투명도를 사용하지 않더라도 bKGD는 유효하고 유용합니다.) bKGD 청크가 없으면 뷰어는 적절한 배경 색을 결정해야 합니다. 다른 정보가 없을 때, 8비트 sRGB 색 공간에서 153과 같은 중간 회색이 합리적인 선택이 될 것입니다. 투명한 검정 또는 흰색 텍스트와 어두운 드롭 섀도우와 같은 일반적인 요소들은 이 배경에서 모두 읽기 쉬울 것입니다.
웹 브라우저와 같이 이미 이미지를 표시할 특정 배경을 가진 뷰어는 bKGD 청크를 무시하여 자체 선호하는 배경 색이나 배경 이미지로 bKGD를 대체해야 합니다.
bKGD 청크로 지정된 배경 색은 tRNS 청크가 지정한 색(또는 인덱스-컬러 이미지의 경우 tRNS가 투명으로 표시한 팔레트 인덱스)과 일치하더라도 투명으로 간주되어서는 안 됩니다. 그렇지 않으면 "배경 뒤에 있는 것"을 상정해야만 그 위에 합성(composite)할 수 있게 됩니다. 배경 색은 배경으로 사용되거나 무시될 뿐이며, PNG 이미지와 다른 배경 사이의 중간 레이어로 간주되지 않습니다.
실제로 bKGD와 tRNS 청크가 동일한 색을 지정하는 경우가 흔할 것입니다. 이 경우 투명도 처리를 구현하지 않는 디코더도 부분 투명 픽이 없을 때 의도된 표시를 제공할 수 있습니다.
알파 채널은 전경 이미지를 배경 이미지 위에 합성(composite)하는 데 사용될 수 있습니다. PNG 데이터스트림은 전경 이미지와 투명도 마스크를 정의하지만 배경 이미지는 정의하지 않습니다. PNG 디코더는 이 가장 일반적인 경우를 반드시 지원해야 하는 것은 아닙니다. 대부분은 단일 배경 색에 대해 합성을 지원할 수 있을 것으로 예상됩니다.
합성된 샘플 값을 계산하는 방정식은 다음과 같습니다:
output = alpha * foreground + (1-alpha) * background
여기서 alpha 및 입력과 출력 샘플 값들은 0에서 1 사이의 분수로 표현됩니다. 이 계산은 강도 샘플(intensity samples)으로 수행되어야 하며, gamma 인코딩된 샘플로 수행해서는 안 됩니다. 컬러 이미지의 경우 R, G, B 샘플 각각에 대해 별도로 계산됩니다.
다음 코드는 전경 이미지를 배경 이미지에 대해 합성하는 일반적인 경우를 보여줍니다. 이 코드는 배경 이미지의 원래 픽셀 데이터가 사용 가능하고 출력이 표시를 위한 frame buffer에 쓰여진다는 가정을 합니다. 다른 변형들도 가능하며 코멘트에 설명이 있습니다. 이 코드는 전경 이미지와 배경 이미지의 샘플 깊이와 gamma values가 서로 다를 수 있고 표시 시스템에 적합하지 않을 수도 있음을 허용합니다. 실제로는 검사 없이 동등성을 가정해서는 안 됩니다.
이 코드는 ISO C 표준에 따른 것으로, 아래 주석에서 참조하기 쉽게 행 번호가 추가되어 있습니다.
01 int foreground[4]; /* 이미지 픽셀: R, G, B, A */
02 int background[3]; /* 배경 픽셀: R, G, B */
03 int fbpix[3]; /* 프레임 버퍼 픽셀 */
04 int fg_maxsample; /* 전경 최대 샘플 */
05 int bg_maxsample; /* 배경 최대 샘플 */
06 int fb_maxsample; /* 프레임 버퍼 최대 샘플 */
07 int ialpha;
08 float alpha, compalpha;
09 float gamfg, linfg, gambg, linbg, comppix, gcvideo;
/* 데이터와 프레임 버퍼의 최대 샘플 값 얻기 */
10 fg_maxsample = (1 << fg_sample_depth) - 1;
11 bg_maxsample = (1 << bg_sample_depth) - 1;
12 fb_maxsample = (1 << frame_buffer_sample_depth) - 1;
/*
* 정수 버전의 알파 얻기.
* 불투명 또는 완전 투명 특수 경우 검사;
* 그런 경우 합성이 필요 없음.
*
* 전체 감마 디코드/보정 과정은 부동소수점으로 보여주지만,
* 실제로는 룩업 테이블로 수행될 가능성이 큽니다.
*/
13 ialpha = foreground[3];
14 if (ialpha == 0) {
/*
* 이 지점의 전경 이미지는 투명입니다.
* 배경 이미지가 이미 프레임 버퍼에 있다면 할 일이 없습니다.
*/
15 ;
16 } else if (ialpha == fg_maxsample) {
/*
* 전경 픽셀을 프레임 버퍼로 복사.
*/
17 for (i = 0; i < 3; i++) {
18 gamfg = (float) foreground[i] / fg_maxsample;
19 linfg = pow(gamfg, 1.0 / fg_gamma);
20 comppix = linfg;
21 gcvideo = pow(comppix, 1.0 / display_exponent);
22 fbpix[i] = (int) (gcvideo * fb_maxsample + 0.5);
23 }
24 } else {
/*
* 합성이 필요합니다.
* 부동소수점 알파 및 그 보수를 얻습니다.
* 주의: 알파는 항상 선형입니다; 감마의 영향을 받지 않습니다.
*/
25 alpha = (float) ialpha / fg_maxsample;
26 compalpha = 1.0 - alpha;
27 for (i = 0; i < 3; i++) {
/*
* 전경과 배경을 부동소수점으로 변환한 후 감마 인코딩을 되돌립니다.
*/
28 gamfg = (float) foreground[i] / fg_maxsample;
29 linfg = pow(gamfg, 1.0 / fg_gamma);
30 gambg = (float) background[i] / bg_maxsample;
31 linbg = pow(gambg, 1.0 / bg_gamma);
/*
* 합성.
*/
32 comppix = linfg * alpha + linbg * compalpha;
/*
* 표시를 위한 감마 보정.
* 정수 프레임 버퍼 픽셀로 변환.
*/
33 gcvideo = pow(comppix, 1.0 / display_exponent);
34 fbpix[i] = (int) (gcvideo * fb_maxsample + 0.5);
35 }
36 }
변형:
/*
* 출력 데이터스트림에 저장하기 위해 감마 인코딩.
* 정수 샘플 값으로 변환.
*/
gamout = pow(comppix, outfile_gamma);
outpix[i] = (int) (gamout * out_maxsample + 0.5);또한, 알파가 0일 때 배경 픽셀도 처리해야
하므로 단순히 픽셀을 건너뛰는 대신 배경 픽셀을 처리하도록 15행을 17-23행의 배경 처리 버전으로 대체해야 합니다.
/*
* 프레임 버퍼 값을 강도 샘플로 변환.
*/
gcvideo = (float) fbpix[i] / fb_maxsample;
linbg = pow(gcvideo, display_exponent);하지만 반올림 오류가 발생할 수 있으므로
가능하면 원래 배경 픽을 사용하는 것이 좋습니다.
참고: 부동소수점에서는 입력 샘플 값이 0에서 1 사이로 보장되고 합성은 항상 입력 값 사이의 결과(포함)만을 낳으므로 오버플로우나 언더플로우 검사가 필요 없습니다. 정수 산술을 사용할 경우 오버플로우나 언더플로우가 없도록 반올림 오차 분석이 필요할 수 있습니다.
풀 알파 채널을 가진 PNG 이미지를 표시할 때는 최소한 검은색 같은 어떤 배경에 대해 이미지를 합성할 수 있어야 합니다. 알파 채널을 무시하면 사전 곱해진(associated-alpha) 표현에서 변환된 PNG 이미지는 올바르게 보이지 않습니다. (물론 알파 채널이 별도의 투명 마스크라면 알파를 무시하는 것이 숨겨진 부분의 이미지를 복구하는 데 유용한 옵션이 될 수 있습니다.)
디코더가 실제 합성 로직을 구현하지 않더라도 알파 값이 0과 1만 포함된 이미지를 처리하는 것은 간단합니다. (이는 greyscale 및 truecolor PNG 데이터스트림에서 tRNS 청크를 사용하는 경우 암시적으로 성립합니다; 인덱스-컬러 PNG 데이터스트림의 경우 tRNS 청크가 0과 255 이외의 값을 포함하는지 확인하기 쉽습니다.) 이 단순한 경우에는 투명 픽은 배경 색으로 대체되고 다른 픽은 변경되지 않습니다.
디코더가 이러한 정도의 투명성 처리만 제공한다면, 풀 알파 채널을 처리할 때 모든 비영(非零) 알파 값을 완전 불투명으로 처리하거나 디더링하여 처리해야 합니다. 어느 쪽도 사전 곱(alpha-associated) 형식에서 변환된 이미지에 대해 매우 좋은 결과를 주지는 않지만 아무 것도 하지 않는 것보다는 낫습니다. 전체 알파를 이진 알파로 디더링하는 것은 그레이스케일을 흑백으로 디더링하는 것과 매우 유사합니다. 단, 완전 투명 및 완전 불투명 픽은 디더링으로 인해 변경되지 않아야 합니다.
인덱스-컬러 하드웨어에서 truecolor 이미지를 출력하려 하거나, 또는 팔레트가 frame buffer에 비해 너무 큰 인덱스-컬러 이미지를 표시하려는 뷰어의 경우, 인코더가 하나 이상의 제안 팔레트(sPLT 청크)를 제공했을 수 있습니다. 크기나 이름 등을 기준으로 적합한 제안 팔레트가 발견되면 PNG 디코더는 해당 팔레트를 사용할 수 있습니다. 디코더가 필요로 하는 샘플 깊이와 다른 샘플 깊이를 가진 제안 팔레트는 샘플 깊이 재스케일링으로 변환할 수 있습니다(참조: 13.12 Sample depth rescaling).
배경이 단색인 경우, 뷰어는 이미지를 그 단색 배경과 함께 composite하고 제안된 팔레트에 대해 그 결과 이미지를 양자화하여 RGB 팔레트를 얻어야 합니다. 이미지가 투명도를 사용하고 배경이 단색이 아닌 경우에는 제안 팔레트가 유용하지 않을 가능성이 높습니다.
truecolor 이미지의 경우, 제안 팔레트가 PLTE 청크로 제공될 수도 있습니다. 이미지에 tRNS 청크가 있고 배경이 단색인 경우, 뷰어는 원하는 배경 색상에 맞게 제안 팔레트를 조정해야 합니다. 이를 위해서는 tRNS 색상과 가장 가까운 팔레트 항목을 원하는 배경 색으로 교체하거나, 뷰어가 PLTE 항목 수보다 더 많은 색을 처리할 수 있다면 배경 색에 대한 팔레트 항목을 추가할 수 있습니다.
color type 6(truecolor with alpha) 이미지의 경우, 어떤 PLTE 청크도 bKGD 청크로 지정된 단일 배경 색에 대한 표시를 염두에 두고 설계되었어야 합니다. 뷰어가 다른 배경을 사용하려 하거나 bKGD 청크가 없으면 팔레트를 무시하는 것이 바람직할 것입니다. 뷰어는 원래 의도된 배경과 다른 배경에 대해 제안 팔레트를 사용할 수 있지만, 그 결과가 좋지 않을 수 있습니다.
뷰어가 투명한 truecolor 이미지를 단일 색보다 복잡한 배경 위에 표시한다면, 제안 팔레트는 합성(composite)된 이미지에 대해 최적이 아닐 가능성이 높습니다. 이 경우에는 truecolor PNG 이미지와 배경 이미지에 대해 먼저 truecolor 합성 단계를 수행한 다음, 그 결과 이미지를 색상 양자화하는 것이 최선입니다.
truecolor PNG 데이터스트림에서 PLTE와 sPLT 청크가 모두 나타나면, PNG 디코더는 둘이 제안하는 팔레트들 중에서 선택할 수 있으며 위에 설명된 서로 다른 투명도 의미론을 고려해야 합니다.
sPLT 및 hIST 청크의 빈도 정보는 뷰어가 PNG 데이터스트림에 사용된 만큼의 색을 제공할 수 없을 때 유용합니다. 뷰어가 몇 개의 색만 부족한 경우에는 보통 팔레트에서 가장 적게 사용된 색을 제거하는 것으로 충분합니다. 색 수를 크게 줄여야 할 때는 기존 팔레트의 부분집합을 쓰려고 하기보다 전혀 새로운 대표 색들을 선택하는 것이 낫습니다. 이는 새로운 색상 양자화 단계를 수행하는 것과 같지만, 기존 팔레트와 히스토그램을 입력 데이터로 사용하면 IDAT 청크의 image data를 다시 스캔하지 않아도 됩니다.
제안 팔레트가 제공되지 않는 경우, 디코더는 자체 팔레트를 개발할 수 있지만 이는 IDAT 청크의 image data를 한 번 더 통과해야 하는 비용이 듭니다. 또는 기본 팔레트(보통 색상 큐브)를 사용할 수도 있습니다.
또한 12.5 Suggested palettes를 참조하십시오.
저자들은 새로운 청크 타입을 도입하기 전에 이 명세와 [PNG-EXTENSIONS] 모두에서 기존 청크 타입을 살펴보는 것이 권장됩니다. [PNG-EXTENSIONS]의 청크 타입은 이 명세에 정의된 것보다 지원 범위가 좁을 것으로 예상됩니다.
PNG editor의 예로는 텍스트 청크를 추가하거나 수정하는 프로그램과 truecolor PNG 데이터스트림에 제안 팔레트를 추가하는 프로그램이 있습니다. 일반 이미지 편집기는 이미지를 읽을 때 인식하지 못한 모든 정보를 버리는 경향이 있으므로 PNG editor로 보지 않습니다.
PNG에 새 청크 타입을 추가할 수 있도록 하려면 모든 청크 타입에 대한 정렬(ordering) 요구사항에 관한 규칙을 정해야 합니다. 그렇지 않으면 PNG editor가 알 수 없는 청크를 만났을 때 무엇을 해야 할지 알 수 없습니다.
예시: 가정으로 새 보조(ancillary) 청크 타입이 safe-to-copy이며 PLTE가 존재하면 그 뒤에 나타나야 한다고 합시다. 어떤 프로그램이 그 새 청크를 인식하지 못한 채 PLTE를 추가하려 하면 PLTE를 잘못된 위치, 즉 새 청크 뒤에 삽입할 수 있습니다. 이러한 문제는 알려지지 않은 청크를 모두 버리도록 PNG 편집기에 요구하면 방지할 수 있지만, 이는 매우 바람직하지 않은 해결책입니다. 대신 PNG는 보조 청크가 이런 식의 정렬 제한을 갖지 않도록 요구합니다.
이런 유형의 문제를 방지하면서도 향후 확장을 허용하기 위해, PNG editors의 동작과 청크의 허용된 정렬 요구사항 모두에 제약을 둡니다. safe-to-copy 비트는 수정 중인 데이터스트림에서 인식되지 않은 청크를 적절히 처리하는 방법을 정의합니다.
청크 정렬을 규정하는 규칙은 다음과 같습니다.
이 규칙들은 입력 데이터스트림에서 출력 데이터스트림으로 청크를 복사하는 관점에서 표현되었지만, PNG 데이터스트림을 제자리에서 수정하는 경우에도 자명하게 적용됩니다.
또한 5.4 Chunk naming conventions를 참조하세요.
이미지 데이터를 변경하지 않는 PNG editors는 tIME 청크를 변경해서는 안 됩니다. tEXt, zTXt, 및 iTXt 청크의 Creation Time 키워드는 사용자 제공 시간을 위해 사용될 수 있습니다.
Critical 청크는 임의의 정렬 요구를 가질 수 있습니다. 왜냐하면 PNG editors는 알 수 없는 critical 청크를 만나면 종료해야 하기 때문입니다. 예를 들어 IHDR은 항상 가장 먼저 나타나야 한다는 특정 정렬 규칙을 갖습니다. PNG 에디터나 어떤 PNG 작성 프로그램이든 자신이 생성할 수 있는 모든 critical 청크 타입에 대한 정렬 규칙을 알고 따르는 것이 요구됩니다.
보조 청크 타입에 대한 가장 엄격한 정렬 규칙은 다음과 같습니다:
특정 보조 청크 타입에 대한 실제 정렬 규칙은 더 약할 수 있습니다. 예를 들어 표준 보조 청크 타입의 정렬 규칙은 5.6 Chunk ordering을 참조하세요.
디코더는 어떤 보조 청크의 위치에 대해 청크 정렬 규칙에서 명시된 것 이상을 가정해서는 안 됩니다. 특히 특정 보조 청크 타입이 다른 보조 청크에 대해 특정 위치에 항상 존재한다고 가정하는 것은 결코 유효하지 않습니다.
예시: 어떤 특정한 개인용 보조 청크가 항상 IEND 직전이라고 가정하는 것은 안전하지 않습니다. 특정 애플리케이션이 항상 그 위치에 쓰더라도, 다른 PNG editor가 그 뒤에 다른 보조 청크를 삽입했을 수 있습니다. 그러나 그 청크가 IDAT와 IEND 사이 어딘가에 남아 있을 것이라는 것은 안전하게 가정할 수 있습니다.
비규범(non-normative)으로 표시된 절들뿐만 아니라, 이 명세서의 모든 작성 지침, 도표, 예제 및 주석은 비규범입니다. 이 명세서의 다른 모든 내용은 규범적(normative)입니다.
본 문서에서 사용된 핵심 단어 MAY, MUST, SHALL, SHOULD, 및 SHOULD NOT 은 BCP 14 [RFC2119] [RFC8174] 에 설명된 대로, 오직 모두 대문자로 나타날 때에 한해 해석되어야 합니다.
이 절은 PNG 데이터스트림, PNG 인코더, PNG 디코더 및 PNG 편집기의 적합성에 대해 다룹니다.
이 절의 명세가 가지는 주요 목적은 다음과 같습니다:
적합성은 PNG 데이터스트림 및 PNG 인코더, 디코더, 편집기에 대해 정의됩니다.
이 절은 PNG 데이터스트림과 구현 요구사항을 다루며 PNG 인코더, PNG 디코더 및 PNG 편집기에 허용되는 차이의 범위를 포함합니다. 이 절은 인코더, 디코더 또는 편집기의 환경적, 성능적 또는 자원 요구사항을 직접적으로 다루지는 않습니다.
이 절의 범위는 PNG 데이터스트림의 공개 교환을 위한 규칙으로 한정됩니다.
다음 조건들이 충족되면 PNG 데이터스트림은 이 명세에 적합하다고 간주됩니다.
다음 조건을 만족하면 PNG 인코더는 이 명세에 적합합니다.
다음 조건을 만족하면 PNG 디코더는 이 명세에 적합합니다.
PNG 편집기가 다음 조건을 만족하면 이 명세에 적합합니다.
이 항목은 최상위 타입 image 아래의 기존 image/png 인터넷 미디어 타입을 갱신합니다. 이 부록은 BCP 13 및 W3CRegMedia를 준수합니다.
PNG 문서는 명시적으로 타입이 지정된 "청크"들의 모음으로 구성됩니다. PNG 명세에서 정의된 각 청크 타입에 대해(gIFx를 제외하고), 해당 청크들이 가진 유일한 영향은 수신자의 디스플레이나 프린터에 이미지를 렌더링하도록 하는 것입니다.
gIFx 청크 타입은 애플리케이션 확장 데이터를 캡슐화하는 데 사용되며, 그 데이터의 일부 사용은 보안 위험을 제기할 수 있지만 알려진 위험은 없습니다. 마찬가지로 향후 청크 타입과 관련된 보안 위험은 평가하기 어렵습니다. 그러나 PNG 워킹 그룹은 "실행 가능한" 데이터를 포함한 청크가 등록되는 것을 허용하지 않으려 합니다.
tEXt, iTXT, 및 zTXt 텍스트 청크는 댓글 등으로 표시될 수 있는 데이터를 포함합니다. 일부 운영체제나 터미널은 제어 문자가 포함된 텍스트를 표시할 때 키 재매핑, 파일 생성 등과 같은 동작을 수행할 수 있으므로, 이 때문에 명세서는 텍스트 청크를 직접 표시하기 전에 제어 문자를 필터링할 것을 권장합니다.
PNG 형식은 파일 전송 오류의 조기 검출을 용이하게 설계되었으며, 청크에 포함된 데이터 무결성을 보장하기 위해 순환 중복 검사(CRC)를 사용합니다.
이 등록은 이전 등록을 갱신합니다:
이 부록은 BCP 13 및 W3CRegMedia를 준수합니다.
APNG 문서는 명시적으로 타입이 지정된 "청크"들의 모음으로 구성됩니다. PNG 명세에서 정의된 각 청크 타입에 대해(gIFx를 제외하고), 해당 청크들이 가진 유일한 영향은 수신자의 디스플레이에 애니메이션 이미지를 렌더링하도록 하는 것입니다.
gIFx 청크 타입은 애플리케이션 확장 데이터를 캡슐화하는 데 사용되며, 그 데이터의 일부 사용은 보안 위험을 제기할 수 있지만 알려진 위험은 없습니다. 마찬가지로 향후 청크 타입과 관련된 보안 위험은 평가하기 어렵습니다. 그러나 PNG 워킹 그룹은 "실행 가능한" 데이터를 포함한 청크가 등록되는 것을 허용하지 않으려 합니다.
tEXt, iTXt 및 zTXt 텍스트 청크는 댓글 등으로 표시될 수 있는 데이터를 포함합니다. 일부 운영체제나 터미널은 제어 문자가 포함된 텍스트를 표시할 때 키 재매핑, 파일 생성 등과 같은 동작을 수행할 수 있으므로, 이 때문에 명세서는 텍스트 청크를 직접 표시하기 전에 제어 문자를 필터링할 것을 권장합니다.
PNG 형식은 파일 전송 오류의 조기 검출을 용이하게 설계되었으며, 청크에 포함된 데이터 무결성을 보장하기 위해 순환 중복 검사(CRC)를 사용합니다.
관련 없는 정적 이미지 청크와 애니메이션 이미지 청크를 포함하는 APNG 파일을 만들면, APNG 포맷을 지원하지 않는 도구를 사용하는 사람들은 정적 이미지만 보게 되어 추가 콘텐츠가 있다는 사실을 알지 못할 수 있습니다. 이는 예를 들어 검열을 회피하는 데 이용될 수 있습니다.
image/apng는 2015년 이후 널리 등록되지 않은 상태로 사용되어 왔습니다. Animated PNG는 2022년까지 공식 PNG 명세의 일부가 아니었습니다. 이 등록과 PNG 명세(3판)는 이미 널리 배포된 실제 상황과 공식 문서를 일치시키는 역할을 합니다.
이 절은 비규범적입니다.
다음은 프라이빗 청크를 정의할 때의 지침을 명시합니다:
이 절은 비규범적입니다.
gamma value는 이미지 캡처 및 재생에서 만나게 되는 특정 비선형 전달 함수에 대한 근사를 설명하는 데 사용되는 수치 매개변수입니다. gamma value는 거듭제곱 법칙 함수의 지수입니다. 예를 들어 다음 함수가 있습니다:
intensity = (voltage + constant)exponent
이는 CRT 디스플레이의 비선형성을 모델링하는 데 사용됩니다. 본 국제 표준에서는 상수를 0으로 가정하는 경우가 많습니다.
이 명세의 목적상, 거듭제곱 법칙으로 모델링될 수 있는 비선형 전달 함수가 발생할 수 있는 일반적인 이미지 파이프라인의 다섯 위치를 고려하는 것이 편리합니다. 각 위치와 관련된 특징적 지수에는 특정 이름이 부여됩니다.
| input_exponent | 이미지 센서의 지수입니다. |
| encoding_exponent | 데이터스트림을 쓰는 프로세스나 장치가 수행하는 어떤 전달 함수의 지수입니다. |
| decoding_exponent | image data스트림을 읽는 소프트웨어가 수행하는 어떤 전달 함수의 지수입니다. |
| LUT_exponent | frame buffer와 디스플레이 장치 사이에 적용되는 전달 함수의 지수입니다(일반적으로 룩업 테이블에 의해 적용됨). |
| output_exponent | 디스플레이 장치의 지수입니다. CRT의 경우 일반적으로 약 2.2에 근접한 값입니다. |
몇몇 복합적 전달 함수 또는 단계들의 조합을 설명하기 위해 몇 가지 추가 엔티티를 정의하는 것이 편리합니다.
| display_exponent |
frame buffer와 디스플레이 장치의 표시 표면 사이에 적용되는 전달 함수의 지수입니다.display_exponent = LUT_exponent * output_exponent
|
| gamma | 디스플레이 출력 강도를 PNG 데이터스트림의 샘플로 매핑하는 함수의 지수입니다.gamma = 1.0 / (decoding_exponent * display_exponent)
|
| end_to_end_exponent | 이미지 센서 입력 강도에서 디스플레이 출력 강도로 매핑하는 함수의 지수입니다. 일반적으로 1.0에서 1.5 범위의 값입니다. |
PNG의 gAMA 청크는 gamma value를 기록하는 데 사용됩니다. 이 정보는 디코더가 표시 환경에 관한 추가 정보와 함께 사용하여 원하는 표시 출력을 달성하거나 근사하는 데 사용될 수 있습니다.
이 주제에 대한 추가 정보는 [GAMMA-FAQ]에서 찾을 수 있습니다.
색 공간이 이미지 인코딩에 미치는 영향에 대한 추가 정보는 [Kasson] 및 [Hill]에서 찾을 수 있습니다.
chromaticity 및 색 공간에 대한 배경 정보는 [COLOR-FAQ]에서 찾을 수 있습니다.
다음의 샘플 코드는 정보적이며 PNG 청크에서 사용되는 CRC (순환 중복 검사)의 실용적 구현을 나타냅니다. (정식 명세는 ISO 3309 [ISO-3309] 또는 ITU-T V.42 [ITU-T-V.42] 를 참조하십시오.)
샘플 코드는 ISO C [ISO_9899] 언어로 작성되었습니다. 표 31의 힌트는 C를 모르는 사용자에게 코드 읽기를 쉽게 도와줄 수 있습니다.
| 연산자 | 설명 |
|---|---|
&
|
비트 단위 AND 연산자. |
^
|
비트 단위 배타적 OR 연산자. |
>>
|
비트 단위 오른쪽 시프트 연산자. 여기서와 같이 부호 없는 수에 적용될 때, 왼쪽에 0이 삽입됩니다. |
!
|
논리 NOT 연산자. |
++
|
"n++"는 변수 n을 1 증가시킵니다. "for" 루프에서는 변수 검사 후에 적용됩니다. |
0xNNN
|
0x는 16진수 상수를 도입합니다. 접미사 L는 long 값(적어도 32비트)을 나타냅니다. |
/* Table of CRCs of all 8-bit messages. */
unsigned long crc_table[256];
/* Flag: has the table been computed? Initially false. */
int crc_table_computed = 0;
/* Make the table for a fast CRC. */
void make_crc_table(void)
{
unsigned long c;
int n, k;
for (n = 0; n < 256; n++) {
c = (unsigned long) n;
for (k = 0; k < 8; k++) {
if (c & 1)
c = 0xedb88320L ^ (c >> 1);
else
c = c >> 1;
}
crc_table[n] = c;
}
crc_table_computed = 1;
}
/* Update a running CRC with the bytes buf[0..len-1]--the CRC
should be initialized to all 1's, and the transmitted value
is the 1's complement of the final running CRC (see the
crc() routine below). */
unsigned long update_crc(unsigned long crc, unsigned char *buf,
int len)
{
unsigned long c = crc;
int n;
if (!crc_table_computed)
make_crc_table();
for (n = 0; n < len; n++) {
c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
}
return c;
}
/* Return the CRC of the bytes buf[0..len-1]. */
unsigned long crc(unsigned char *buf, int len)
{
return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL;
}
이 절은 비규범적입니다.
이 부록은 PNG 소프트웨어 개발자를 위한 일부 인터넷 자원의 위치를 제공합니다. 인터넷의 특성상 목록은 완전하지 않으며 변경될 수 있습니다.
ICC 프로파일 명세는 다음에서 확인할 수 있습니다: https://www.color.org/
PNG에 관한 World Wide Web 사이트가 있습니다: http://www.libpng.org/pub/png/. 이 페이지는 PNG 및
PNG 관련 도구에 대한 최신 정보를 얻을 수 있는 중심 위치입니다.
또한 deflate에 대한 추가 문서 및 이식 가능한 C 코드와 CRC 알고리즘의 최적화된 구현은 zlib 웹사이트에서 제공됩니다: https://www.zlib.net/.
이식 가능한 C로 된 샘플 구현인 libpng는 다음에서 제공됩니다: http://www.libpng.org/pub/png/libpng.html.
libpng의 샘플 뷰어 및 인코더 응용 프로그램은 http://www.libpng.org/pub/png/book/sources.html
에 있으며, PNG: The Definitive Guide [ROELOFS]에 자세히 설명되어 있습니다. 테스트
이미지는 PNG 웹 사이트에서도 접근할 수 있습니다.
이 절은 비규범적입니다.
Video Full Range Flag에 대한 더 나은 설명 추가비공식적으로 정의되어 있던 세 개의 Animated PNG(APNG) 청크가 추가되었습니다:
이는 PNG 명세를 널리 배포된 산업 관행과 일치시키는 변경입니다.
cICP 청크(비코딩 종속 코드 포인트, 비디오 신호 유형 식별용)를 추가하여, [ITU-T-H.273]에 정의된 이미지 포맷 메타데이터를 포함할 수 있게 했습니다. 이를 통해 PNG는 [ITU-R-BT.2100]의 고동적 범위(HDR) 및 광범위 색 영역(WCG) 이미지를 포함할 수 있습니다.
이미지 색 공간을 정의하는 청크들에 대해, 둘 이상이 존재할 경우 우선순위가 명확히 정의되었습니다.
기존에 정의된 eXIf 청크를 확장 문서(PNG-EXTENSIONS)에서 본 명세서 본문으로 이동시켜 사용 증가를 반영했습니다.
HDR 콘텐츠의 톤 매핑을 돕기 위해, 마스터링에 사용된 디스플레이에 대한 메타데이터를 포함하는 mDCV 청크와 최고 및 평균 광도 수준에 대한 메타데이터를 포함하는 cLLI 청크를 추가했습니다. 이는 이기종 플랫폼에서 더 정확한 색상 매칭을 가능하게 합니다.
ICC 프로파일을 포함하는 iCCP 청크가 ICC.1 규격의 어떤 버전과도 일치하는 프로파일을 포함할 수 있음을 명확히 했습니다. PNG 제2판은 당시의 v2만 참조했으나, 이후 업계 관행은 더 높은 버전도 사용하는 것입니다.
인덱스-컬러 PNG의 범위를 벗어난 인덱스 처리에 대한 명확화
알려지지 않은 보조 청크 및 잘못된 보조 청크에 대한 오류 복구 절차 명확화
PNG 제2판 정정표의 통합. 특히, HTML이나 SVG 등에 임베드된 gamma 값이 알려지지 않은 PNG 이미지는 untagged images로 처리되어야 함을 명확히 함.
커뮤니티 피드백에 따른 다양한 편집상 명확화
참조를 최신 버전으로 업데이트
마크업 수정 및 링크 수리
문서 소스 포맷을 ReSpec로 재포맷
W3C 권고안 PNG Specification Version 1.0과 PNG Second Edition 사이의 변경사항 목록은 PNG Second Edition changelist를 참조하십시오.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: