From 28849b589dcd933b2527d9f231ce6668ed7d19fa Mon Sep 17 00:00:00 2001 From: Leo Howell Date: Sat, 26 Sep 2009 16:08:27 +0900 Subject: (partially) layout code --- lpg/libqr/Makefile | 1 + lpg/libqr/code-create.c | 82 +++++++++++++++++++++++++++---- lpg/libqr/code-layout.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ lpg/libqr/code-layout.h | 12 +++++ lpg/libqr/test.c | 15 ++++++ 5 files changed, 227 insertions(+), 8 deletions(-) create mode 100644 lpg/libqr/code-layout.c create mode 100644 lpg/libqr/code-layout.h diff --git a/lpg/libqr/Makefile b/lpg/libqr/Makefile index 1f34caf..e9783f6 100644 --- a/lpg/libqr/Makefile +++ b/lpg/libqr/Makefile @@ -1,6 +1,7 @@ OBJECTS := bitstream.o \ code-common.o \ code-create.o \ + code-layout.o \ code-parse.o \ code-render.o \ data-common.o \ diff --git a/lpg/libqr/code-create.c b/lpg/libqr/code-create.c index 9ed59de..a462ea3 100644 --- a/lpg/libqr/code-create.c +++ b/lpg/libqr/code-create.c @@ -4,6 +4,7 @@ #include #include "code-common.h" +#include "code-layout.h" #include "data-common.h" #include "rs.h" @@ -26,6 +27,46 @@ static void x_dump(struct bitstream * bits) printf("\n"); } +static void setpx(struct qr_code * code, int x, int y) +{ + size_t off = y * code->line_stride + x / CHAR_BIT; + unsigned char bit = 1 << (x % CHAR_BIT); + + code->modules[off] |= bit; +} + +static void draw_locator(struct qr_code * code, int x, int y) +{ + int i; + for (i = 0; i < 6; ++i) { + setpx(code, x + i, y + 0); + setpx(code, x + 6, y + i); + setpx(code, x + i + 1, y + 6); + setpx(code, x, y + i + 1); + } + for (i = 0; i < 9; ++i) + setpx(code, x + 2 + i % 3, y + 2 + i / 3); +} + +static void draw_fixed_bits(struct qr_code * code) +{ + int dim = code_side_length(code->format); + int i; + + /* Locator pattern */ + draw_locator(code, 0, 0); + draw_locator(code, 0, dim - 7); + draw_locator(code, dim - 7, 0); + + /* Timing pattern */ + for (i = 8; i < dim - 8; i += 2) { + setpx(code, i, 6); + setpx(code, 6, i); + } + + /* XXX: alignment pattern */ +} + static int pad_data(struct bitstream * bits, size_t limit) { /* This function is not very nice. Sorry. */ @@ -157,22 +198,47 @@ struct qr_code * qr_code_create(enum qr_ec_level ec, const struct qr_data * data) { struct qr_code * code; - struct bitstream * ecdata; + struct bitstream * bits = 0; + struct qr_iterator * layout; + size_t dim; code = malloc(sizeof(*code)); if (!code) return 0; + dim = code_side_length(data->format); + code->format = data->format; - ecdata = make_data(data->format, ec, data->bits); + code->line_stride = dim / CHAR_BIT + ((dim % CHAR_BIT) ? 1 : 0); + code->modules = calloc(dim * code->line_stride, sizeof(unsigned char)); - if (!ecdata) { - free(code); - return 0; - } + if (!code->modules) + goto fail; - /* TODO: allocate bitmap; layout */ + draw_fixed_bits(code); - return 0; + bits = make_data(data->format, ec, data->bits); + if (!bits) + goto fail; + + layout = qr_layout_begin(code); + if (!layout) + goto fail; + + bitstream_seek(bits, 0); + while (bitstream_remaining(bits) >= 8) + qr_layout_write(layout, bitstream_read(bits, 8)); + qr_layout_end(layout); + +exit: + if (bits) + bitstream_destroy(bits); + + return code; + +fail: + qr_code_destroy(code); + code = 0; + goto exit; } diff --git a/lpg/libqr/code-layout.c b/lpg/libqr/code-layout.c new file mode 100644 index 0000000..228758a --- /dev/null +++ b/lpg/libqr/code-layout.c @@ -0,0 +1,125 @@ +#include +#include +#include "code-common.h" +#include "code-layout.h" + +struct qr_iterator { + struct qr_code * code; + int dim; + int column; + int row; + int up; + int mask; + unsigned char * p; +}; + +static int is_data_bit(const struct qr_iterator * i) +{ + if (i->row == 6 || i->column == 6) /* timing */ + return 0; + + if (i->column < 9 && i->row < 9) /* top-left */ + return 0; + + if (i->column >= i->dim - 8 && i->row < 9) /* top-right */ + return 0; + + if (i->column < 9 && i->row >= i->dim - 8) /* bottom-left */ + return 0; + + /* XXX: format data */ + /* XXX: alignment pattern */ + + return 1; +} + +static void set_pointer(struct qr_iterator * i) +{ + i->mask = 1 << (i->column % CHAR_BIT); + i->p = i->code->modules + + i->code->line_stride * i->row + + i->column / CHAR_BIT; +} + +static void advance(struct qr_iterator * i) +{ + do { + /* This XOR is to account for the vertical strip of + * timing bits in column 6 which displaces everything. + */ + if ((i->column < 6) ^ !(i->column % 2)) { + /* Right-hand part or at left edge */ + i->column -= 1; + } else { + /* Left-hand part */ + i->column += 1; + + if (( i->up && i->row == 0) || + (!i->up && i->row == i->dim - 1)) { + /* Hit the top / bottom */ + i->column -= 2; + i->up = !i->up; + } else { + i->row += i->up ? -1 : 1; + } + } + + if (i->column < 0) + continue; /* don't go off left edge */ + + /* Check for one-past-end */ + if (i->column == 0 && i->row >= i->dim - 8) + break; + + } while (!is_data_bit(i)); + + set_pointer(i); +} + +struct qr_iterator * qr_layout_begin(struct qr_code * code) +{ + struct qr_iterator * i; + + i = malloc(sizeof(*i)); + if (i) { + i->dim = code_side_length(code->format); + i->code = code; + i->column = i->dim - 1; + i->row = i->dim - 1; + i->up = 1; + set_pointer(i); + } + + return i; +} + +void qr_layout_end(struct qr_iterator * i) +{ + free(i); +} + +unsigned int qr_layout_read(struct qr_iterator * i) +{ + unsigned int x = 0; + int b; + + for (b = 0; b < 8; ++b) { + x |= (*i->p & i->mask) ? 1 : 0; + advance(i); + x <<= 1; + } + + return x; +} + +void qr_layout_write(struct qr_iterator * i, unsigned int x) +{ + int b; + + for (b = 0; b < 8; ++b) { + *i->p |= (x & 0x80) ? i->mask : 0; + advance(i); + x <<= 1; + } +} + diff --git a/lpg/libqr/code-layout.h b/lpg/libqr/code-layout.h new file mode 100644 index 0000000..79e9730 --- /dev/null +++ b/lpg/libqr/code-layout.h @@ -0,0 +1,12 @@ +#ifndef CODE_LAYOUT_H +#define CODE_LAYOUT_H + +struct qr_iterator; + +struct qr_iterator * qr_layout_begin(struct qr_code *); +unsigned int qr_layout_read(struct qr_iterator *); +void qr_layout_write(struct qr_iterator *, unsigned int); +void qr_layout_end(struct qr_iterator *); + +#endif + diff --git a/lpg/libqr/test.c b/lpg/libqr/test.c index ec77bfe..f51b90b 100644 --- a/lpg/libqr/test.c +++ b/lpg/libqr/test.c @@ -33,6 +33,21 @@ int main() { printf("Code width %d\n", qr_code_width(code)); + { + /* Hack: render the code using ANSI terminal art */ + char buf[80*25]; + int x, y; + + qr_code_render(code, buf, 8, 80, 0, 1, 0); + for (y=0;y<21;++y) { + printf("\t|"); + for (x=0;x<21;++x) { + printf("%s ", buf[y*80+x]?"\033[7m":"\033[0m"); + } + printf("\033[0m|\n"); + } + } + return 0; } -- cgit v1.2.3-70-g09d2