SWAPQR← Руководство

QR-код из фотографии: как дизеринг превращает снимок в сканируемый код

Большинство «художественных» QR-кодов устроены просто: берут картинку и ставят поверх неё код. QR-код с дизерингом — другое дело: изображение здесь одно, и код является частью его зерна. Ниже разобрано, что коду на самом деле необходимо, как работает рассеивание ошибки, какая единственная поправка позволяет коду и снимку делить один квадрат, какие две настройки решают всё и какими тремя способами эта техника ломается.

Создать QR-код в браузере →Напечатайте квадрат один раз. Куда он ведёт — решите потом.

Начните с того, что коду действительно нужно

QR-код — это сетка модулей, маленьких квадратов, каждый из которых либо тёмный, либо светлый. Часть из них структурная и не может сдвинуться: три больших квадрата по углам, по которым сканер находит код и понимает его ориентацию, тонкая чередующаяся линия между ними, маленькие выравнивающие квадраты и полосы, кодирующие формат и версию. Всё остальное — данные плюс байты коррекции ошибок. Именно коррекция ошибок и есть та щель, в которую пролезает картинка. На высшем уровне можно разрушить примерно 30% кода, и читатель всё равно восстановит содержимое. То есть код не обязан быть безупречным. Он обязан быть безупречным там, где это важно, и достаточно близким к правильному во всём остальном. Держите это различие в голове, потому что на нём стоит вся техника: структурные модули считаются неприкосновенными, а область данных — тем, что должно быть верным лишь в среднем, на том масштабе, каким её видит камера. Любой генератор, помещающий картинку в код, тратит часть этих 30%; вопрос только в том, насколько аккуратно он их тратит и заметен ли глазу этот расход.

Дизеринг в одном абзаце

Дизеринг Флойда—Стейнберга превращает полутоновую фотографию в чистые чёрное и белое. Пиксели обходятся по порядку. Для каждого выбирается то из двух значений, которое ближе, а затем сделанная ошибка — разница между нужным серым и напечатанным значением — распределяется по ещё не посещённым соседям с весами 7/16 для пикселя справа и 3/16, 5/16 и 1/16 для трёх пикселей снизу. Каждый из этих соседей, когда доходит его очередь, стартует уже со слегка поправленного значения, поэтому ошибка никогда не теряется — она только перемещается. Картинка выходит полем крапа, локальная плотность которого повторяет исходную яркость: средне-серая область становится примерно наполовину чёрными точками, светлое место — редкими точками по белому, тень — редкими белыми точками по чёрному. С расстояния глаз усредняет крап обратно в тон, поэтому изображение с дизерингом читается как фотография, хотя каждый его пиксель имеет один из двух цветов. Ровно то же усреднение делает камера, когда смотрит на небольшой отпечаток, — и именно на нём техника и играет.

Сам приём

Код рисуется с фиксированным числом пикселей на модуль — SWAPQR использует девять, то есть каждый модуль это блок 9×9. Затем фотография подвергается дизерингу по всему квадрату, с одной поправкой: там, где код требует конкретного значения, порог не применяется. Пиксель принудительно ставится в то, что нужно коду, измеряется вызванная этим ошибка и рассеивается точно так же, как любая другая. Последнее предложение и есть вся идея. Принудительные точки не нарисованы поверх картинки — за них платят окружающие пиксели, которые сдвигаются, компенсируя. Они попадают внутрь той же зернистой текстуры, что и всё прочее, и глазу нечем отделить их от неё. Структурные модули — поисковые узоры, синхрополоса, выравнивание, формат — рисуются сплошными и не трогаются вовсе, потому что сканер обязан сначала найти код, и только потом коррекция ошибок сможет ему помочь. Описанный подход следует работе Эндрю Т., опубликовавшего разбор генерации QR-кодов с дизерингом в 2026 году; реализация SWAPQR написана по описанию, а не портирована из его исходников.

Две ручки, которые решают всё

