aboutsummaryrefslogtreecommitdiff
path: root/lpg/libqr/qr-bitmap-render.c
blob: 197e947f736e15911ccb925042348a09984cd54e (plain)
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
#include <string.h>
#include <limits.h>
#include <assert.h>

#include <qr/bitmap.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_bitmap_render(const struct qr_bitmap * bmp,
                      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 = bmp->bits;
        out = buffer;
        dim = bmp->width;

        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 += bmp->stride;
                out = next;
        }
}