aboutsummaryrefslogtreecommitdiff
path: root/lpg/libqr
diff options
context:
space:
mode:
Diffstat (limited to 'lpg/libqr')
-rw-r--r--lpg/libqr/code-create.c100
-rw-r--r--lpg/libqr/qr/code.h8
2 files changed, 102 insertions, 6 deletions
diff --git a/lpg/libqr/code-create.c b/lpg/libqr/code-create.c
index 5582a30..9ce46f7 100644
--- a/lpg/libqr/code-create.c
+++ b/lpg/libqr/code-create.c
@@ -19,6 +19,12 @@ static int count_locators(const struct qr_bitmap * bmp);
static int calc_bw_balance(const struct qr_bitmap * bmp);
static int get_px(const struct qr_bitmap * bmp, int x, int y);
static int get_mask(const struct qr_bitmap * bmp, int x, int y);
+static int draw_format(struct qr_bitmap * bmp,
+ struct qr_code * code,
+ enum qr_ec_level ec,
+ int mask);
+static int calc_format_bits(enum qr_ec_level ec, int mask);
+static unsigned long gal_residue(unsigned long a, unsigned long m);
/* FIXME: the static functions should be in a better
* order, with prototypes.
@@ -63,6 +69,7 @@ static void draw_locator(struct qr_bitmap * bmp, int x, int y)
}
static int draw_functional(struct qr_code * code,
+ enum qr_ec_level ec,
unsigned int mask)
{
struct qr_bitmap * bmp;
@@ -85,8 +92,13 @@ static int draw_functional(struct qr_code * code,
}
/* XXX: alignment pattern */
- /* XXX: mask, format info */
+ /* Format info */
+ setpx(bmp, 8, dim - 8);
+ if (draw_format(bmp, code, ec, mask) != 0)
+ return -1;
+
+ /* Merge data */
qr_bitmap_merge(bmp, code->modules);
qr_bitmap_destroy(code->modules);
code->modules = bmp;
@@ -261,7 +273,7 @@ struct qr_code * qr_code_create(enum qr_ec_level ec,
if (mask < 0)
goto fail;
- if (draw_functional(code, mask) != 0)
+ if (draw_functional(code, ec, mask) != 0)
goto fail;
exit:
@@ -466,3 +478,87 @@ static int get_mask(const struct qr_bitmap * bmp, int x, int y)
return bmp->mask[off] & bit;
}
+static int draw_format(struct qr_bitmap * bmp,
+ struct qr_code * code,
+ enum qr_ec_level ec,
+ int mask)
+{
+ int i;
+ size_t dim;
+ long bits;
+
+ dim = bmp->width;
+
+ bits = calc_format_bits(ec, mask);
+ if (bits < 0)
+ return -1;
+
+ for (i = 0; i < 8; ++i) {
+ if (bits & 0x1) {
+ setpx(bmp, 8, i);
+ setpx(bmp, dim - 1 - i, 8);
+ }
+ bits >>= 1;
+ }
+
+ for (i = 0; i < 7; ++i) {
+ if (bits & 0x1) {
+ setpx(bmp, 8, dim - 7 + i);
+ setpx(bmp, 6 - i + (i == 0), 8);
+ }
+ bits >>= 1;
+ }
+
+ /* XXX: size info for 7~40 */
+
+ return 0;
+}
+
+static int calc_format_bits(enum qr_ec_level ec, int mask)
+{
+ int bits;
+
+ bits = (ec & 0x3) << 3 | (mask & 0x7);
+
+ /* Compute (15, 5) BCH code with
+ * G(x) = x^10 + x^8 + x^5 + x^4 + x^2 + x + 1
+ */
+
+ bits <<= 15 - 5;
+ bits |= (unsigned int)gal_residue(bits, 0x537);
+
+ /* XOR mask: 101 0100 0001 0010 */
+ bits ^= 0x5412;
+
+ return bits;
+}
+
+/* Calculate the residue of a modulo m */
+static unsigned long gal_residue(unsigned long a,
+ unsigned long m)
+{
+ unsigned long o = 1;
+ int n = 1;
+
+ /* Find one past the highest bit of the modulus */
+ while (m & ~(o - 1))
+ o <<= 1;
+
+ /* Find the highest n such that O(m * x^n) <= O(a) */
+ while (a & ~(o - 1)) {
+ o <<= 1;
+ ++n;
+ }
+
+ /* For each n, try to reduce a by (m * x^n) */
+ while (n--) {
+ o >>= 1;
+
+ /* o is the highest bit of (m * x^n) */
+ if (a & o)
+ a ^= m << n;
+ }
+
+ return a;
+}
+
diff --git a/lpg/libqr/qr/code.h b/lpg/libqr/qr/code.h
index 56a9884..dba0040 100644
--- a/lpg/libqr/qr/code.h
+++ b/lpg/libqr/qr/code.h
@@ -5,10 +5,10 @@
#include "types.h"
enum qr_ec_level {
- QR_EC_LEVEL_L,
- QR_EC_LEVEL_M,
- QR_EC_LEVEL_Q,
- QR_EC_LEVEL_H
+ QR_EC_LEVEL_L = 0x1,
+ QR_EC_LEVEL_M = 0x0,
+ QR_EC_LEVEL_Q = 0x3,
+ QR_EC_LEVEL_H = 0x2
};
struct qr_code * qr_code_create(enum qr_ec_level ec,