Первая — какая доля каждого модуля ставится принудительно. Заставьте только центральный пиксель, и картинка почти не пострадает, но код станет хрупким: один пиксель на модуль должен пережить каждое пересэмплирование между принтером и матрицей камеры. Заставьте блок 7×7 из девяти на девять — код станет устойчивым, а картинка бледной, потому что большая часть каждого модуля теперь сплошная. SWAPQR выносит это прямо в интерфейс как баланс «Фото ↔ Код» с положениями «Фото», «Середина» и «Код», так что компромисс становится вашим выбором, а не константой, спрятанной в генераторе. Вторая ручка — насколько сильно подталкивается каждый модуль. Перед дизерингом все пиксели тёмного модуля чуть затемняются, а светлого — чуть осветляются. Картинка сохраняет детали, но средний тон модуля кренится в нужную сторону, а это ровно то, что видит камера, глядя на небольшой отпечаток с другого конца комнаты. Вдвоём эти настройки решают, получится ли фотография со слабым кодом внутри или код со слабой фотографией, и где именно на этой прямой должен стоять конкретный отпечаток, зависит от того, как его будут сканировать.

Где ломается и стоит ли оно того

Три режима отказа, все настоящие и ни один не загадочный. Плоская фотография: равномерно освещённое однотонное изображение превращается дизерингом в правильную шахматку — ровно ту текстуру, что конкурирует с кодом, поэтому снимку нужен подлинный диапазон от света к тени, и студия предупреждает, когда его нет. Длинная ссылка: больше символов означает больше модулей в том же квадрате, значит каждому модулю достаётся меньше картинки; после примерно восьмой версии — 49×49 модулей — фотографии становится негде жить, и лечится это коротким адресом перенаправления. И крайне близкое сканирование на части читателей — настолько неочевидный случай, что в этом руководстве ему отведена отдельная статья. Художественный код всегда обменивает надёжность на вид. Он оправдан там, где код является частью оформления и его собираются сканировать намеренно: афиша, конверт пластинки, упаковка, визитка. Ему не место на табличке аварийного выхода. В любом случае проверьте напечатанный образец настоящим телефоном, прежде чем заказывать тысячу штук; студия говорит то же самое рядом с кнопкой экспорта и говорит это всерьёз.

Часть кодаКак обрабатывается в коде с дизерингомПочему
Поисковые узоры (три угловых квадрата)Рисуются сплошными, дизеринг не применяетсяСканер обязан сначала найти код и определить его ориентацию
Синхрополоса, выравнивающие квадраты, полосы формата и версииРисуются сплошными, дизеринг не применяетсяСтруктура; коррекция ошибок не спасёт код, который не найден
Модули данных и коррекции ошибокЦентральный блок модуля ставится принудительно, остальное несёт фотографиюКамера на дистанции сканирования видит средний тон модуля
Пиксели вокруг принудительного блокаСдвигаются рассеиванием ошибки в качестве компенсацииДержат правильным локальное среднее, и принудительные точки прячутся в крапе
Зона тишиныСветлая, не трогаетсяПо пустому полю сканер находит границу кода

Часто задаваемые вопросы

Фотография просто подложена под код?

Нет. Код и снимок получаются за один проход: картинка проходит дизеринг, и там, где коду нужно значение, пиксель ставится принудительно, а его ошибка рассеивается по соседям. Изображение одно, а не слой поверх слоя.

Почему девять пикселей на модуль?

Так каждому модулю достаётся блок 9×9 — достаточно большой, чтобы вместить принудительное ядро изменяемого размера и всё же оставить пиксели картинке. Насколько велика принудительная часть блока, решает настройка баланса.

Сканируется ли он обычными телефонами?

Да, для тех объёмов данных и изображений, на которые он рассчитан; каждая сборка проверяется двумя независимыми декодерами на семи смоделированных дистанциях. Это всё равно обмен надёжности на вид, поэтому напечатайте один образец и проверьте своим телефоном.

Почему длинная ссылка портит картинку?

Более длинный текст поднимает версию, значит модулей становится больше и они мельче в том же квадрате. Каждому модулю остаётся меньше пикселей под фотографию, а после примерно 49×49 модулей картинка исчезает. Используйте короткую ссылку перенаправления.

Напечатайте квадрат один раз. Куда он ведёт — решите потом. SWAPQR создаёт статические QR-коды бесплатно, со всеми вариантами оформления, без аккаунта и без водяного знака. Платный план делает код динамическим: напечатанный квадрат остаётся прежним, а вы меняете его адрес назначения и видите, как часто его сканировали, по дням и по устройствам.

Создать QR-код в браузере
Язык: TR EN DE ES FR IT PT AR RU JA KO