Пандемия, осеннее обострение, зима близко и QR коды на каждом шагу, роботы наступают, рутина работы затягивает. Хочешь покушать — покажи картинку. Скучную и квадратную, для робота, не для человека. Только единицы могут ее читать, и только избранные рисовать. Вон на прошлой неделе как хабр qr кодом бомбануло!


Идея

А что если оживить и “очеловечить” QR код, сделать его не только для робота, но и для человека? Такая мысль мне не приходила, до тех пор пока я не наткнулся на статью про генерацию фотомозаик в виде QR кодов, наткнулся совершенно случайно, в процессе изучения вопроса генерации изображений для приложения по расчету параметров для варки пива. “QR кодная Мона Лиза” из этой статьи меня покорила своей причастностью к текущим реалиям.

Moza Лиза
Moza Лиза

И появилась идея. А если есть идея, то можно быстро сделать вечерний спайк на коленке и проверить ее работоспособность - “тыж программист”. Увы, спайк получился так себе, QR код читался через раз и выглядел отвратно, но идея не отпускала. Уж очень хотелось взять этот скучный ковидный QR код и сделать его прикольным, чтобы люди проверяющие его в кафе или торговом центре улыбнулись и настроение их улучшилось.

Так вечерний спайк превратился в ночной ресерч. И к утру, я нашел две вещи достойные внимания и работы над ними. Это были “halftone qr codes” и “Aesthetic QR codes”. А еще перелопатил кучу коммерчески успешных приложений которые умеют рисовать QR по всякому: рисуют классно, красиво, стабильно и… скучно.

Реализация день первый

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

Мы выбрали Next.js от Vercel. Так как на React уже что-то писали и очень хотелось пощупать как работает их реализация serverless, а еще хотелось ощутить степень интеграции с гитхабом и прочие неведомые плюшки. Так же рассматривали возможность сделать нативные приложения используя react-native, но вовремя поняли, что за выходные этого не реализовать, а веб приложение всегда можно поместить на рабочий стол в пару тачей.

yarn create next-app
yarn create next-app

Название родилось быстро, сошлись на QRART, Мона Лиза сыграла в этом не последнюю роль, да и pixel ART тоже проходил рядом. Купили домен и проксировали его через cloudflare на проект в vercel, для того чтобы еще на уровне dns отсечь ботов и всякую агрессивную нечисть. Проксирование оказалось очень простым и как приятное дополнение мы получили бесплатный https из коробки. Оказалось что можно не поднимать сервачок с убунтой, и не шаманить с letsencrypt, certbot-том и апачем. Что все просто работает, фактически на острие технологий.

За первую половину дня мы напилили спайк, который брал урл, превращал его в qr код используя библиотеку qrcode-generator в npm и отрисовывал на канвас результат. 

Технически идея и реализация получилась простая. Мы делаем картинку в градациях серого и поверх нее рисуем точки или по правильному модули QR кода, по факту точки черного и белого цвета. По умолчанию мы используем средний уровень коррекции ошибок, в котором можно восстановить 15 процентов информации. А размер QR кода 6, это значит что в нем будет 41 модуль или точка, такой размер лучше всего подходит для визуального представления картинок. Конечно есть ограничения по размеру данных, но ссылка с ГосУслуг влезает. Вот тут можно посмотреть таблицу вместимости.

Дальше лучше в демке смотреть.
Дальше лучше в демке смотреть.

Локально все работало просто прекрасно, и мы попробовали задеплоить в облако. И обломались, оказалось что с 2019 года vercel не может подружить библиотеки канваса с лямбдами. Добро пожаловать в мир серверлесс. Ну ничего, ничего, поставили подпорку - все заработало, хакатон как-никак.

Ближе к концу первого дня у нас было приложение которое умело генерить QR код по урлу или тексту, и сращивать его с картинкой, которую предварительно мы переводили в оттенки серого. Спайк работал. 

Захотелось локализацию и в Next она есть из коробки, да еще и с определением локалей, что очень и очень удобно. Называется это i18n-routing.

UI нашего спайка выглядел не особо, да и мы не дизайнеры. Но мы очень любим игры, старенькие nes’совские. И оказалось, есть готовая библиотека NES.css, которая стала фундаментом в дизайне нашего приложения и сэкономила кучу времени.

NES ностальгия
NES ностальгия

Еще захотелось добавить шаринг во все что можно, для этого мы использовали addthis, но мы не смогли добавить его в Next на уровне кода. Причину искать долго не стали. А просто использовали cloudflare apps и добавили addthis не через код. И оно работает, что удивительно.  (Кстати, кто знает напишите, этот гад посылает запрос, но ничего не отрисовывает. Или подскажите в комментах хорошую альтернативу для шаринга)

