파일포맷 톺아보기: JPEG
JPEG, JPG는 PNG와 더불어서 가장 널리 사용되는 이미지 파일 포맷이다. Joint Photographic Experts Group의 축약이고, 손실 압축 알고리즘을 사용한다. 1992년에 탄생했다.
JPG는 DCT(Discrete Cosine Transform)라고 불리는 알고리즘을 통해 손실 압축을 수행한다.
손실 압축을 하는 탓에 이미지 크기를 획기적으로 줄일 수 있지만, 필연적으로 화질의 손실도 발생한다.
그래서 JPG 변환을 여러번 거치다보면 화질이 급격하게 파괴될 수 있다.
흔히 말하는 디지털 풍화라는게 보통 이걸로 인해 발생한다...
무손실 모드로 변환하는 것도 가능하긴 하지만, 잘 지원되지 않을 때가 많다고 한다.
한번 받아서 까보면서 개략적인 구조를 파악해보자.
첨부파일bonobono.jpg파일 다운로드
다운받아서 적당히 이미지를 읽어다가 바이트열을 확인해보자.
나는 Rust로 했지만 그냥 아무 언어로나 해도 된다.
fn main() {
if let Ok(bytes) = std::fs::read("bonobono.jpg") {
println!("{:?}", bytes)
}
}
그럼 이렇게 쫙 출력이 될 것이다.
맨 앞에 있는 0xFF, 0xD8(255, 216)이 이미지의 시작을 알리는 메타데이터다.
JPG에서는 저런걸 다 마커라고 부르는데, 항상 저걸로 시작한다.
마지막은 항상 이미지의 끝을 알리는 0xFF, 0xD9(255, 217)로 종료된다.
그리고 두번째의 0xFF, 0xE0(255, 224)은 JPG의 압축 표준인 JFIF 섹션이 시작됨을 알리는 마커다.
그 다음은 JFIF 데이터의 크기를 뜻하고
그다음은 JFIF를 뜻하는 아스키 코드 시퀀스다. 왜 있는지는 모르겠다.
나머지도 쭉쭉 고유의 의미를 가지는 태그값들이다.

참조
https://www.adobe.com/kr/creativecloud/file-types/image/raster/jpeg-file.html
https://en.wikipedia.org/wiki/Discrete_cosine_transform