QRUtil.js 8.0 KB

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