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;
}
|