Расшарить во все!
Расшарить во все!

Для аналитики мы взяли plausible.io это легковесное решение, которое пилят два разработчика и она тоже серверлесс. Но можно и у себя развернуть на большом, настоящем, железном сервачке.

В итоге первого дня разработки у нас было локализованное на два языка приложение, которое выглядело не отвратно, и даже минимально работало. Был выстроен удобный “пайплайн” разработки благодаря интеграции Vercel проекта с репозиторием и  деплоем в прод по коммиту в мастер. 

А еще был план на следующий день. Который мы просто записали в readme репозитория, да и весь TODO вели там же в одном файлике. Без трелл, планнеров джир и прочих сложных энтерпрайз штуковин.

Реализация день второй

В первый день работы над приложением мы реально кайфанули от разработки и прощупывания стека технологий, даже проблема с канвасом (которую не могут решить с 2019 года sic!) казалась не ущербностью, а просто технической недоработкой, на которую можно закрыть глаза.

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

С редиректа и стартовали. И тут выяснился интересный момент, что forwardemail который я успешно использовал для нескольких проектов, не заработал в связке с cloudflare и vercel. А improvmx.com заработал без вопросов. Почему так? Мы, следуя выбранной парадигме хакатона - "работает не трогай", исследовать не стали.

Галерею сделали из стандартного пакета react-image-gallery, тут все прошло гладко.

Котиков мало не бывает!
Котиков мало не бывает!
<ImageGallery
	ref={gallery}
	additionalClass="img-gallery animate__animated animate__bounceInDown"
	items={galleryItems}
	infinite={false}
	showPlayButton={false}
	showFullscreenButton={false}
/>

А вот с генерацией из загружаемой картинки пришлось повозиться. Момент в том что создание QR кодов происходит на сервере, и туда нужно эту картинку передать. По хорошему для этого нужно делать multipart запрос и передавать картинку. Обычно это делают в миделваре для next api routes. Но, хакатон же. В итоге, мы жмем картинку на клиенте и отправляем ее на сервер как json.

Не, ну а чо?
Не, ну а чо?

А обработанный результат складываем в DO spaces, конечно тут можно было взять хранилище от Amazon. Но под рукой оказался DO, тем более что он просто проксирует Amazon.

В завершении дня мы нашли и починили баг созданием QR кода в котором есть киррилица. Код создавался, но считывалась какая-то ерунда. Оказалось нужно прописать использование многобайтовой кодировки. Одна строчка кода и столько радости, что русский язык заработал:

qrcode.stringToBytes = qrcode.stringToBytesFuncs['UTF-8']

Результат

От второго дня нашего крафтового хакатона мы тоже остались очень довольны. И даже пофантазировали над фичами которые можно еще сделать - цветные qr коды, как это делает visualead, коды из мозаик, аналитика для qr кодов и многое многое другое.

Даже была идея открыть код, но там сейчас все довольно страшненько написано. Сейчас это скорее спайк, без тестов, без документации и с некоторыми явными костылями. И путь от спайка к настоящему продукту долог.

Главный результат в том, что мы получили кучу положительных эмоций от этих двух дней разработки. Мы можем точно сказать что выбранный нами стек отлично подходит для прототипирования приложений и его можно использовать.

Будем рады, если и вам понравится наш эксперимент.

Mono Лиза
Mono Лиза

А еще я успел написать статью которую вы сейчас прочитали. Мона Лиза прилагается и улыбается вам сквозь время и пиксели. Спасибо!

PS после публикации выяснилось что есть целое направление искусства, которое занимается созданием красивых QR кодов. И называется оно quick response art. И уже есть реализации генераторов, которые делают коды круто и красиво. Например библиотека amazing-qr. Скорее всего есть еще решения и сервисы. Буду вести и пополнять список под статьей.

amazing-qr - Python QR Code Generator GPLv3

