aboutsummaryrefslogtreecommitdiff
path: root/lpg/libqr/code-create.c
diff options
context:
space:
mode:
Diffstat (limited to 'lpg/libqr/code-create.c')
-rw-r--r--lpg/libqr/code-create.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/lpg/libqr/code-create.c b/lpg/libqr/code-create.c
new file mode 100644
index 0000000..d09c2fe
--- /dev/null
+++ b/lpg/libqr/code-create.c
@@ -0,0 +1,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;
+}
+