JPEG / JPG
JPEG (Joint Photographic Experts Group) — растровый формат изображений со сжатием с потерями, стандарт ISO/IEC 10918 (1992). Алгоритм DCT разбивает изображение на блоки 8×8 пикселей и отбрасывает высокочастотные детали. Идеален для фотографий; разрушителен для QR-кодов: артефакты сжатия повреждают finder pattern и делают код нечитаемым.
Что такое JPEG
JPEG (Joint Photographic Experts Group) — растровый формат изображений, принятый как международный стандарт ISO/IEC 10918 в 1992 году. Расширение файла — .jpg или .jpeg — один и тот же формат (DOS ограничивал расширения тремя буквами). JPEG создавался для фотографий: пейзажи, портреты, плавные цветовые переходы. Сжимает фото 5 МП с 15 МБ (PNG) до 1,5–3 МБ — в 5–10 раз, — и глаз почти не замечает потерь.
Но за компактность платят качеством. JPEG — формат lossy compression (сжатия с потерями): часть данных уничтожается безвозвратно. В отличие от PNG, где deflate хранит каждый пиксель точно, JPEG выбрасывает то, что глаз «не заметит». Для фото работает. Для QR-кода — нет.
Существуют наследники: JPEG 2000 (вейвлеты вместо DCT, плохо поддерживается браузерами), MozJPEG (улучшенный энкодер Mozilla, те же артефакты, но меньший вес), WebP (25–35% компактнее JPEG, поддерживает прозрачность). Ни один не подходит для QR: проблема не в реализации, а в самом принципе lossy-сжатия.
Сжатие с потерями: DCT и артефакты
JPEG сжимает через DCT (Discrete Cosine Transform). Три шага: (1) изображение делится на блоки 8×8 пикселей; (2) каждый блок переводится в пространство частот — выделяются плавные переходы (низкие частоты) и резкие края (высокие); (3) высокочастотные компоненты квантуются — округляются или обнуляются. Чем ниже quality, тем грубее обрезка. Это и есть потеря: выброшенное не восстановить.
На фото результат незаметен — плавные переходы не требуют высоких частот. Но на резких границах появляются блочные артефакты: размытые ореолы 8×8 пикселей вокруг контрастных краёв. Фотография 5 МП в JPEG quality=85 весит ~2 МБ, в PNG — 12–15 МБ. QR 400×400 px в PNG весит 3–6 КБ; в JPEG — тоже ~5 КБ, но с артефактами на границах каждого модуля. Высокое разрешение не спасает: артефакты появляются при любом DPI, если кодирование lossy.
JPEG для QR — почему нет
QR-код читается сканером по контрасту: тёмный модуль против светлого фона. Алгоритм декодирования ищет finder pattern (три угловых квадрата), timing pattern (чередующиеся линии) и отдельные модули данных. Для успешного распознавания граница между тёмным и светлым должна быть чёткой — несколько пикселей погрешности допустимы, но не размытый ореол шириной 8 пикселей.
JPEG разбивает QR на блоки 8×8 пикселей. Finder pattern попадает сразу в несколько блоков, и в каждом DCT создаёт артефакты вокруг тёмных краёв. Граница модуля превращается из резкой линии в градиент из нескольких оттенков серого. Сканер видит не «1» (тёмный) или «0» (светлый), а зашумлённую полутоновую картину и начинает ошибаться.
Даже при quality=95 (почти незаметные потери для глаза) артефакты на QR-коде приводят к сбоям. При quality=85 (стандарт для веб-фото) код с высокой вероятностью не читается вообще. Правило одно: JPEG для QR-кодов не используется. Никогда. Если QR пришёл клиенту или контрагенту в JPG-файле — его нужно перегенерировать. Альтернативы: PNG (lossless, идеален для цифрового использования) или SVG (вектор, идеален для печати). Оба форматов сохраняют каждый пиксель точно.
Частые вопросы
Почему JPEG портит QR, если quality стоит 95%?
Параметр quality=95 — это человеческое восприятие, а не техническая точность. Глаз плохо замечает артефакты на фотографии с плавными переходами. Но сканер QR работает иначе: он ищет резкие границы модулей с точностью до пикселя. DCT при любом quality создаёт блочные артефакты вокруг контрастных краёв — пусть и небольшие при 95%. Этого достаточно, чтобы смазать finder pattern и сорвать декодирование. Проверить легко: сохраните QR в JPEG quality=95, откройте и увеличьте до 400% — вокруг каждого чёрного квадрата увидите ореол серых пикселей. Вот почему сканер ошибается даже при «почти без потерь».
Чем JPEG отличается от PNG применительно к QR?
PNG использует алгоритм deflate — сжатие без потерь. Каждый пиксель хранится точно так, как был записан: если модуль QR чёрный (0, 0, 0), при сохранении и открытии он останется (0, 0, 0). JPEG перекодирует изображение через DCT и квантование: тот же чёрный пиксель может стать (12, 8, 5) или (0, 0, 4) — незаметно глазу, но критично для сканера. Размер файла у обоих форматов для QR 400×400 px примерно одинаков (3–6 КБ). Но PNG даёт чистый чёрно-белый код, JPEG — зашумлённый. Вывод: для QR выбирайте PNG всегда, JPEG — только для фотографий.
Можно ли исправить QR, который уже сохранён в JPEG?
Нет. Потери при JPEG-сжатии необратимы: выброшенные при DCT данные не восстанавливаются из файла. Если у вас есть только JPG-версия QR — перегенерируйте код заново на исходном сервисе и экспортируйте в PNG или SVG. Если исходный сервис недоступен — перегенерируйте QR с тем же URL или данными на QRkoder и скачайте в правильном формате. Конвертация JPG→PNG даст PNG с теми же артефактами — формат изменится, но артефакты останутся.
Что лучше для QR: PNG или SVG?
Зависит от задачи. PNG — для цифрового использования: сайт, мессенджеры, email, WhatsApp. Открывается везде без конвертации, весит 3–6 КБ при 400×400 px. SVG — для передачи в типографию и печати крупных форматов: масштабируется без потерь до любого размера, весит 3–6 КБ независимо от разрешения. Для плаката А1 SVG останется 4 КБ, а PNG потребует 5–25 МБ. Оба формата хранят пиксели (или точки) без потерь — никаких DCT-артефактов. JPEG не является конкурентом ни одному из них для QR.
Где JPEG всё-таки уместен в контексте QR-проектов?
JPEG уместен только для фоновых изображений, на которых QR накладывается поверх — например, фотобаннер с QR-кодом в углу. Сам фон-фото можно хранить в JPEG для экономии места. QR при этом должен быть отдельным слоем в PNG или SVG — с чёткими границами модулей. Смешивать QR и JPEG-фон можно только на финальном рендере в дизайн-программе; финальный экспорт QR как отдельного файла — всегда PNG или SVG.