본문 바로가기
Frontend

JPEG 손실 압축

by 그냥하는거지뭐~ 2025. 1. 27.

JPEG은 손실 압축 방식으로 압축을 수행한다. 어떤 원리로 압축이 수행되는지 알아보자. 

1. Color Space Conversion
2. Chrominance Downsampling
3. Discrete Cosine Transform
4. Quantization
5. Run Length and Huffman Encoding

 

인간의 눈은 완벽하지 않다. JPEG은 인간이 알아차리지 못하는 정보를 지움으로써 압축을 한다. 

출처: https://www.color-meanings.com/evolution-color-vision-humans-animals/

 

Rods Cones
Brightness & Low light sensitive Color sensitive
100 million 6 million

 

밝기를 감지하는 Rods가 색깔을 감지하는 Cones보다 훨씬 많다. 그래서 우리 눈은 밝기에 더 민감하다.


STEP 1: Color Space Conversion

JPEG 압축에서는 RGB를 그대로 사용하지 않고, YCbCr으로 변환한다. 인간의 눈이 밝기(Luminance, Y)에 민감하지만 색 차이(Chrominance, Cb, Cr)에는 둔감하다는 특성을 이용한 것이다. 

 

  • RGB → YCbCr 변환
    • Y (Luminance, 휘도): 밝기 정보, 흑백 TV에서 사용되던 성분.
    • Cb (Chrominance-Blue, 색차-블루): Blue 채널과 밝기 Y의 차이.
    • Cr (Chrominance-Red, 색차-레드): Red 채널과 밝기 Y의 차이.
🤔 Green 성분은 어디로 갔을까?
Green 성분(G)은 직접 저장되지 않는다. 대신, Y 성분을 통해 간접적으로 포함된다. Y는 RGB의 가중합으로 계산되므로, Green 성분은 Y에서 Red와 Blue를 빼면 자동으로 얻어진다.

 

출처: https://dprime.kr/g2/bbs/board.php?bo_table=dpinfo&wr_id=47998

RGB-YCbCr 변환 공식

여기서 주목할 점은:

  • Y 성분은 Green(G)의 가중치가 가장 크다. 이는 인간의 눈이 초록색에 가장 민감하기 때문이다.
  • Cb, Cr은 색차(Chrominance) 정보로, Y와의 차이를 계산하는 방식이다. 
    • Cb는 Blue 채널과 Y의 차이 (Blue-Yellow 축)
    • Cr는 Red 채널과 Y의 차이 (Red-Cyan 축)

이제 YCbCr을 다시 RGB로 변환할 수도 있다.

여기서도 마찬가지로:

  • Green(G)은 Cb, Cr의 영향을 동시에 받는다.
  • 인간의 시각적 특성 덕분에 Cb와 Cr을 줄여도 큰 화질 저하가 발생하지 않는다.

YCbCr 방식이 압축에 뭐가 좋을까?

YCbCr로 변환함으로써 우리는 밝기와 색 정보를 분리했다. 색 정보의 해상도를 낮춰도 자연스러운 이미지를 유지할 수 있는 구조가 되었다. 또, Y 성분만 남기면 흑백 영상으로 변환도 가능하다. 


STEP 2: Chrominance Downsampling

YCbCr 변환 후, 밝기(Y)는 원본 해상도를 유지하지만, 색차(Cb, Cr)의 해상도를 낮춘다. 색차 정보를 줄이는 방식은 4:x:y 형식으로 표현된다.

  • 4 → 고정값. 한 번에 처리하는 픽셀 블록(4픽셀 기준).
  • x → 첫 번째 행의 숫자.
  • y → 두 번째 행의 숫자.

4:2:2이면 1행에서 두 개의 픽셀을 사용하고, 2행에서도 두 개의 픽셀을 사용해서 다음과 같이 표현된다. 

4:2:2

4:2:0이면 1행에서 두 개, 2행에서는 픽셀을 사용하지 않는다.

4:2:0

여기에 밝기 정보를 추가하면,

 

JPEG은 대부분 4:2:0 방식을 이용한다. 


STEP 3: Discrete Cosine Transform (DCT)

이미지를 주파수 영역으로 변환하면 불필요한 정보를 쉽게 제거할 수 있어 압축이 용이한 형태가 된다.

 

우리가 그림을 색칠할 때 배경색을 먼저 채운 뒤 점점 디테일한 부분을 채워 나가듯이, 이미지에서도 저주파 성분은 배경이나 하늘과 같은 큰 구조를 표현하고, 고주파 성분은 경계선이나 작은 디테일을 표현한다.

 

원래의 복잡한 이미지 신호는 여러 개의 다른 주파수를 가진 코사인 파형들의 합으로 표현될 수 있다. 즉, 이미지는 다양한 주파수 성분이 혼합된 결과물이며, DCT는 이를 개별적인 주파수 성분으로 분해하는 과정이다.

 

원리

 

