1 #include "qr.h"
2
3 #include "debug.h"
4 #include "stb.h"
5 #include "tox.h"
6 #include "self.h"
7
8 #include "native/image.h"
9
10 #include <qrcodegen.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #define QR_BORDER_SIZE 4 /* unit: QR modules */
16
generate_qr(const char * text,uint8_t * qrcode)17 static bool generate_qr(const char *text, uint8_t *qrcode)
18 {
19 uint8_t temp_buffer[qrcodegen_BUFFER_LEN_MAX];
20 return qrcodegen_encodeText(text, temp_buffer, qrcode, qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN,
21 qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
22 }
23
convert_qr_to_rgb(const uint8_t * qrcode,uint8_t size,uint8_t * pixels)24 static void convert_qr_to_rgb(const uint8_t *qrcode, uint8_t size, uint8_t *pixels)
25 {
26 /* skip first border on y and x axis */
27 uint16_t i = ((QR_BORDER_SIZE * size) + QR_BORDER_SIZE) * 3;
28 for (uint8_t y = 0; y < qrcodegen_getSize(qrcode); y++) {
29 for (uint8_t x = 0; x < qrcodegen_getSize(qrcode); x++) {
30 bool black = qrcodegen_getModule(qrcode, x, y);
31 pixels[i] = pixels[i + 1] = pixels[i + 2] = black ? 0x00 : 0xFF;
32 i += 3;
33 }
34 /* skip border until end of line and border on start of next line */
35 i += (QR_BORDER_SIZE * 2) * 3;
36 }
37 }
38
qr_setup(const char * id_str,uint8_t ** qr_data,int * qr_data_size,NATIVE_IMAGE ** qr_image,int * qr_image_size)39 void qr_setup(const char *id_str, uint8_t **qr_data, int *qr_data_size, NATIVE_IMAGE **qr_image, int *qr_image_size)
40 {
41 const uint8_t channel_number = 3;
42 uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX] = { 0 };
43 char tox_uri[TOX_ADDRESS_STR_SIZE + sizeof("tox:")];
44
45 snprintf(tox_uri, sizeof(tox_uri), "tox:%.*s", (unsigned int) TOX_ADDRESS_STR_SIZE, id_str);
46
47 if (!generate_qr(tox_uri, qrcode)) {
48 LOG_ERR("QR", "Unable to generate QR code from Tox URI.");
49 return;
50 }
51
52 *qr_image_size = qrcodegen_getSize(qrcode);
53 *qr_image_size += QR_BORDER_SIZE * 2; /* add border on both sides */
54 uint8_t pixels[*qr_image_size * *qr_image_size * channel_number];
55 memset(pixels, 0xFF, sizeof(pixels)); /* make it all white */
56 convert_qr_to_rgb(qrcode, *qr_image_size, pixels);
57
58 *qr_data = stbi_write_png_to_mem(pixels, 0, *qr_image_size, *qr_image_size, channel_number, qr_data_size);
59
60 uint16_t native_size = *qr_image_size;
61 *qr_image = utox_image_to_native(*qr_data, *qr_data_size, &native_size, &native_size, false);
62 }
63