aboutsummaryrefslogtreecommitdiff
path: root/lpg/libqr/code-render.c
diff options
context:
space:
mode:
Diffstat (limited to 'lpg/libqr/code-render.c')
-rw-r--r--lpg/libqr/code-render.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/lpg/libqr/code-render.c b/lpg/libqr/code-render.c
new file mode 100644
index 0000000..cdffe24
--- /dev/null
+++ b/lpg/libqr/code-render.c
@@ -0,0 +1,119 @@
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+#include <qr/code.h>
+
+#include "code-common.h"
+
+/* CHAR_BIT | mod_bits (multi-byte) */
+static void render_line_1(unsigned char * out,
+ const unsigned char * in,
+ size_t mod_bits,
+ size_t dim,
+ unsigned long mark,
+ unsigned long space)
+{
+ unsigned char in_mask;
+ size_t n, b;
+
+ in_mask = 1;
+ n = dim;
+
+ while (n-- > 0) {
+ unsigned long v = (*in & in_mask) ? mark : space;
+
+ if ((in_mask <<= 1) == 0) {
+ in_mask = 1;
+ ++in;
+ }
+
+ b = mod_bits / CHAR_BIT;
+ while (b-- > 0) {
+ *out++ = (unsigned char) v;
+ v >>= CHAR_BIT;
+ }
+ }
+}
+
+/* mod_bits | CHAR_BIT (packed) */
+static void render_line_2(unsigned char * out,
+ const unsigned char * in,
+ size_t mod_bits,
+ size_t dim,
+ unsigned long mark,
+ unsigned long space)
+{
+ unsigned char in_mask;
+ size_t n, b, step, shift;
+
+ in_mask = 1;
+ step = CHAR_BIT / mod_bits;
+ shift = CHAR_BIT - mod_bits;
+ n = dim;
+
+ while (n > 0) {
+ unsigned char tmp = 0;
+
+ b = step;
+ while (b-- > 0) {
+ unsigned long v = (*in & in_mask) ? mark : space;
+
+ if ((in_mask <<= 1) == 0) {
+ in_mask = 1;
+ ++in;
+ }
+
+ tmp = (tmp >> mod_bits) | (v << shift);
+ if (--n == 0) {
+ tmp >>= b * mod_bits;
+ break;
+ }
+ };
+
+ *out++ = tmp;
+ }
+}
+
+void qr_code_render(const struct qr_code * code,
+ void * buffer,
+ size_t mod_bits,
+ size_t line_stride,
+ size_t line_repeat,
+ unsigned long mark,
+ unsigned long space)
+{
+ unsigned char * out;
+ const unsigned char * in;
+ size_t n, dim;
+ int pack;
+
+ pack = (mod_bits < CHAR_BIT);
+ assert(!pack || (CHAR_BIT % mod_bits == 0));
+ assert( pack || (mod_bits % CHAR_BIT == 0));
+
+ in = code->modules;
+ out = buffer;
+ dim = qr_code_width(code);
+
+ n = dim;
+ while (n-- > 0) {
+ size_t rpt;
+ unsigned char * next;
+
+ if (pack)
+ render_line_2(out, in, mod_bits, dim, mark, space);
+ else
+ render_line_1(out, in, mod_bits, dim, mark, space);
+
+ rpt = line_repeat;
+ next = out + line_stride;
+ while (rpt-- > 0) {
+ memcpy(next, out, line_stride);
+ next += line_stride;
+ }
+
+ in += code->line_stride;
+ out = next;
+ }
+}
+