qrencode  4.1.1
About: libqrencode is a fast and compact library and command-line utility for encoding data in a QR Code symbol.
  Fossies Dox: qrencode-4.1.1.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

mask.c
Go to the documentation of this file.
1/*
2 * qrencode - QR Code encoder
3 *
4 * Masking.
5 * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#if HAVE_CONFIG_H
23# include "config.h"
24#endif
25#include <stdlib.h>
26#include <string.h>
27#include <limits.h>
28#include <errno.h>
29
30#include "qrencode.h"
31#include "qrspec.h"
32#include "mask.h"
33
34STATIC_IN_RELEASE int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level)
35{
36 unsigned int format;
37 unsigned char v;
38 int i;
39 int blacks = 0;
40
41 format = QRspec_getFormatInfo(mask, level);
42
43 for(i = 0; i < 8; i++) {
44 if(format & 1) {
45 blacks += 2;
46 v = 0x85;
47 } else {
48 v = 0x84;
49 }
50 frame[width * 8 + width - 1 - i] = v;
51 if(i < 6) {
52 frame[width * i + 8] = v;
53 } else {
54 frame[width * (i + 1) + 8] = v;
55 }
56 format= format >> 1;
57 }
58 for(i = 0; i < 7; i++) {
59 if(format & 1) {
60 blacks += 2;
61 v = 0x85;
62 } else {
63 v = 0x84;
64 }
65 frame[width * (width - 7 + i) + 8] = v;
66 if(i == 0) {
67 frame[width * 8 + 7] = v;
68 } else {
69 frame[width * 8 + 6 - i] = v;
70 }
71 format= format >> 1;
72 }
73
74 return blacks;
75}
76
77/**
78 * Demerit coefficients.
79 * See Section 8.8.2, pp.45, JIS X0510:2004.
80 */
81#define N1 (3)
82#define N2 (3)
83#define N3 (40)
84#define N4 (10)
85
86#define MASKMAKER(__exp__) \
87 int x, y;\
88 int b = 0;\
89\
90 for(y = 0; y < width; y++) {\
91 for(x = 0; x < width; x++) {\
92 if(*s & 0x80) {\
93 *d = *s;\
94 } else {\
95 *d = *s ^ ((__exp__) == 0);\
96 }\
97 b += (int)(*d & 1);\
98 s++; d++;\
99 }\
100 }\
101 return b;
102
103static int Mask_mask0(int width, const unsigned char *s, unsigned char *d)
104{
105 MASKMAKER((x+y)&1)
106}
107
108static int Mask_mask1(int width, const unsigned char *s, unsigned char *d)
109{
110 MASKMAKER(y&1)
111}
112
113static int Mask_mask2(int width, const unsigned char *s, unsigned char *d)
114{
115 MASKMAKER(x%3)
116}
117
118static int Mask_mask3(int width, const unsigned char *s, unsigned char *d)
119{
120 MASKMAKER((x+y)%3)
121}
122
123static int Mask_mask4(int width, const unsigned char *s, unsigned char *d)
124{
125 MASKMAKER(((y/2)+(x/3))&1)
126}
127
128static int Mask_mask5(int width, const unsigned char *s, unsigned char *d)
129{
130 MASKMAKER(((x*y)&1)+(x*y)%3)
131}
132
133static int Mask_mask6(int width, const unsigned char *s, unsigned char *d)
134{
135 MASKMAKER((((x*y)&1)+(x*y)%3)&1)
136}
137
138static int Mask_mask7(int width, const unsigned char *s, unsigned char *d)
139{
140 MASKMAKER((((x*y)%3)+((x+y)&1))&1)
141}
142
143#define maskNum (8)
144typedef int MaskMaker(int, const unsigned char *, unsigned char *);
148};
149
150#ifdef WITH_TESTS
151unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask)
152{
153 unsigned char *masked;
154
155 masked = (unsigned char *)malloc((size_t)(width * width));
156 if(masked == NULL) return NULL;
157
158 maskMakers[mask](width, frame, masked);
159
160 return masked;
161}
162#endif
163
164unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level)
165{
166 unsigned char *masked;
167
168 if(mask < 0 || mask >= maskNum) {
169 errno = EINVAL;
170 return NULL;
171 }
172
173 masked = (unsigned char *)malloc((size_t)(width * width));
174 if(masked == NULL) return NULL;
175
176 maskMakers[mask](width, frame, masked);
177 Mask_writeFormatInformation(width, masked, mask, level);
178
179 return masked;
180}
181
182
183//static int n1;
184//static int n2;
185//static int n3;
186//static int n4;
187
188STATIC_IN_RELEASE int Mask_calcN1N3(int length, int *runLength)
189{
190 int i;
191 int demerit = 0;
192 int fact;
193
194 for(i = 0; i < length; i++) {
195 if(runLength[i] >= 5) {
196 demerit += N1 + (runLength[i] - 5);
197 //n1 += N1 + (runLength[i] - 5);
198 }
199 if((i & 1)) {
200 if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) {
201 fact = runLength[i] / 3;
202 if(runLength[i-2] == fact &&
203 runLength[i-1] == fact &&
204 runLength[i+1] == fact &&
205 runLength[i+2] == fact) {
206 if(i == 3 || runLength[i-3] >= 4 * fact) {
207 demerit += N3;
208 //n3 += N3;
209 } else if(i+4 >= length || runLength[i+3] >= 4 * fact) {
210 demerit += N3;
211 //n3 += N3;
212 }
213 }
214 }
215 }
216 }
217
218 return demerit;
219}
220
221STATIC_IN_RELEASE int Mask_calcN2(int width, unsigned char *frame)
222{
223 int x, y;
224 unsigned char *p;
225 unsigned char b22, w22;
226 int demerit = 0;
227
228 p = frame + width + 1;
229 for(y = 1; y < width; y++) {
230 for(x = 1; x < width; x++) {
231 b22 = p[0] & p[-1] & p[-width] & p [-width-1];
232 w22 = p[0] | p[-1] | p[-width] | p [-width-1];
233 if((b22 | (w22 ^ 1))&1) {
234 demerit += N2;
235 }
236 p++;
237 }
238 p++;
239 }
240
241 return demerit;
242}
243
244STATIC_IN_RELEASE int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength)
245{
246 int head;
247 int i;
248 unsigned char prev;
249
250 if(frame[0] & 1) {
251 runLength[0] = -1;
252 head = 1;
253 } else {
254 head = 0;
255 }
256 runLength[head] = 1;
257 prev = frame[0];
258
259 for(i = 1; i < width; i++) {
260 if((frame[i] ^ prev) & 1) {
261 head++;
262 runLength[head] = 1;
263 prev = frame[i];
264 } else {
265 runLength[head]++;
266 }
267 }
268
269 return head + 1;
270}
271
272STATIC_IN_RELEASE int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength)
273{
274 int head;
275 int i;
276 unsigned char prev;
277
278 if(frame[0] & 1) {
279 runLength[0] = -1;
280 head = 1;
281 } else {
282 head = 0;
283 }
284 runLength[head] = 1;
285 prev = frame[0];
286
287 for(i = 1; i < width; i++) {
288 if((frame[i * width] ^ prev) & 1) {
289 head++;
290 runLength[head] = 1;
291 prev = frame[i * width];
292 } else {
293 runLength[head]++;
294 }
295 }
296
297 return head + 1;
298}
299
300STATIC_IN_RELEASE int Mask_evaluateSymbol(int width, unsigned char *frame)
301{
302 int x, y;
303 int demerit = 0;
304 int runLength[QRSPEC_WIDTH_MAX + 1];
305 int length;
306
307 demerit += Mask_calcN2(width, frame);
308
309 for(y = 0; y < width; y++) {
310 length = Mask_calcRunLengthH(width, frame + y * width, runLength);
311 demerit += Mask_calcN1N3(length, runLength);
312 }
313
314 for(x = 0; x < width; x++) {
315 length = Mask_calcRunLengthV(width, frame + x, runLength);
316 demerit += Mask_calcN1N3(length, runLength);
317 }
318
319 return demerit;
320}
321
322unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level)
323{
324 int i;
325 unsigned char *mask, *bestMask;
326 int minDemerit = INT_MAX;
327 int blacks;
328 int bratio;
329 int demerit;
330 int w2 = width * width;
331
332 mask = (unsigned char *)malloc((size_t)w2);
333 if(mask == NULL) return NULL;
334 bestMask = (unsigned char *)malloc((size_t)w2);
335 if(bestMask == NULL) {
336 free(mask);
337 return NULL;
338 }
339
340 for(i = 0; i < maskNum; i++) {
341// n1 = n2 = n3 = n4 = 0;
342 demerit = 0;
343 blacks = maskMakers[i](width, frame, mask);
344 blacks += Mask_writeFormatInformation(width, mask, i, level);
345 bratio = (200 * blacks + w2) / w2 / 2; /* (int)(100*blacks/w2+0.5) */
346 demerit = (abs(bratio - 50) / 5) * N4;
347// n4 = demerit;
348 demerit += Mask_evaluateSymbol(width, mask);
349// printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, demerit);
350 if(demerit < minDemerit) {
351 minDemerit = demerit;
352 memcpy(bestMask, mask, (size_t)w2);
353 }
354 }
355 free(mask);
356 return bestMask;
357}
static int Mask_mask0(int width, const unsigned char *s, unsigned char *d)
Definition: mask.c:103
static int Mask_mask3(int width, const unsigned char *s, unsigned char *d)
Definition: mask.c:118
static int Mask_mask7(int width, const unsigned char *s, unsigned char *d)
Definition: mask.c:138
static int Mask_mask2(int width, const unsigned char *s, unsigned char *d)
Definition: mask.c:113
STATIC_IN_RELEASE int Mask_evaluateSymbol(int width, unsigned char *frame)
Definition: mask.c:300
#define MASKMAKER(__exp__)
Definition: mask.c:86
STATIC_IN_RELEASE int Mask_calcN1N3(int length, int *runLength)
Definition: mask.c:188
static int Mask_mask5(int width, const unsigned char *s, unsigned char *d)
Definition: mask.c:128
unsigned char * Mask_mask(int width, unsigned char *frame, QRecLevel level)
Definition: mask.c:322
static int Mask_mask6(int width, const unsigned char *s, unsigned char *d)
Definition: mask.c:133
int MaskMaker(int, const unsigned char *, unsigned char *)
Definition: mask.c:144
STATIC_IN_RELEASE int Mask_calcN2(int width, unsigned char *frame)
Definition: mask.c:221
static int Mask_mask4(int width, const unsigned char *s, unsigned char *d)
Definition: mask.c:123
static int Mask_mask1(int width, const unsigned char *s, unsigned char *d)
Definition: mask.c:108
#define N4
Definition: mask.c:84
STATIC_IN_RELEASE int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level)
Definition: mask.c:34
unsigned char * Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level)
Definition: mask.c:164
#define N1
Demerit coefficients.
Definition: mask.c:81
STATIC_IN_RELEASE int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength)
Definition: mask.c:244
#define N2
Definition: mask.c:82
#define maskNum
Definition: mask.c:143
#define N3
Definition: mask.c:83
static MaskMaker * maskMakers[(8)]
Definition: mask.c:145
STATIC_IN_RELEASE int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength)
Definition: mask.c:272
static QRecLevel level
Definition: qrenc.c:50
QRecLevel
Level of error correction.
Definition: qrencode.h:124
unsigned int QRspec_getFormatInfo(int mask, QRecLevel level)
Format information.
Definition: qrspec.c:383
#define QRSPEC_WIDTH_MAX
Version and capacity.
Definition: qrspec.h:34