Комментарии (63)


  1. Chuvi
    22.11.2021 10:06
    +8

    BinaryEye QR-коды из статьи QR-кодами не посчиитал.

    Вот вам и вжух.


    1. SeOd Автор
      22.11.2021 10:10

      Ох уж эти баги. ) Нужно глянуть что это за штука BinaryEye, iphone и android норм читает из коробки.


      1. El_Kraken_Feliz
        22.11.2021 10:18
        +4

        У меня читается, андроид


      1. Chuvi
        22.11.2021 10:20
        +1

        Решил проверить через Google Объектив.

        Во-первых работает, а во-вторых, нашлись похожие изображения. https://habr.com/ru/post/310052/


        1. SeOd Автор
          22.11.2021 10:22

          Дык идея полутоновых кодов еще 2013 года. На хабре не видел, спасибо за ссылку! Можно будет применить.


      1. FotoHunter
        23.11.2021 21:36

        Яндекс "поиск по фото" и гугл "умная лупа" - увидели мону лизу и не стали читать текст. Зато накидали и оригинальные фото и другие фото с qr-кодами. Видимо алгоритмы этих сайтов в первую очередь видят фото в целом и не воспринимают её как qr код. Только первы qrCat распознался правильно.


    1. vvzvlad
      22.11.2021 13:26
      +1

      Стандартная эппловская камера тоже.


      1. SeOd Автор
        22.11.2021 13:32

        А моделька какая телефона?


    1. xakep2011
      22.11.2021 14:19

      "Сканер QR- и штрих-кодов" https://play.google.com/store/apps/details?id=com.teacapps.barcodescanner прочитал без промедлений. Довольно мощное приложение, читает самые хардкорные экземляры.


      1. SeOd Автор
        22.11.2021 16:20

        Круто!


      1. Pinkbyte
        22.11.2021 20:52

        Странно, именно он у меня как раз Моно Лизу и не осилил, в отличие от встроенного в Firefox-а под андроид сканера...


    1. cepera_ang
      22.11.2021 14:56

      У меня читает, только не очень стабильно, надо поиграться с положением/углом, чтобы поймал.


      1. Beanut
        22.11.2021 15:39
        +2

        Я представляю как проверяющий в кафе сидит пыхтит пытаясь заставить свой сканер считать этот код. Итак день не задался, так еще эти "весельчаки" со своими нескучными QR-кодами.


        1. SeOd Автор
          22.11.2021 16:19
          +1

          Да, подтверждаю некоторые андроид устройства не всегда читают код. Дочь пришла из школы, провела там всестороннее тестирование на реальных устройствах)
          Поправим, скорее всего накосячили в генерации картинки, подсмотрим как у крутых ребят сделано. Может и цвет добавим, но на это не буду загадывать.


    1. mitasamodel
      22.11.2021 16:50

      QR Droid Private + LG V30 ничего не прочитали
      А вот это прочиталось (отсюда):

      QR
      image


      1. SeOd Автор
        22.11.2021 20:05

        Ну так ручной труд не победить, да там есть проблема с генерацией. Мы о ней знаем, даже примерно понятно как чинить.


    1. Medeyko
      22.11.2021 18:31

      Либо какая-то совсем допотопная версия BinaryEye, либо у Вас что-то с экраном или с камерой. У меня совершенно без проблем прочитал всё, в том числе и на запасном дешёвом телефоне с не самой лучшей камерой.


    1. Fullmoon
      22.11.2021 22:19
      +1

      У меня специализированное приложение прочитало (правда, с цветным повозилось), а вот родная самсунговская камера слишком универсальная, и вместо кода в первую очередь полезла определять лицо.


      1. SeOd Автор
        22.11.2021 22:23
        +1

        запала на Мона Лизу) Мы тут в логах обнаружили что пришел чат бот и давай к лямбдам приставать. То им текст введет, то картинку подсунет, я подозреваю что у них там уже отношения. Вроде надо и забанить, а вдруг это любовь...


        1. Kazehay
          23.11.2021 20:35

          Забаньте. Любовь не знает преград, а вот неразумным не стоит делать лишних поблажек))


  1. ihost
    22.11.2021 11:58
    +2

    1. Cerberuser
      22.11.2021 13:40

      При отправке строки длиннее 106 символов получаю Internal Server Error. Это так и задумано?


      1. SeOd Автор
        22.11.2021 13:44
        +1

        Скорее нет, чем да. Нужно поставить отбивки и проверки. Мы по логам лямбды видим что кто-то сует большой текст. И знаем о проблеме. Обязательно починим.


  1. Cost_Estimator
    22.11.2021 13:40
    +1

    Сканер QR (разработчик — TeaCapps), на андроиде. Распознал все три кода из статьи. Классная идея, спасибо )

    Кстати, вот рекурсивный QR-кот
    image


    1. SeOd Автор
      22.11.2021 13:46

      Идея старая, мы на новаторство не претендуем) Это такой привет из прошлого на относительно свежем стеке технологий.

      Рекурсивный QR кот, мем родился)


  1. stim644
    22.11.2021 13:48

    qr коды не использую))


  1. Psychorabbi
    22.11.2021 16:19
    +4

    Хммм, как насчёт qr-кода, перезагружающего устройство при сканировании? Это могло бы помочь побыстрее разобраться с очередями на входах.


    1. SeOd Автор
      22.11.2021 16:20
      +1

      тут главное не присесть за это дело. совсем на грани будет.


  1. KoteMilote
    22.11.2021 16:56
    +5

    хорошая идея что бы разжиться базой QR кодов о прививках, а потом их можно будет продавать


    1. SeOd Автор
      23.11.2021 11:23
      +1

      фичу в TODO добавлять?


      1. iMoHax
        24.11.2021 11:05

        Поиск еще добавить, чтобы можно было по первым буквам ФИО подобрать нужный


  1. Medeyko
    22.11.2021 18:35

    А почему вы так щепетильно отнеслись к полосам синхронизации? На картине “QR кодная Мона Лиза” с ними обошлись так же, как и с остальными полями, кроме поисковых и выравнивающего узоров. Вы ориентировались на спецификацию?

    Просто, на мой взгляд, полосы синхронизации вносят в картинку заметный диссонанс...


    1. SeOd Автор
      22.11.2021 22:03

      Мы сгенерировали qr код с помощью библиотеки qrcode-generator. И в виде точек совместили с изображением. Он сканировался совсем плохо, потом мы добавили полноразмерные position pattern (поисковые узоры) - это не помогло. А дальше стали добавлять запчасти qr кода до тех пор пока он не сканировался нормально айфоном который был под рукой. Это подход совсем не по спецификации и возможно сейчас из за этого проблемы на некоторых устройствах. Но это все-таки спайк выходного дня.


      1. Medeyko
        22.11.2021 22:48

        По спецификации, насколько я знаю, ищется и анализируется средняя яркость поля, а форма особого значения не имеет. Может, эта информация будет вам чем-то полезна.

        А вы error correction level не хотите сделать 'H', а не 'M', как у вас сейчас (библиотека вроде поддерживает, насколько я посмотрел)? Будет несколько лучше сканироваться.

        Ещё дешёвый способ улучшить распознавание - увеличить радиус информационных точек. По-моему, если чуть-чуть увеличить, останется красиво, а уровень распознавания вырастет сильно.


        1. SeOd Автор
          23.11.2021 11:23

          Уровень коррекции поставили M, чтоб ссылка на гос услуги влезала. А версию 6 чтобы меньше квадратов было. Размеры точек определяли от обратного, по факту уменьшали их до тех пор пока телефон переставал распознавать. Возможно переборщили, так как iphone хорош в распознавании кодов.


  1. ifap
    22.11.2021 18:42
    +1

    А что если оживить и “очеловечить” QR код, сделать его не только для робота, но и для человека?

    А мсье знает толк в приключениях ;) Рассказываю, что будет если: это не код а непойми что, досвидос, не задерживайте очередь! И особо строгие ревнители устава караульно-постовой службы даже не будут пытаться его сканировать.


    1. SeOd Автор
      22.11.2021 20:11
      +2

      Вполне возможная ситуация. Ну я бы не провоцировал важные инстанции. А вот в паб сходить с таким кодом самое оно.


  1. BloodyKompot
    22.11.2021 20:07

    Классно придумано! Переделал свой qr-сертификат под любимого Doge, теперь черно-белые квадраты радуют глаз))


  1. glooow
    22.11.2021 20:07
    +1

    Признаться, я не совсем понял, для чего его вообще "очеловечивать". Будет, конечно же, нескучно (как болгенос), но мне кажется это только геморрой лишний. Чем меньше тактов тела требует какое-то действие, тем для тела лучше, а где лучше для тела, там лучше для мозга, а где для мозга лучше, там хорошее настроение и вера в завтрашней день!


    1. SeOd Автор
      22.11.2021 20:08
      +2

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


  1. korsarer
    22.11.2021 22:22

    Я так и не понял. А где ссылка на получившийся сайт? Хочется же поробовать. Или есть только приложение? По запросу "QRART" выходит сайт qrart.com, который кажется не имеет отношения к описанному в статье.


    1. Medeyko
      22.11.2021 22:52
      +2

      Подождите. Вы это серьёзно? Или я в шутку не врубился? :)

      Вы пробовали сканировать изображения из статьи? Они все, кроме "Moza Лиза", дают ссылку https://qrart.app/


  1. Kolobrod72
    23.11.2021 00:37

    Штатный "Сканер" из софта "из коробки" Xiaomi Readme 4X. Ч/б Мону Лизу прочитал легко, цветную - с трудом, а кота - только по увеличенной картинке.


  1. Andy_Big
    23.11.2021 08:32

    Аппаратный сканер штрих-кодов цветную Мону Лизу сканирует 1 раз из 5, черно-белую вообще не получилось ни разу за сотню попыток :)


    1. Ds02006
      23.11.2021 09:21
      -1

      Сканер штрих-кодов не обязательно дол уметь считывать QR-коды.


      1. Andy_Big
        23.11.2021 10:54

        Не обязательно. Но мой умеет среди множества других видов и QR.


  1. GT21
    23.11.2021 11:09

    А можно для домохозяек: как этим пользоваться? Начиная с момента как скачать


    1. SeOd Автор
      23.11.2021 11:11

      Качать не нужно. Это просто сайт, который может сделать qr код в виде картинки с текстом или адресом сайта из готовой картинки.

      Исходную картинку можно выбрать готовую или подложить свою.


      1. GT21
        23.11.2021 11:40

        Тогда я не нашел ссылку на сайт. Вижу только на гитхаб


        1. vrusua
          23.11.2021 13:54

          подскажите, где Вы нашли ссылку на гитхаб?


          1. GT21
            23.11.2021 13:56

            "amazing-qr - Python QR Code Generator GPLv3"


            1. vrusua
              24.11.2021 11:18

              понял, это один из сторонних примеров на Python, которые вдохновили авторов статьи, а их приложение на NextJS доступно здесь https://qrart.app, на гитхаб, к сожалению, ссылок нет ((


  1. A_Botov
    23.11.2021 11:12

    С неделю назад как раз появилась аналогичная идея, но немного с другой точки зрения. QR код как инструмент оперативной передачи данных в рекламных блоках вижу регулярно, но в последнее время у многих коды вызывают крайне негативные ассоциации. И вот именно с этой точки зрения и именно в данном контексте было бы неплохо наверное заменить скучные коды нужными в рекламном блоке изображениями.


    1. SeOd Автор
      23.11.2021 11:17
      +1

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

      Во нашел, вот этот: https://www.instagram.com/p/CCHmh0OKFgf/


  1. Lexicon
    23.11.2021 16:02

    Под ноду/веб есть модуль https://www.npmjs.com/package/awesome-qr
    ИМХО, QR коды в виде картинок глазами уже не так узнаваемы
    И красивее почему-то кажутся обычные QR с иконкой в центре


    1. SeOd Автор
      24.11.2021 11:08

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

      Хотелось именно картинок пиксельных. А так да, можно у qr кода поменять глазки, модули красиво отрисовать и картинку в центр добавить. Так в целом все сервисы и делают, это нормальная практика.


  1. fedotovartuom76
    23.11.2021 16:37

    Bing все QR-коды из статьи и комментариев - распознал на лету. Мощная штука на самом деле. Мона Лиза ещё даже полностью в кадр не попала, а он уже считал всё. Трудности у него возникли только с рекурсивным QR-котом из комментов, но через несколько секунд всё-таки прочитал.

    Google объектив немного дольше, но справился со всем кроме рекурсивного QR-кота из комментов. Его ни в какую не хочет сканировать. Родная камера ASUS ZenFone 7 справилась аналогично Google объективу.


  1. mishneg
    23.11.2021 16:38

    Предвижу целую картину из QR-кодов.


  1. Hoodsey112
    24.11.2021 09:07

    У меня прочитались все коды без проблем стандартной камерой (Pixel 5A)


  1. Grigo52
    24.11.2021 11:09

    Вот было бы смешно, если бы вирусы на телефоны начали передавать через QR коды


    1. SeOd Автор
      24.11.2021 11:11

      Вот тут https://hackaday.com/2020/08/17/fitting-snake-into-a-qr-code/ ребята змейку упаковали в qr, так что сунуть вирус или эксплоит вполне реальная ситуация. А с учетом того что люди научились использовать qr, то пора уже антивирус под это дело пилить.


  1. denisshabr
    24.11.2021 16:16
    +2

    Почитал пост, почувствовал себя со смузи и вейпом на гироскутере. Стильно, модно, молодёжно, serverless и ещё дофига модных слов чтобы не скучать.

    Не понимаю в чём прикол этих serverless бомж-пакетов, зависитеть от них, страдать от того, что что-то там не работает как надо, вместо того чтобы за $5-$10 в год взять VPS. Тем более тот же DO Space стоит $5/месяц и вы их уже платите.


    1. SeOd Автор
      24.11.2021 16:36

      Да, все можно на vps развернуть. Будет работать примерно так же. И свитер сам собой прорастет и борода закудрявится)

      Нам, правда, очень понравилось тыкать палочкой serverless стек, в этом точно что то есть. Появилось стойкое ощущение что будущее за облаками, в той или иной реализации.