Маскирование QR (QR Masking)
Маскирование QR — обязательный этап кодирования: после добавления коррекции ошибок генератор применяет XOR к модулям данных, перебирает все 8 масок, считает штраф по 4 правилам и выбирает маску с минимальным penalty score.
Зачем нужна маска QR
Маскирование QR (QR Masking) — обязательный этап, встроенный в стандарт ISO/IEC 18004. После того как данные закодированы и к ним добавлены байты коррекции ошибок Reed-Solomon, готовая битовая последовательность укладывается в матрицу модулей. Проблема в том, что реальные данные — URL, номер телефона, JSON — могут случайно сформировать опасные визуальные паттерны: длинные полосы одного цвета, большие однотонные прямоугольники или структуры, похожие на Finder Pattern. Такие паттерны сбивают декодер: он теряет калибровку, видит ложные метки или просто не может выравнять сетку модулей.
Маскирование решает это через XOR. Каждый модуль данных поразрядно складывается с соответствующим битом маски — это меняет цвет части модулей и «разбивает» нежелательные структуры. Служебные зоны — три Finder Pattern, Alignment Pattern, Timing Pattern, Format Information — остаются нетронутыми. Только поле данных и ECC-байты проходят через преобразование.
Без маскирования коды с однородными данными (например, строка нулей или QR только с цифрами) были бы практически неработоспособны на части сканеров. Маскирование гарантирует, что итоговый код выглядит визуально случайным — независимо от содержимого. Попробуйте создать QR-код с разными данными: результат всегда выглядит равномерным именно благодаря этому механизму.
Penalty score и выбор маски
Стандарт не позволяет выбрать маску произвольно. Генератор обязан перебрать все 8 паттернов масок, для каждого вычислить суммарный штраф (penalty score) и выбрать маску с наименьшим значением. Штраф складывается из четырёх независимых правил:
- Правило N1 — серии одного цвета. Каждая горизонтальная или вертикальная цепочка из 5 и более модулей одного цвета добавляет штраф 3 + (длина − 5). Шесть чёрных модулей подряд — штраф 4, десять — штраф 8. Правило штрафует «полосатость» кода.
- Правило N2 — блоки 2×2. Каждый квадрат 2×2 из модулей одного цвета стоит 3 балла. Правило предотвращает большие однотонные прямоугольники — именно они чаще всего мешают сканеру откалиброваться по сетке.
- Правило N3 — ложный Finder Pattern. Паттерн 1:1:3:1:1 (чёрный-белый-3 чёрных-белый-чёрный) в любом ряду или столбце, особенно окружённый четырьмя белыми, штрафуется 40 баллами за каждое вхождение. 40 — намеренно высокий вес: ложный Finder Pattern критичнее любой полосы, потому что сбивает детектор меток.
- Правило N4 — перевес по цвету. Если доля чёрных модулей отклоняется от 50%, штраф = 10 × ⌊|доля − 50| / 5⌋. При 45% или 55% — штраф 10, при 40% или 60% — штраф 20. Правило требует примерного баланса чёрного и белого по всей матрице.
Все четыре штрафа суммируются. Маска с наименьшей суммой признаётся оптимальной. На практике генераторы выполняют весь перебор за миллисекунды: для QR версии 1 (21×21) это 8 × 441 XOR-операций и подсчёт штрафов — тривиальная задача даже для 8-битного микроконтроллера.
Связь с Finder Pattern и форматом
Маскирование неотделимо от двух других структур QR-кода. Во-первых, правило N3 напрямую ссылается на Finder Pattern: именно его характерное соотношение 1:1:3:1:1 штрафуется максимально. Без этого правила выбранная маска могла бы непреднамеренно воспроизвести структуру поисковой метки в поле данных, дезориентировав сканер.
Во-вторых, результат выбора маски записывается в область Format Information — 15-модульную служебную зону, дублированную в двух местах матрицы для надёжности. Эти 15 модулей содержат 2 бита уровня ECC и 3 бита номера маски, защищённые кодом BCH(15, 5). Сканер читает Format Information первым: узнаёт уровень коррекции и номер маски, после чего применяет обратный XOR к полю данных и запускает декодирование Reed-Solomon. Если Format Information повреждена в обеих копиях — код нечитаем, даже если все данные в порядке.
Важно понимать: маска не делает данные более надёжными в смысле коррекции — это задача ECC. Маскирование отвечает исключительно за распределение чёрных и белых модулей, чтобы сканер физически мог прочитать код с любым содержимым.
Частые вопросы
Чем маскирование отличается от маски QR?
Маскирование (QR Masking) — это весь процесс: перебор 8 паттернов, подсчёт penalty score по четырём правилам и выбор оптимальной маски. Маска QR — один из 8 конкретных паттернов, задаваемых математической формулой по координатам модуля (i, j). Аналогия: маскирование — это процедура выбора ткани для пальто, а маска — конкретный рулон ткани из восьми доступных. В технической документации термины нередко смешивают, но ISO/IEC 18004 чётко разграничивает процедуру выбора (masking procedure) и сами шаблоны (mask patterns 000–111).
Почему penalty score за ложный Finder Pattern равен 40?
Это намеренно завышенный вес — разработчики ISO/IEC 18004 выбрали 40 баллов, чтобы алгоритм при любых обстоятельствах избегал воспроизведения паттерна 1:1:3:1:1 в поле данных. Стоимость одного ложного Finder Pattern эквивалентна примерно 13 сериям из 5 одноцветных модулей или примерно 13 блокам 2×2. На практике маска, создающая хотя бы один ложный Finder Pattern, почти всегда проигрывает конкурентам по итоговому штрафу. Это гарантирует, что сканер не перепутает данные с меткой позиционирования.
Можно ли принудительно задать номер маски?
Да, некоторые профессиональные библиотеки (zxing, python-qrcode, qrcode-generator) позволяют зафиксировать номер маски вручную. Это используется в двух сценариях: отладка — когда разработчик хочет воспроизвести конкретный байтовый паттерн для тестирования; художественный QR — когда одна из масок создаёт визуально более симметричный или красивый рисунок. В обоих случаях надёжность сканирования может снизиться. Большинство генераторов, включая QRkoder, всегда используют автоматический перебор — это оптимально для продакшн-кодов.
Сколько времени занимает выбор маски при генерации?
Меньше миллисекунды на современном процессоре. Для QR версии 40 (177×177 = 31329 модулей) алгоритм выполняет 8 × 31329 XOR-операций и 8 проходов по штрафным правилам — это порядка 500 тысяч простых арифметических операций. На частоте 1 ГГц весь перебор завершится за 0,5 мс. Реальные реализации ещё быстрее: они векторизуют XOR через SIMD-инструкции. Маскирование не является узким местом генерации QR — обычно дольше выполняется кодирование данных и вычисление полиномов Reed-Solomon.
Что произойдёт, если маска не применяется совсем?
QR-код без маскирования технически не соответствует стандарту ISO/IEC 18004, и большинство валидаторов отклонят его. На практике последствия зависят от данных: «удачные» данные создадут хорошо распределённую матрицу и код будет читаться. Но «неудачные» — например, строка из одних нулей или повторяющихся байтов — создадут большие однотонные блоки или паттерны, неотличимые от Finder Pattern. Такой код не смогут прочитать многие сканеры. Именно поэтому маскирование сделано обязательным, а не рекомендованным.
Как маскирование влияет на внешний вид дизайнерского QR?
Прямо: разные маски дают разный визуальный рисунок модулей при одинаковых данных. Два QR-кода с одним URL, но разными масками выглядят непохоже, хотя оба корректно сканируются. Дизайнеры иногда выбирают маску вручную, подбирая ту, которая создаёт наиболее симметричный или «чистый» паттерн вокруг встроенного логотипа. Это допустимо, но требует проверки на нескольких сканерах: ручная маска не гарантирует оптимального penalty score и может ухудшить читаемость на дешёвых устройствах.