원본 이미지를 8×8 블록으로 분할한 후 DCT 변환을 수행한다. 각 블록을 DCT 변환을 해서 frequency domain으로 변환하면, 저주파 성분은 좌측 상단에, 고주파 성분은 우측 하단에 배치된다.
이를 통해 이미지의 주요 정보(배경, 부드러운 색 변화)는 좌측 상단에 집중되고, 세부적인 디테일(경계선, 노이즈 등)은 우측 하단에 위치하게 된다.

원본 8×8 블록 (밝기 Y 값) DCT 변환 결과

 

DCT 변환 결과를 보면,
좌측 상단(저주파 성분)은 큰 값들이 배치되어 있고,
우측 하단(고주파 성분)은 작은 값들이 많거나 거의 0에 가까움.

 

고주파 성분은 제거해도 인간의 눈으로는 차이를 거의 느끼지 못하기 때문에, 이 부분을 제거하면 파일 크기를 줄이면서도 화질을 유지할 수 있다.

https://www.youtube.com/watch?v=Q2aEzeMDHMA

STEP 4: Quantization

JPEG 표준에서 사용하는 양자화 행렬(Quantization Table)은 아래와 같다.

JPEG 표준 quantization table


이 행렬에서 숫자가 클수록 손실이 더 크게 발생하는데, 저주파 성분(좌측 상단)은 작은 값을 할당하여 정밀도를 유지하고, 고주파 성분(우측 하단)은 큰 값을 할당하여 손실을 유도한다. 

 

각 주파수 성분을 양자화 행렬의 값으로 나눈 후 반올림한다.

quantization formula

그럼 다음과 같은 형태가 된다.

after quantization

고주파 성분은 대부분 0이 됨 → 압축률 증가
파일 크기가 줄어들면서도 화질 저하는 크지 않음

 

 

복원 과정: Dequantization

복원할 때는 다음 공식을 사용한다. 

Dequantization formula

하지만, 양자화 과정에서 DCT 계수를 양자화 행렬로 나누고 반올림하여 정수로 변환했기 때문에, 나중에 다시 곱해서 복원하더라도 소수점 이하의 정보는 복구할 수 없다. (손실 압축)

ex)
1. 원래 값: 19.7
2. 양자화 적용: round(18.7 / 10) = round(1.87) = 2
3. 역양자화: 2 × 10 = 20
4. 복구된 값: 20 (원래 값 18.7과 다름!)

 

즉, 원래 값을 정확히 복원할 수 없음.
이 차이가 바로 JPEG의 손실 압축(lossy compression) 효과이다.
하지만 인간의 눈에는 차이가 거의 느껴지지 않기 때문에 문제없음!


STEP 5: Run-Length Encoding & Huffman Encoding

JPEG 압축 과정에서 DCT 변환과 양자화를 통해 불필요한 정보(고주파 성분)를 제거하고, 정수 값으로 변환했다.
그러나 이렇게 변환된 데이터도 그대로 저장하면 압축 효율이 낮기 때문에, 무손실 압축 알고리즘인 Run-Length Encoding(RLE)과 Huffman Encoding을 적용하여 더욱 효율적으로 저장한다.

이 두 가지 방법을 순차적으로 적용하여 JPEG 이미지 데이터를 효과적으로 압축한다.

 

① Run-Length Encoding (RLE)

RLE는 같은 값이 연속해서 반복될 때, 이를 압축하여 저장하는 방법이다.

데이터: AAAAAABBBBCCCCCCDD
RLE 적용: (A,6) (B,4) (C,6) (D,2)

 

즉, 반복되는 데이터의 개수를 기록하여 저장 공간을 절약한다.

 

DCT 변환 후 양자화를 거친 8×8 블록에서는, 8×8 블록을 순차적으로 저장하기 위해 "Zigzag 스캔"을 사용한다.

📌 Zigzag 스캔이란?
- 8×8 블록을 좌측 상단(저주파)에서 우측 하단(고주파)으로 지그재그 방식으로 읽는 방법이다.
- 이렇게 하면 대부분의 0이 마지막 부분에 모이므로 RLE 압축 효율이 높아짐.
양자화까지 거친 8×8 블록
Zigzag 스캔 적용 42, -5, -5, -2, -4, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, ...
RLE 적용

 

이렇게 하면 데이터 크기가 대폭 줄어듦.
대부분의 고주파 성분(우측 하단)이 0이므로 압축 효과가 큼.

 

② Huffman Encoding

Huffman Encoding은 자주 나타나는 데이터에는 짧은 코드, 덜 나타나는 데이터에는 긴 코드를 할당하여 압축하는 기법이다.

 

다음과 같은 데이터가 있을 때,

A A A A B B B C C D 

 

각 문자의 빈도수를 세면:

A: 4회, B: 3회, C: 2회, D: 1회

 

허프만 트리(Huffman Tree)를 만들어 압축하면:

A → 0
B → 10
C → 110
D → 111

기존 40비트 → 19비트로 줄어듦.

 

 

 

 

 

'Frontend' 카테고리의 다른 글

WebView: 나빼고 다 쓰고있었잖아?  (1) 2025.01.15