mmask.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * qrencode - QR Code encoder
  3. *
  4. * Masking for Micro QR Code.
  5. * Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
  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. #if HAVE_CONFIG_H
  22. # include "config.h"
  23. #endif
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <limits.h>
  27. #include <errno.h>
  28. #include "qrencode.h"
  29. #include "mqrspec.h"
  30. #include "mmask.h"
  31. __STATIC void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level)
  32. {
  33. unsigned int format;
  34. unsigned char v;
  35. int i;
  36. format = MQRspec_getFormatInfo(mask, version, level);
  37. for(i=0; i<8; i++) {
  38. v = 0x84 | (format & 1);
  39. frame[width * (i + 1) + 8] = v;
  40. format = format >> 1;
  41. }
  42. for(i=0; i<7; i++) {
  43. v = 0x84 | (format & 1);
  44. frame[width * 8 + 7 - i] = v;
  45. format = format >> 1;
  46. }
  47. }
  48. #define MASKMAKER(__exp__) \
  49. int x, y;\
  50. \
  51. for(y=0; y<width; y++) {\
  52. for(x=0; x<width; x++) {\
  53. if(*s & 0x80) {\
  54. *d = *s;\
  55. } else {\
  56. *d = *s ^ ((__exp__) == 0);\
  57. }\
  58. s++; d++;\
  59. }\
  60. }
  61. static void Mask_mask0(int width, const unsigned char *s, unsigned char *d)
  62. {
  63. MASKMAKER(y&1)
  64. }
  65. static void Mask_mask1(int width, const unsigned char *s, unsigned char *d)
  66. {
  67. MASKMAKER(((y/2)+(x/3))&1)
  68. }
  69. static void Mask_mask2(int width, const unsigned char *s, unsigned char *d)
  70. {
  71. MASKMAKER((((x*y)&1)+(x*y)%3)&1)
  72. }
  73. static void Mask_mask3(int width, const unsigned char *s, unsigned char *d)
  74. {
  75. MASKMAKER((((x+y)&1)+((x*y)%3))&1)
  76. }
  77. #define maskNum (4)
  78. typedef void MaskMaker(int, const unsigned char *, unsigned char *);
  79. static MaskMaker *maskMakers[maskNum] = {
  80. Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3
  81. };
  82. #ifdef WITH_TESTS
  83. unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask)
  84. {
  85. unsigned char *masked;
  86. masked = (unsigned char *)malloc(width * width);
  87. if(masked == NULL) return NULL;
  88. maskMakers[mask](width, frame, masked);
  89. return masked;
  90. }
  91. #endif
  92. unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level)
  93. {
  94. unsigned char *masked;
  95. int width;
  96. if(mask < 0 || mask >= maskNum) {
  97. errno = EINVAL;
  98. return NULL;
  99. }
  100. width = MQRspec_getWidth(version);
  101. masked = (unsigned char *)malloc(width * width);
  102. if(masked == NULL) return NULL;
  103. maskMakers[mask](width, frame, masked);
  104. MMask_writeFormatInformation(version, width, masked, mask, level);
  105. return masked;
  106. }
  107. __STATIC int MMask_evaluateSymbol(int width, unsigned char *frame)
  108. {
  109. int x, y;
  110. unsigned char *p;
  111. int sum1 = 0, sum2 = 0;
  112. p = frame + width * (width - 1);
  113. for(x=1; x<width; x++) {
  114. sum1 += (p[x] & 1);
  115. }
  116. p = frame + width * 2 - 1;
  117. for(y=1; y<width; y++) {
  118. sum2 += (*p & 1);
  119. p += width;
  120. }
  121. return (sum1 <= sum2)?(sum1 * 16 + sum2):(sum2 * 16 + sum1);
  122. }
  123. unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level)
  124. {
  125. int i;
  126. unsigned char *mask, *bestMask;
  127. int maxScore = 0;
  128. int score;
  129. int width;
  130. width = MQRspec_getWidth(version);
  131. mask = (unsigned char *)malloc(width * width);
  132. if(mask == NULL) return NULL;
  133. bestMask = NULL;
  134. for(i=0; i<maskNum; i++) {
  135. score = 0;
  136. maskMakers[i](width, frame, mask);
  137. MMask_writeFormatInformation(version, width, mask, i, level);
  138. score = MMask_evaluateSymbol(width, mask);
  139. if(score > maxScore) {
  140. maxScore = score;
  141. free(bestMask);
  142. bestMask = mask;
  143. mask = (unsigned char *)malloc(width * width);
  144. if(mask == NULL) break;
  145. }
  146. }
  147. free(mask);
  148. return bestMask;
  149. }