mask.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * qrencode - QR Code encoder
  3. *
  4. * Masking.
  5. * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
  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. #include <stdlib.h>
  22. #include <string.h>
  23. #include <limits.h>
  24. //#include "config.h"
  25. #include "qrencode.h"
  26. #include "qrspec.h"
  27. #include "mask.h"
  28. //__STATIC
  29. static int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level)
  30. {
  31. unsigned int format;
  32. unsigned char v;
  33. int i;
  34. int blacks = 0;
  35. format = QRspec_getFormatInfo(mask, level);
  36. for(i=0; i<8; i++) {
  37. if(format & 1) {
  38. blacks += 2;
  39. v = 0x85;
  40. } else {
  41. v = 0x84;
  42. }
  43. frame[width * 8 + width - 1 - i] = v;
  44. if(i < 6) {
  45. frame[width * i + 8] = v;
  46. } else {
  47. frame[width * (i + 1) + 8] = v;
  48. }
  49. format= format >> 1;
  50. }
  51. for(i=0; i<7; i++) {
  52. if(format & 1) {
  53. blacks += 2;
  54. v = 0x85;
  55. } else {
  56. v = 0x84;
  57. }
  58. frame[width * (width - 7 + i) + 8] = v;
  59. if(i == 0) {
  60. frame[width * 8 + 7] = v;
  61. } else {
  62. frame[width * 8 + 6 - i] = v;
  63. }
  64. format= format >> 1;
  65. }
  66. return blacks;
  67. }
  68. /**
  69. * Demerit coefficients.
  70. * See Section 8.8.2, pp.45, JIS X0510:2004.
  71. */
  72. #define N1 (3)
  73. #define N2 (3)
  74. #define N3 (40)
  75. #define N4 (10)
  76. #define MASKMAKER(__exp__) \
  77. int x, y;\
  78. int b = 0;\
  79. \
  80. for(y=0; y<width; y++) {\
  81. for(x=0; x<width; x++) {\
  82. if(*s & 0x80) {\
  83. *d = *s;\
  84. } else {\
  85. *d = *s ^ ((__exp__) == 0);\
  86. }\
  87. b += (int)(*d & 1);\
  88. s++; d++;\
  89. }\
  90. }\
  91. return b;
  92. static int Mask_mask0(int width, const unsigned char *s, unsigned char *d)
  93. {
  94. MASKMAKER((x+y)&1)
  95. }
  96. static int Mask_mask1(int width, const unsigned char *s, unsigned char *d)
  97. {
  98. MASKMAKER(y&1)
  99. }
  100. static int Mask_mask2(int width, const unsigned char *s, unsigned char *d)
  101. {
  102. MASKMAKER(x%3)
  103. }
  104. static int Mask_mask3(int width, const unsigned char *s, unsigned char *d)
  105. {
  106. MASKMAKER((x+y)%3)
  107. }
  108. static int Mask_mask4(int width, const unsigned char *s, unsigned char *d)
  109. {
  110. MASKMAKER(((y/2)+(x/3))&1)
  111. }
  112. static int Mask_mask5(int width, const unsigned char *s, unsigned char *d)
  113. {
  114. MASKMAKER(((x*y)&1)+(x*y)%3)
  115. }
  116. static int Mask_mask6(int width, const unsigned char *s, unsigned char *d)
  117. {
  118. MASKMAKER((((x*y)&1)+(x*y)%3)&1)
  119. }
  120. static int Mask_mask7(int width, const unsigned char *s, unsigned char *d)
  121. {
  122. MASKMAKER((((x*y)%3)+((x+y)&1))&1)
  123. }
  124. typedef int MaskMaker(int, const unsigned char *, unsigned char *);
  125. static MaskMaker *maskMakers[] = {
  126. Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3,
  127. Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7
  128. };
  129. unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level)
  130. {
  131. unsigned char *masked;
  132. masked = (unsigned char *)malloc(width * width);
  133. if(masked == NULL) return NULL;
  134. maskMakers[mask](width, frame, masked);
  135. Mask_writeFormatInformation(width, masked, mask, level);
  136. return masked;
  137. }
  138. static int runLength[QRSPEC_WIDTH_MAX + 1];
  139. //static int n1;
  140. //static int n2;
  141. //static int n3;
  142. //static int n4;
  143. static int Mask_calcN1N3(int length, int *runLength)
  144. {
  145. int i;
  146. int demerit = 0;
  147. int fact;
  148. for(i=0; i<length; i++) {
  149. if(runLength[i] >= 5) {
  150. demerit += N1 + (runLength[i] - 5);
  151. //n1 += N1 + (runLength[i] - 5);
  152. }
  153. if((i & 1)) {
  154. if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) {
  155. fact = runLength[i] / 3;
  156. if(runLength[i-2] == fact &&
  157. runLength[i-1] == fact &&
  158. runLength[i+1] == fact &&
  159. runLength[i+2] == fact) {
  160. if(runLength[i-3] < 0 || runLength[i-3] >= 4 * fact) {
  161. demerit += N3;
  162. //n3 += N3;
  163. } else if(i+3 >= length || runLength[i+3] >= 4 * fact) {
  164. demerit += N3;
  165. //n3 += N3;
  166. }
  167. }
  168. }
  169. }
  170. }
  171. return demerit;
  172. }
  173. //__STATIC
  174. static int Mask_evaluateSymbol(int width, unsigned char *frame)
  175. {
  176. int x, y;
  177. unsigned char *p;
  178. unsigned char b22, w22;
  179. int head;
  180. int demerit = 0;
  181. p = frame;
  182. for(y=0; y<width; y++) {
  183. head = 0;
  184. runLength[0] = 1;
  185. for(x=0; x<width; x++) {
  186. if(x > 0 && y > 0) {
  187. b22 = p[0] & p[-1] & p[-width] & p [-width-1];
  188. w22 = p[0] | p[-1] | p[-width] | p [-width-1];
  189. if((b22 | (w22 ^ 1))&1) {
  190. demerit += N2;
  191. }
  192. }
  193. if(x == 0 && (p[0] & 1)) {
  194. runLength[0] = -1;
  195. head = 1;
  196. runLength[head] = 1;
  197. } else if(x > 0) {
  198. if((p[0] ^ p[-1]) & 1) {
  199. head++;
  200. runLength[head] = 1;
  201. } else {
  202. runLength[head]++;
  203. }
  204. }
  205. p++;
  206. }
  207. demerit += Mask_calcN1N3(head+1, runLength);
  208. }
  209. for(x=0; x<width; x++) {
  210. head = 0;
  211. runLength[0] = 1;
  212. p = frame + x;
  213. for(y=0; y<width; y++) {
  214. if(y == 0 && (p[0] & 1)) {
  215. runLength[0] = -1;
  216. head = 1;
  217. runLength[head] = 1;
  218. } else if(y > 0) {
  219. if((p[0] ^ p[-width]) & 1) {
  220. head++;
  221. runLength[head] = 1;
  222. } else {
  223. runLength[head]++;
  224. }
  225. }
  226. p+=width;
  227. }
  228. demerit += Mask_calcN1N3(head+1, runLength);
  229. }
  230. return demerit;
  231. }
  232. unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level)
  233. {
  234. int i;
  235. unsigned char *mask, *bestMask;
  236. int minDemerit = INT_MAX;
  237. int bestMaskNum = 0;
  238. int blacks;
  239. int demerit;
  240. mask = (unsigned char *)malloc(width * width);
  241. if(mask == NULL) return NULL;
  242. bestMask = NULL;
  243. for(i=0; i<8; i++) {
  244. // n1 = n2 = n3 = n4 = 0;
  245. demerit = 0;
  246. blacks = maskMakers[i](width, frame, mask);
  247. blacks += Mask_writeFormatInformation(width, mask, i, level);
  248. blacks = 100 * blacks / (width * width);
  249. demerit = (abs(blacks - 50) / 5) * N4;
  250. // n4 = demerit;
  251. demerit += Mask_evaluateSymbol(width, mask);
  252. // printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, demerit);
  253. if(demerit < minDemerit) {
  254. minDemerit = demerit;
  255. bestMaskNum = i;
  256. if(bestMask != NULL) {
  257. free(bestMask);
  258. }
  259. bestMask = (unsigned char *)malloc(width * width);
  260. if(bestMask == NULL) break;
  261. memcpy(bestMask, mask, width * width);
  262. }
  263. }
  264. free(mask);
  265. return bestMask;
  266. }