Делаем пиксели штрих-кода RGB пригодными для сканирования

Похожий на HCCB от Microsoft перед его прекращением около 2015 года я пытался создать двухмерный штрих-код, который использует пиксели RGB для кодирования более двух возможных состояний (черный / белый).

Теоретически при 100% емкости данных вы могли бы удерживать 16 777 216 разные целые числа в одном пикселе. Однако такой уровень хранения невозможен.


Рассмотрим два цвета RGB 47,213,71 а также 47,213,72:

демонстрация двух соседних значений rgb

Эту незаметную разницу необходимо будет надежно обнаруживать даже в неоптимальных условиях и освещении.

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


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

Таким образом, большой зазор, например 128, может сделать каждый пиксель возможным в общей сложности 8 цветами — как в оригинальном HCCB от Microsoft; В то время как небольшой промежуток, такой как 1, даст вам вышеупомянутые 16 777 216 цветов.

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

#include <stdio.h>
#include <stdint.h>

uint8_t* bind(uint32_t val, uint8_t bound){
  static uint8_t rgb[3];
  uint32_t buffer[3];
  uint32_t max = bound*(256/bound);

  buffer[0] = val * bound;
  buffer[1] = (buffer[0]/max)*bound;
  buffer[2] = (buffer[1]/max)*bound;

  rgb[0] = buffer[0] % max;
  rgb[1] = buffer[1] % max;
  rgb[2] = buffer[2] % max;

  return rgb;
}

uint32_t unbind(uint8_t* rgb, uint8_t bound){
  uint32_t max = 256/bound;
  return (rgb[0]/bound)+(rgb[1]/bound)*max+(rgb[2]/bound)*max*max;
}

int main(void) {
  uint32_t data = 1;
  uint8_t color_range = 128;

  uint8_t* colors = bind(data, color_range);
  uint32_t calculated = unbind(colors, color_range);

  printf("expected value: %unreturned value: %unn", data, calculated);
  printf("rgb value: %u,%u,%un", colors[0], colors[1], colors[2]);
  return 0;
}

1 ответ
1

Этот:

static uint8_t rgb[3];
return rgb;

это проблема. Два разных вызывающих абонента, предполагающие, что у них есть две разные копии возвращаемого массива, на самом деле будут иметь только одну, и это прерывает повторный вход. В этом случае лучше возвращать по значению, а не по ссылке, особенно если вы создаете служебную структуру. Обычный шаблон — union над трехэлементным массивом и вложенной структурой из красного, зеленого и синего компонентов. Чтобы убедиться, что это действительно так, вам нужно указать вашему компилятору использовать плотную упаковку, обычно с #pragma pack. Если у вас есть опасения по поводу переносимости этого подхода и вам нужно поддерживать несколько экзотических компиляторов, вам нужно отказаться от union а вместо этого напишите функцию преобразования.

bind а также unbind оба могут быть отмечены static поскольку они находятся в одной единице перевода.

Единственная другая незначительная вещь, которую я здесь вижу, — это то, что отступ в два пробела несколько нестандартен, а четыре пробела будут более разборчивыми.

  • Могу ли я заставить его принимать указатель на массив rgb в качестве аргумента и сделать так, чтобы сама функция возвращала значение void?

    — QuestionLimitGoBrrrrr

  • Да, это тоже возможно.

    — Райндериен

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *