aboutsummaryrefslogtreecommitdiff
path: root/lpg/libqr/code-create.c
blob: d09c2fe2d79480e11d8c95686a7fa5b9394be3f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#include <qr/code.h>

#include "code-common.h"
#include "data-common.h"

#define MIN(a, b) ((b) < (a) ? (b) : (a))

#include <stdio.h>
static void x_dump(struct bitstream * bits)
{
        size_t i, n;

        bitstream_seek(bits, 0);
        n = bitstream_size(bits);
        for (i = 0; i < n; ++i) {
                printf("%d", bitstream_read(bits, 1));
                if (i % 8 == 7)
                        printf(" ");
                if ((i+1) % (7 * 8) == 0)
                        printf("\n");
        }
        printf("\n");
}

static int add_ecc(struct bitstream * bits, int format, enum qr_ec_level ec)
{
        puts("Before ecc:");
        x_dump(bits);

        return -1;
}

static int pad_data(struct bitstream * bits, size_t limit)
{
        /* This function is not very nice. Sorry. */

        size_t count, n;

        assert(bitstream_size(bits) <= limit);

        if (bitstream_resize(bits, limit) != 0)
                return -1;

        n = bitstream_size(bits);
        bitstream_seek(bits, n);
        count = limit - n;

        /* First append the terminator (0000) if possible,
         * and pad with zeros up to an 8-bit boundary
         */
        n = (n + 4) % 8;
        if (n != 0)
                n = 8 - n;
        n = MIN(count, n + 4);
        bitstream_write(bits, 0, n);
        count -= n;

        assert(count % 8 == 0); /* since data codewords are 8 bits */

        /* Finally pad with the repeating sequence 11101100 00010001 */
        while (count >= 16) {
                bitstream_write(bits, 0xEC11, 16);
                count -= 16;
        }
        if (count > 0) {
                assert(count == 8);
                bitstream_write(bits, 0xEC, 8);
        }

        return 0;
}

static struct bitstream * make_data(int                format,
                                    enum qr_ec_level   ec,
                                    struct bitstream * data)
{
        size_t data_bits = 16 * 8 /*XXX*/;
        struct bitstream * out;

        out = bitstream_copy(data);
        if (!out)
                return 0;

        if (pad_data(out, data_bits) != 0)
                goto fail;

        if (add_ecc(out, format, ec) != 0)
                goto fail;

        return out;
fail:
        bitstream_destroy(out);
        return 0;
}

struct qr_code * qr_code_create(enum qr_ec_level       ec,
                                const struct qr_data * data)
{
        struct qr_code * code;
        struct bitstream * ecdata;

        code = malloc(sizeof(*code));
        if (!code)
                return 0;

        code->format = data->format;
        ecdata = make_data(data->format, ec, data->bits);

        if (!ecdata) {
                free(code);
                return 0;
        }

        /* TODO: allocate bitmap; layout */

        return 0;
}