JPEG Explorer

Как JPEG сжимает картинку

JPEG — lossy-сжатие: часть информации намеренно выбрасывается. Алгоритм рассчитан на то, как устроен глаз: хорошо видим яркость, плохо — мелкий цвет. Ниже весь путь данных, этап за этапом.

Загрузите картинку → кликните по блоку 8×8 → листайте вниз.

0 Исходное и восстановленное изображение

Слева — оригинал (RGB, без сжатия: ширина × высота × 3 байта). Справа — тот же кадр после полного цикла JPEG (YCbCr → блоки → DCT → квантование → обратно). Кликните по блоку 8×8 слева.

Загрузите изображение через кнопку «Картинка» вверху.

1 RGB → YCbCr

JPEG переводит цвет из RGB в YCbCr — не сжатие, а подготовка: отделить яркость (глаз видит хорошо) от цвета (видит плохо).

Три канала

Y = 0.299·R + 0.587·G + 0.114·B
Cb = −0.169·R − 0.331·G + 0.500·B + 128
Cr = 0.500·R − 0.419·G − 0.081·B + 128

Зелёный «спрятан» в Y (вес 0.587). Отдельного зелёного канала нет — из Y+Cb+Cr RGB восстанавливается точно. Шаг обратимый, потерь нет.

2 Chroma subsampling (4:2:0)

Цвет хранят реже: в 4:2:0 на 4 пикселя яркости — 1 сэмпл Cb и 1 сэмпл Cr. Объём цвета падает в 4 раза, для глаза почти незаметно.

Галочка «4:2:0» вверху включает/выключает этот шаг.

3 Блок 8×8 — исходный и после JPEG

Каждый канал режется на квадраты 8×8. Ниже выбранный блок увеличен в 40 раз (каждый пиксель = 40×40 экранных пикселей): слева исходный, справа после DCT → квантования → IDCT.

Выберите блок на оригинале выше.

Перед DCT из каждого значения вычитается 128 (диапазон ≈ −128…+127). Разница между левым и правым блоком — это как раз потери JPEG на этом куске.

4 DCT — переход в частоты

Дискретное косинусное преобразование переводит блок пикселей в блок частот. Шаг lossless: через IDCT можно вернуть данные обратно без потерь.

Идея

Любой 8×8 — сумма 64 фиксированных базисных картинок (от гладкого среднего до мелкой сетки). DCT находит вес каждой.

F(u,v) = ¼ · C(u)·C(v) · Σx Σy f(x,y) · cos[(2x+1)uπ/16] · cos[(2y+1)vπ/16]
C(u) = 1/√2 при u=0, иначе 1

Коэффициенты DCT

Базисные паттерны

Выберите блок.

DCT ничего не сжимает и не теряет — только переупорядочивает данные так, чтобы квантование могло легко выкинуть высокие частоты.

5 Квантование — здесь теряются данные

Единственный необратимый шаг. Каждый коэффициент делится на число из таблицы квантования и округляется. Мелкие (высокие частоты) → ноль.

Fq(u,v) = round( F(u,v) / Q(u,v) )

Q(u,v) маленькие слева сверху (низкие частоты берегут), большие справа снизу. При декодировании: F' = Fq · Q — но нули обратно не вернуть.

Таблица квантования (Y, Q=50)

Слайдер «Качество» масштабирует таблицу. Для Cb/Cr она жёстче, чем для Y.

После квантования

Выберите блок.

Отсюда артефакты: мыло, потеря текстур, цветные ореолы, квадратная сетка.

6 Зигзаг и Хаффман

После квантования много нулей. Их упаковывают: зигзаг-сканирование (DC → низкие → высокие частоты) + run-length + код Хаффмана.

Частые маленькие числа получают короткие битовые коды. Оценка «≈ байт» выше приблизительная — настоящий Хаффман зависит от всей картинки.

7 Как восстанавливается блок

Декодер: Хаффман → обратный зигзаг → умножение на Q → IDCT → +128 → YCbCr → RGB.

Сравните крупный исходный и восстановленный блок в этапе 3 — разница между ними и есть потери JPEG на этом куске картинки.