Почему китайские QR-коды занимают больше места, чем английские?

Одни и те же несколько десятков символов: китайский QR-код выглядит плотным, а английский — заметно просторнее. Это не иллюзия — так работают правила кодирования.

Каждый, кто генерировал QR-коды, сталкивался с этой загадкой: содержимое не длинное, а код выходит настолько плотным, что его трудно разобрать, — тогда как чужой код, ведущий на довольно длинный URL, выглядит куда реже.

Причина в том, что внутри QR-кода есть четыре разных режима кодирования. Разные виды символов идут по разным каналам, и занимаемое ими место может различаться в несколько раз. Поняв это, можно сознательно управлять плотностью кода.

Четыре режима кодирования: одна информация, очень разные размеры

QR-коды предоставляют отдельные кодировки для разных типов символов, каждая со своей «эффективностью упаковки»:

Режим Символы Бит на символ Относительная эффективность
Цифровой0-9около 3,33 битаНаивысшая (экономия 40 %)
Буквенно-цифровой0-9 A-Z пробел $%*+-./:около 5,5 битаВысокая
БайтовыйВсё остальное (вкл. китайский)8 битБазовый
КандзиКандзи Shift-JIS13 битНемного лучше для частых CJK

Главное: один китайский иероглиф в UTF-8 занимает 3 байта, то есть 24 бита, тогда как одна латинская буква — 1 байт (8 бит). Значит, для одних и тех же «20 символов» китайскому нужно 480 бит, а английскому всего 160 — разница в 3 раза.

Это и есть самая прямая причина, почему китайские QR-коды выходят плотнее.

Режим кандзи помогает немного, но с условиями

Стандарт QR включает отдельный «режим кандзи», где каждый символ занимает всего 13 бит — почти вдвое меньше 24 бит байтового режима. Звучит отлично, но есть жёсткое ограничение: он поддерживает только символы, существующие в кодировке Shift-JIS.

Shift-JIS — японская кодировка, и набор охватываемых ею символов не полностью совпадает с GB2312 или Unicode. Поэтому:

  • Многие частые китайские иероглифы попадают в неё и экономят место;
  • Часть упрощённых иероглифов, редкие иероглифы и все некитайские символы (китайская пунктуация, эмодзи) возвращаются к байтовому режиму;
  • Генератор должен разумно переключаться между режимами, иначе экономится очень мало.

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

Попутный практический совет: китайская пунктуация тоже занимает 3 байта. Полноширинная точка 。, запятая ,и перечислительная запятая 、все полноширинные и занимают по 3 байта. Если ваш текст насыщен пунктуацией, попробуйте перейти на полуширинные знаки, чтобы вернуть немного места.

Уровень коррекции ошибок: избыточность покупает устойчивость

Другое место, где QR-код расходует пространство, — код коррекции ошибок. Он использует кодирование Рида — Соломона, чтобы добавить данным избыточность, так что даже при загрязнении части узора исходное содержимое всё ещё можно восстановить. Четыре уровня:

  • Уровень L: около 7 % избыточности, восстанавливает примерно 7 % повреждений
  • Уровень M: около 15 % (самое частое значение по умолчанию)
  • Уровень Q: около 25 %
  • Уровень H: около 30 %, наибольшая устойчивость

Эта избыточность занимает реальное место. На версии 10 (57×57 модулей) уровень L вмещает 271 байт, а уровень H — только 119, то есть почти на 56 % меньше.

Так что если ваш код нужно сканировать лишь с экрана, L или M вполне достаточно, и узор будет заметно реже и легче для сканирования. Прибегайте к Q или H только когда код печатается на чём-то, что может изнашиваться, или когда в центр идёт логотип.

Именно так работает логотип в центре: закрытая область трактуется как повреждение и восстанавливается из 30 % избыточности уровня H. Поставьте логотип на код уровня L — и он по сути не будет сканироваться.

Версия: «размерный класс» QR-кода

Всего есть 40 версий, и версия n имеет длину стороны 4n + 17 модулей:

  • Версия 1: 21 × 21
  • Версия 2: 25 × 25
  • Версия 10: 57 × 57
  • Версия 20: 97 × 97
  • Версия 40: 177 × 177

Ёмкость растёт от нескольких десятков байт на версии 1 до 2 953 байт на версии 40 (уровень L, байтовый режим). Генератор выбирает наименьшую версию, в которую помещается ваш текст.

Здесь стоит отметить два момента:

  • Число модулей растёт как квадрат стороны. Переход с версии 20 на 40 менее чем удваивает сторону, но умножает число модулей на 3,3. Поэтому код высокой версии получает очень мелкие отдельные модули.
  • Слишком мелкие модули не сканируются. Теоретически каждому модулю нужно минимум 2–3 пикселя для стабильного распознавания. Если ваш текст загоняет версию выше 20, а размер печати скромный, на практике он вполне может оказаться нечитаемым.

Практические выводы: сделайте QR-код удобнее для сканирования

Чтобы получить код, который и чёткий, и легко сканируется, оптимизируйте в таком порядке:

  • Сократите содержимое. Это самый действенный рычаг. Более короткие URL, меньше параметров и перенаправление через короткую ссылку посередине — обычный подход. Уменьшите содержимое вдвое, и версия может упасть на несколько ступеней.
  • Понизьте уровень коррекции ошибок. Используйте L или M для показа на экране, а не выбирайте рефлекторно H. Высшие уровни оправданы лишь тогда, когда нужно встроить логотип или код печатается на изнашиваемом материале.
  • Сохраняйте тихую зону. QR-коду нужен чистый отступ минимум в четыре модуля шириной со всех сторон — тихая зона, — который алгоритм распознавания использует, чтобы найти край кода. Срезать её — причина номер один неудач сканирования, ещё более частая, чем размытость.
  • Дайте достаточно пикселей. Минимум 4 пикселя на модуль — безопасная цель, поэтому версии 10 (57 модулей) нужно минимум 228 пикселей ширины.
  • Не используйте маленькое растровое изображение. Если нужно встроить код в картинку, экспортируйте с достаточным разрешением или используйте векторный формат (SVG), чтобы масштабирование его не размыло.

Как понять, насколько плотен ваш код

Два подхода:

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

Во-вторых, отнесите существующий код в декодер QR-кодов и проверьте его версию, уровень коррекции ошибок и тип содержимого. Если найдёте якобы длинный текст в низкой версии, скорее всего, в содержимом есть короткая ссылка.

Оба инструмента работают локально в вашем браузере; изображения, которые вы генерируете и загружаете, никогда не проходят через сервер.

Одним предложением

Плотность QR-кода = байты содержимого ÷ эффективность кодирования + избыточность коррекции ошибок. Китайский считается по 3 байта, китайская пунктуация тоже, поэтому китайские коды от природы плотнее. Чтобы сделать код реже, самые действенные шаги — меньше содержимого и ниже уровень коррекции, а не другой генератор.

Связанные инструменты