util.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. var Mode = require('./mode');
  2. var Polynomial = require('./Polynomial');
  3. var math = require('./math');
  4. var QRMaskPattern = {
  5. PATTERN000 : 0,
  6. PATTERN001 : 1,
  7. PATTERN010 : 2,
  8. PATTERN011 : 3,
  9. PATTERN100 : 4,
  10. PATTERN101 : 5,
  11. PATTERN110 : 6,
  12. PATTERN111 : 7
  13. };
  14. var QRUtil = {
  15. PATTERN_POSITION_TABLE : [
  16. [],
  17. [6, 18],
  18. [6, 22],
  19. [6, 26],
  20. [6, 30],
  21. [6, 34],
  22. [6, 22, 38],
  23. [6, 24, 42],
  24. [6, 26, 46],
  25. [6, 28, 50],
  26. [6, 30, 54],
  27. [6, 32, 58],
  28. [6, 34, 62],
  29. [6, 26, 46, 66],
  30. [6, 26, 48, 70],
  31. [6, 26, 50, 74],
  32. [6, 30, 54, 78],
  33. [6, 30, 56, 82],
  34. [6, 30, 58, 86],
  35. [6, 34, 62, 90],
  36. [6, 28, 50, 72, 94],
  37. [6, 26, 50, 74, 98],
  38. [6, 30, 54, 78, 102],
  39. [6, 28, 54, 80, 106],
  40. [6, 32, 58, 84, 110],
  41. [6, 30, 58, 86, 114],
  42. [6, 34, 62, 90, 118],
  43. [6, 26, 50, 74, 98, 122],
  44. [6, 30, 54, 78, 102, 126],
  45. [6, 26, 52, 78, 104, 130],
  46. [6, 30, 56, 82, 108, 134],
  47. [6, 34, 60, 86, 112, 138],
  48. [6, 30, 58, 86, 114, 142],
  49. [6, 34, 62, 90, 118, 146],
  50. [6, 30, 54, 78, 102, 126, 150],
  51. [6, 24, 50, 76, 102, 128, 154],
  52. [6, 28, 54, 80, 106, 132, 158],
  53. [6, 32, 58, 84, 110, 136, 162],
  54. [6, 26, 54, 82, 110, 138, 166],
  55. [6, 30, 58, 86, 114, 142, 170]
  56. ],
  57. G15 : (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
  58. G18 : (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
  59. G15_MASK : (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
  60. getBCHTypeInfo : function(data) {
  61. var d = data << 10;
  62. while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
  63. d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) ) );
  64. }
  65. return ( (data << 10) | d) ^ QRUtil.G15_MASK;
  66. },
  67. getBCHTypeNumber : function(data) {
  68. var d = data << 12;
  69. while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
  70. d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) ) );
  71. }
  72. return (data << 12) | d;
  73. },
  74. getBCHDigit : function(data) {
  75. var digit = 0;
  76. while (data != 0) {
  77. digit++;
  78. data >>>= 1;
  79. }
  80. return digit;
  81. },
  82. getPatternPosition : function(typeNumber) {
  83. return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
  84. },
  85. getMask : function(maskPattern, i, j) {
  86. switch (maskPattern) {
  87. case QRMaskPattern.PATTERN000 : return (i + j) % 2 == 0;
  88. case QRMaskPattern.PATTERN001 : return i % 2 == 0;
  89. case QRMaskPattern.PATTERN010 : return j % 3 == 0;
  90. case QRMaskPattern.PATTERN011 : return (i + j) % 3 == 0;
  91. case QRMaskPattern.PATTERN100 : return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0;
  92. case QRMaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0;
  93. case QRMaskPattern.PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0;
  94. case QRMaskPattern.PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0;
  95. default :
  96. throw new Error("bad maskPattern:" + maskPattern);
  97. }
  98. },
  99. getErrorCorrectPolynomial : function(errorCorrectLength) {
  100. var a = new Polynomial([1], 0);
  101. for (var i = 0; i < errorCorrectLength; i++) {
  102. a = a.multiply(new Polynomial([1, math.gexp(i)], 0) );
  103. }
  104. return a;
  105. },
  106. getLengthInBits : function(mode, type) {
  107. if (1 <= type && type < 10) {
  108. // 1 - 9
  109. switch(mode) {
  110. case Mode.MODE_NUMBER : return 10;
  111. case Mode.MODE_ALPHA_NUM : return 9;
  112. case Mode.MODE_8BIT_BYTE : return 8;
  113. case Mode.MODE_KANJI : return 8;
  114. default :
  115. throw new Error("mode:" + mode);
  116. }
  117. } else if (type < 27) {
  118. // 10 - 26
  119. switch(mode) {
  120. case Mode.MODE_NUMBER : return 12;
  121. case Mode.MODE_ALPHA_NUM : return 11;
  122. case Mode.MODE_8BIT_BYTE : return 16;
  123. case Mode.MODE_KANJI : return 10;
  124. default :
  125. throw new Error("mode:" + mode);
  126. }
  127. } else if (type < 41) {
  128. // 27 - 40
  129. switch(mode) {
  130. case Mode.MODE_NUMBER : return 14;
  131. case Mode.MODE_ALPHA_NUM : return 13;
  132. case Mode.MODE_8BIT_BYTE : return 16;
  133. case Mode.MODE_KANJI : return 12;
  134. default :
  135. throw new Error("mode:" + mode);
  136. }
  137. } else {
  138. throw new Error("type:" + type);
  139. }
  140. },
  141. getLostPoint : function(qrCode) {
  142. var moduleCount = qrCode.getModuleCount();
  143. var lostPoint = 0;
  144. // LEVEL1
  145. for (var row = 0; row < moduleCount; row++) {
  146. for (var col = 0; col < moduleCount; col++) {
  147. var sameCount = 0;
  148. var dark = qrCode.isDark(row, col);
  149. for (var r = -1; r <= 1; r++) {
  150. if (row + r < 0 || moduleCount <= row + r) {
  151. continue;
  152. }
  153. for (var c = -1; c <= 1; c++) {
  154. if (col + c < 0 || moduleCount <= col + c) {
  155. continue;
  156. }
  157. if (r == 0 && c == 0) {
  158. continue;
  159. }
  160. if (dark == qrCode.isDark(row + r, col + c) ) {
  161. sameCount++;
  162. }
  163. }
  164. }
  165. if (sameCount > 5) {
  166. lostPoint += (3 + sameCount - 5);
  167. }
  168. }
  169. }
  170. // LEVEL2
  171. for (var row = 0; row < moduleCount - 1; row++) {
  172. for (var col = 0; col < moduleCount - 1; col++) {
  173. var count = 0;
  174. if (qrCode.isDark(row, col ) ) count++;
  175. if (qrCode.isDark(row + 1, col ) ) count++;
  176. if (qrCode.isDark(row, col + 1) ) count++;
  177. if (qrCode.isDark(row + 1, col + 1) ) count++;
  178. if (count == 0 || count == 4) {
  179. lostPoint += 3;
  180. }
  181. }
  182. }
  183. // LEVEL3
  184. for (var row = 0; row < moduleCount; row++) {
  185. for (var col = 0; col < moduleCount - 6; col++) {
  186. if (qrCode.isDark(row, col)
  187. && !qrCode.isDark(row, col + 1)
  188. && qrCode.isDark(row, col + 2)
  189. && qrCode.isDark(row, col + 3)
  190. && qrCode.isDark(row, col + 4)
  191. && !qrCode.isDark(row, col + 5)
  192. && qrCode.isDark(row, col + 6) ) {
  193. lostPoint += 40;
  194. }
  195. }
  196. }
  197. for (var col = 0; col < moduleCount; col++) {
  198. for (var row = 0; row < moduleCount - 6; row++) {
  199. if (qrCode.isDark(row, col)
  200. && !qrCode.isDark(row + 1, col)
  201. && qrCode.isDark(row + 2, col)
  202. && qrCode.isDark(row + 3, col)
  203. && qrCode.isDark(row + 4, col)
  204. && !qrCode.isDark(row + 5, col)
  205. && qrCode.isDark(row + 6, col) ) {
  206. lostPoint += 40;
  207. }
  208. }
  209. }
  210. // LEVEL4
  211. var darkCount = 0;
  212. for (var col = 0; col < moduleCount; col++) {
  213. for (var row = 0; row < moduleCount; row++) {
  214. if (qrCode.isDark(row, col) ) {
  215. darkCount++;
  216. }
  217. }
  218. }
  219. var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
  220. lostPoint += ratio * 10;
  221. return lostPoint;
  222. }
  223. };
  224. module.exports = QRUtil;