qrcode.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. var QR = (function () {
  2. // alignment pattern
  3. var adelta = [
  4. 0, 11, 15, 19, 23, 27, 31, // force 1 pat
  5. 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24,
  6. 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28
  7. ];
  8. // version block
  9. var vpat = [
  10. 0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d,
  11. 0x928, 0xb78, 0x45d, 0xa17, 0x532, 0x9a6, 0x683, 0x8c9,
  12. 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75,
  13. 0x250, 0x9d5, 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64,
  14. 0x541, 0xc69
  15. ];
  16. // final format bits with mask: level << 3 | mask
  17. var fmtword = [
  18. 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, //L
  19. 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, //M
  20. 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, //Q
  21. 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b //H
  22. ];
  23. // 4 per version: number of blocks 1,2; data width; ecc width
  24. var eccblocks = [
  25. 1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17,
  26. 1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28,
  27. 1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22,
  28. 1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16,
  29. 1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22,
  30. 2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28,
  31. 2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26,
  32. 2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26,
  33. 2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24,
  34. 2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28,
  35. 4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24,
  36. 2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28,
  37. 4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22,
  38. 3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24,
  39. 5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24,
  40. 5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30,
  41. 1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28,
  42. 5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28,
  43. 3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26,
  44. 3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28,
  45. 4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30,
  46. 2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24,
  47. 4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30,
  48. 6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30,
  49. 8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30,
  50. 10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30,
  51. 8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30,
  52. 3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30,
  53. 7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30,
  54. 5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30,
  55. 13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30,
  56. 17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30,
  57. 17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30,
  58. 13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30,
  59. 12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30,
  60. 6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30,
  61. 17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30,
  62. 4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30,
  63. 20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30,
  64. 19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30
  65. ];
  66. // Galois field log table
  67. var glog = [
  68. 0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
  69. 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
  70. 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
  71. 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
  72. 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
  73. 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
  74. 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
  75. 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
  76. 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
  77. 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
  78. 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
  79. 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
  80. 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
  81. 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
  82. 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
  83. 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf
  84. ];
  85. // Galios field exponent table
  86. var gexp = [
  87. 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
  88. 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
  89. 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
  90. 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
  91. 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
  92. 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
  93. 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
  94. 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
  95. 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
  96. 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
  97. 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
  98. 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
  99. 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
  100. 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
  101. 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
  102. 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00
  103. ];
  104. // Working buffers:
  105. // data input and ecc append, image working buffer, fixed part of image, run lengths for badness
  106. var strinbuf=[], eccbuf=[], qrframe=[], framask=[], rlens=[];
  107. // Control values - width is based on version, last 4 are from table.
  108. var version, width, neccblk1, neccblk2, datablkw, eccblkwid;
  109. var ecclevel = 2;
  110. // set bit to indicate cell in qrframe is immutable. symmetric around diagonal
  111. function setmask(x, y)
  112. {
  113. var bt;
  114. if (x > y) {
  115. bt = x;
  116. x = y;
  117. y = bt;
  118. }
  119. // y*y = 1+3+5...
  120. bt = y;
  121. bt *= y;
  122. bt += y;
  123. bt >>= 1;
  124. bt += x;
  125. framask[bt] = 1;
  126. }
  127. // enter alignment pattern - black to qrframe, white to mask (later black frame merged to mask)
  128. function putalign(x, y)
  129. {
  130. var j;
  131. qrframe[x + width * y] = 1;
  132. for (j = -2; j < 2; j++) {
  133. qrframe[(x + j) + width * (y - 2)] = 1;
  134. qrframe[(x - 2) + width * (y + j + 1)] = 1;
  135. qrframe[(x + 2) + width * (y + j)] = 1;
  136. qrframe[(x + j + 1) + width * (y + 2)] = 1;
  137. }
  138. for (j = 0; j < 2; j++) {
  139. setmask(x - 1, y + j);
  140. setmask(x + 1, y - j);
  141. setmask(x - j, y - 1);
  142. setmask(x + j, y + 1);
  143. }
  144. }
  145. //========================================================================
  146. // Reed Solomon error correction
  147. // exponentiation mod N
  148. function modnn(x)
  149. {
  150. while (x >= 255) {
  151. x -= 255;
  152. x = (x >> 8) + (x & 255);
  153. }
  154. return x;
  155. }
  156. var genpoly = [];
  157. // Calculate and append ECC data to data block. Block is in strinbuf, indexes to buffers given.
  158. function appendrs(data, dlen, ecbuf, eclen)
  159. {
  160. var i, j, fb;
  161. for (i = 0; i < eclen; i++)
  162. strinbuf[ecbuf + i] = 0;
  163. for (i = 0; i < dlen; i++) {
  164. fb = glog[strinbuf[data + i] ^ strinbuf[ecbuf]];
  165. if (fb != 255) /* fb term is non-zero */
  166. for (j = 1; j < eclen; j++)
  167. strinbuf[ecbuf + j - 1] = strinbuf[ecbuf + j] ^ gexp[modnn(fb + genpoly[eclen - j])];
  168. else
  169. for( j = ecbuf ; j < ecbuf + eclen; j++ )
  170. strinbuf[j] = strinbuf[j + 1];
  171. strinbuf[ ecbuf + eclen - 1] = fb == 255 ? 0 : gexp[modnn(fb + genpoly[0])];
  172. }
  173. }
  174. //========================================================================
  175. // Frame data insert following the path rules
  176. // check mask - since symmetrical use half.
  177. function ismasked(x, y)
  178. {
  179. var bt;
  180. if (x > y) {
  181. bt = x;
  182. x = y;
  183. y = bt;
  184. }
  185. bt = y;
  186. bt += y * y;
  187. bt >>= 1;
  188. bt += x;
  189. return framask[bt];
  190. }
  191. //========================================================================
  192. // Apply the selected mask out of the 8.
  193. function applymask(m)
  194. {
  195. var x, y, r3x, r3y;
  196. switch (m) {
  197. case 0:
  198. for (y = 0; y < width; y++)
  199. for (x = 0; x < width; x++)
  200. if (!((x + y) & 1) && !ismasked(x, y))
  201. qrframe[x + y * width] ^= 1;
  202. break;
  203. case 1:
  204. for (y = 0; y < width; y++)
  205. for (x = 0; x < width; x++)
  206. if (!(y & 1) && !ismasked(x, y))
  207. qrframe[x + y * width] ^= 1;
  208. break;
  209. case 2:
  210. for (y = 0; y < width; y++)
  211. for (r3x = 0, x = 0; x < width; x++, r3x++) {
  212. if (r3x == 3)
  213. r3x = 0;
  214. if (!r3x && !ismasked(x, y))
  215. qrframe[x + y * width] ^= 1;
  216. }
  217. break;
  218. case 3:
  219. for (r3y = 0, y = 0; y < width; y++, r3y++) {
  220. if (r3y == 3)
  221. r3y = 0;
  222. for (r3x = r3y, x = 0; x < width; x++, r3x++) {
  223. if (r3x == 3)
  224. r3x = 0;
  225. if (!r3x && !ismasked(x, y))
  226. qrframe[x + y * width] ^= 1;
  227. }
  228. }
  229. break;
  230. case 4:
  231. for (y = 0; y < width; y++)
  232. for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++, r3x++) {
  233. if (r3x == 3) {
  234. r3x = 0;
  235. r3y = !r3y;
  236. }
  237. if (!r3y && !ismasked(x, y))
  238. qrframe[x + y * width] ^= 1;
  239. }
  240. break;
  241. case 5:
  242. for (r3y = 0, y = 0; y < width; y++, r3y++) {
  243. if (r3y == 3)
  244. r3y = 0;
  245. for (r3x = 0, x = 0; x < width; x++, r3x++) {
  246. if (r3x == 3)
  247. r3x = 0;
  248. if (!((x & y & 1) + !(!r3x | !r3y)) && !ismasked(x, y))
  249. qrframe[x + y * width] ^= 1;
  250. }
  251. }
  252. break;
  253. case 6:
  254. for (r3y = 0, y = 0; y < width; y++, r3y++) {
  255. if (r3y == 3)
  256. r3y = 0;
  257. for (r3x = 0, x = 0; x < width; x++, r3x++) {
  258. if (r3x == 3)
  259. r3x = 0;
  260. if (!(((x & y & 1) + (r3x && (r3x == r3y))) & 1) && !ismasked(x, y))
  261. qrframe[x + y * width] ^= 1;
  262. }
  263. }
  264. break;
  265. case 7:
  266. for (r3y = 0, y = 0; y < width; y++, r3y++) {
  267. if (r3y == 3)
  268. r3y = 0;
  269. for (r3x = 0, x = 0; x < width; x++, r3x++) {
  270. if (r3x == 3)
  271. r3x = 0;
  272. if (!(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) && !ismasked(x, y))
  273. qrframe[x + y * width] ^= 1;
  274. }
  275. }
  276. break;
  277. }
  278. return;
  279. }
  280. // Badness coefficients.
  281. var N1 = 3, N2 = 3, N3 = 40, N4 = 10;
  282. // Using the table of the length of each run, calculate the amount of bad image
  283. // - long runs or those that look like finders; called twice, once each for X and Y
  284. function badruns(length)
  285. {
  286. var i;
  287. var runsbad = 0;
  288. for (i = 0; i <= length; i++)
  289. if (rlens[i] >= 5)
  290. runsbad += N1 + rlens[i] - 5;
  291. // BwBBBwB as in finder
  292. for (i = 3; i < length - 1; i += 2)
  293. if (rlens[i - 2] == rlens[i + 2]
  294. && rlens[i + 2] == rlens[i - 1]
  295. && rlens[i - 1] == rlens[i + 1]
  296. && rlens[i - 1] * 3 == rlens[i]
  297. // white around the black pattern? Not part of spec
  298. && (rlens[i - 3] == 0 // beginning
  299. || i + 3 > length // end
  300. || rlens[i - 3] * 3 >= rlens[i] * 4 || rlens[i + 3] * 3 >= rlens[i] * 4)
  301. )
  302. runsbad += N3;
  303. return runsbad;
  304. }
  305. // Calculate how bad the masked image is - blocks, imbalance, runs, or finders.
  306. function badcheck()
  307. {
  308. var x, y, h, b, b1;
  309. var thisbad = 0;
  310. var bw = 0;
  311. // blocks of same color.
  312. for (y = 0; y < width - 1; y++)
  313. for (x = 0; x < width - 1; x++)
  314. if ((qrframe[x + width * y] && qrframe[(x + 1) + width * y]
  315. && qrframe[x + width * (y + 1)] && qrframe[(x + 1) + width * (y + 1)]) // all black
  316. || !(qrframe[x + width * y] || qrframe[(x + 1) + width * y]
  317. || qrframe[x + width * (y + 1)] || qrframe[(x + 1) + width * (y + 1)])) // all white
  318. thisbad += N2;
  319. // X runs
  320. for (y = 0; y < width; y++) {
  321. rlens[0] = 0;
  322. for (h = b = x = 0; x < width; x++) {
  323. if ((b1 = qrframe[x + width * y]) == b)
  324. rlens[h]++;
  325. else
  326. rlens[++h] = 1;
  327. b = b1;
  328. bw += b ? 1 : -1;
  329. }
  330. thisbad += badruns(h);
  331. }
  332. // black/white imbalance
  333. if (bw < 0)
  334. bw = -bw;
  335. var big = bw;
  336. var count = 0;
  337. big += big << 2;
  338. big <<= 1;
  339. while (big > width * width)
  340. big -= width * width, count++;
  341. thisbad += count * N4;
  342. // Y runs
  343. for (x = 0; x < width; x++) {
  344. rlens[0] = 0;
  345. for (h = b = y = 0; y < width; y++) {
  346. if ((b1 = qrframe[x + width * y]) == b)
  347. rlens[h]++;
  348. else
  349. rlens[++h] = 1;
  350. b = b1;
  351. }
  352. thisbad += badruns(h);
  353. }
  354. return thisbad;
  355. }
  356. function genframe(instring)
  357. {
  358. var x, y, k, t, v, i, j, m;
  359. // find the smallest version that fits the string
  360. t = instring.length;
  361. version = 0;
  362. do {
  363. version++;
  364. k = (ecclevel - 1) * 4 + (version - 1) * 16;
  365. neccblk1 = eccblocks[k++];
  366. neccblk2 = eccblocks[k++];
  367. datablkw = eccblocks[k++];
  368. eccblkwid = eccblocks[k];
  369. k = datablkw * (neccblk1 + neccblk2) + neccblk2 - 3 + (version <= 9);
  370. if (t <= k)
  371. break;
  372. } while (version < 40);
  373. // FIXME - insure that it fits insted of being truncated
  374. width = 17 + 4 * version;
  375. // allocate, clear and setup data structures
  376. v = datablkw + (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
  377. for( t = 0; t < v; t++ )
  378. eccbuf[t] = 0;
  379. strinbuf = instring.slice(0);
  380. for( t = 0; t < width * width; t++ )
  381. qrframe[t] = 0;
  382. for( t = 0 ; t < (width * (width + 1) + 1) / 2; t++)
  383. framask[t] = 0;
  384. // insert finders - black to frame, white to mask
  385. for (t = 0; t < 3; t++) {
  386. k = 0;
  387. y = 0;
  388. if (t == 1)
  389. k = (width - 7);
  390. if (t == 2)
  391. y = (width - 7);
  392. qrframe[(y + 3) + width * (k + 3)] = 1;
  393. for (x = 0; x < 6; x++) {
  394. qrframe[(y + x) + width * k] = 1;
  395. qrframe[y + width * (k + x + 1)] = 1;
  396. qrframe[(y + 6) + width * (k + x)] = 1;
  397. qrframe[(y + x + 1) + width * (k + 6)] = 1;
  398. }
  399. for (x = 1; x < 5; x++) {
  400. setmask(y + x, k + 1);
  401. setmask(y + 1, k + x + 1);
  402. setmask(y + 5, k + x);
  403. setmask(y + x + 1, k + 5);
  404. }
  405. for (x = 2; x < 4; x++) {
  406. qrframe[(y + x) + width * (k + 2)] = 1;
  407. qrframe[(y + 2) + width * (k + x + 1)] = 1;
  408. qrframe[(y + 4) + width * (k + x)] = 1;
  409. qrframe[(y + x + 1) + width * (k + 4)] = 1;
  410. }
  411. }
  412. // alignment blocks
  413. if (version > 1) {
  414. t = adelta[version];
  415. y = width - 7;
  416. for (;;) {
  417. x = width - 7;
  418. while (x > t - 3) {
  419. putalign(x, y);
  420. if (x < t)
  421. break;
  422. x -= t;
  423. }
  424. if (y <= t + 9)
  425. break;
  426. y -= t;
  427. putalign(6, y);
  428. putalign(y, 6);
  429. }
  430. }
  431. // single black
  432. qrframe[8 + width * (width - 8)] = 1;
  433. // timing gap - mask only
  434. for (y = 0; y < 7; y++) {
  435. setmask(7, y);
  436. setmask(width - 8, y);
  437. setmask(7, y + width - 7);
  438. }
  439. for (x = 0; x < 8; x++) {
  440. setmask(x, 7);
  441. setmask(x + width - 8, 7);
  442. setmask(x, width - 8);
  443. }
  444. // reserve mask-format area
  445. for (x = 0; x < 9; x++)
  446. setmask(x, 8);
  447. for (x = 0; x < 8; x++) {
  448. setmask(x + width - 8, 8);
  449. setmask(8, x);
  450. }
  451. for (y = 0; y < 7; y++)
  452. setmask(8, y + width - 7);
  453. // timing row/col
  454. for (x = 0; x < width - 14; x++)
  455. if (x & 1) {
  456. setmask(8 + x, 6);
  457. setmask(6, 8 + x);
  458. }
  459. else {
  460. qrframe[(8 + x) + width * 6] = 1;
  461. qrframe[6 + width * (8 + x)] = 1;
  462. }
  463. // version block
  464. if (version > 6) {
  465. t = vpat[version - 7];
  466. k = 17;
  467. for (x = 0; x < 6; x++)
  468. for (y = 0; y < 3; y++, k--)
  469. if (1 & (k > 11 ? version >> (k - 12) : t >> k)) {
  470. qrframe[(5 - x) + width * (2 - y + width - 11)] = 1;
  471. qrframe[(2 - y + width - 11) + width * (5 - x)] = 1;
  472. }
  473. else {
  474. setmask(5 - x, 2 - y + width - 11);
  475. setmask(2 - y + width - 11, 5 - x);
  476. }
  477. }
  478. // sync mask bits - only set above for white spaces, so add in black bits
  479. for (y = 0; y < width; y++)
  480. for (x = 0; x <= y; x++)
  481. if (qrframe[x + width * y])
  482. setmask(x, y);
  483. // convert string to bitstream
  484. // 8 bit data to QR-coded 8 bit data (numeric or alphanum, or kanji not supported)
  485. v = strinbuf.length;
  486. // string to array
  487. for( i = 0 ; i < v; i++ )
  488. eccbuf[i] = strinbuf.charCodeAt(i);
  489. strinbuf = eccbuf.slice(0);
  490. // calculate max string length
  491. x = datablkw * (neccblk1 + neccblk2) + neccblk2;
  492. if (v >= x - 2) {
  493. v = x - 2;
  494. if (version > 9)
  495. v--;
  496. }
  497. // shift and repack to insert length prefix
  498. i = v;
  499. if (version > 9) {
  500. strinbuf[i + 2] = 0;
  501. strinbuf[i + 3] = 0;
  502. while (i--) {
  503. t = strinbuf[i];
  504. strinbuf[i + 3] |= 255 & (t << 4);
  505. strinbuf[i + 2] = t >> 4;
  506. }
  507. strinbuf[2] |= 255 & (v << 4);
  508. strinbuf[1] = v >> 4;
  509. strinbuf[0] = 0x40 | (v >> 12);
  510. }
  511. else {
  512. strinbuf[i + 1] = 0;
  513. strinbuf[i + 2] = 0;
  514. while (i--) {
  515. t = strinbuf[i];
  516. strinbuf[i + 2] |= 255 & (t << 4);
  517. strinbuf[i + 1] = t >> 4;
  518. }
  519. strinbuf[1] |= 255 & (v << 4);
  520. strinbuf[0] = 0x40 | (v >> 4);
  521. }
  522. // fill to end with pad pattern
  523. i = v + 3 - (version < 10);
  524. while (i < x) {
  525. strinbuf[i++] = 0xec;
  526. // buffer has room if (i == x) break;
  527. strinbuf[i++] = 0x11;
  528. }
  529. // calculate and append ECC
  530. // calculate generator polynomial
  531. genpoly[0] = 1;
  532. for (i = 0; i < eccblkwid; i++) {
  533. genpoly[i + 1] = 1;
  534. for (j = i; j > 0; j--)
  535. genpoly[j] = genpoly[j]
  536. ? genpoly[j - 1] ^ gexp[modnn(glog[genpoly[j]] + i)] : genpoly[j - 1];
  537. genpoly[0] = gexp[modnn(glog[genpoly[0]] + i)];
  538. }
  539. for (i = 0; i <= eccblkwid; i++)
  540. genpoly[i] = glog[genpoly[i]]; // use logs for genpoly[] to save calc step
  541. // append ecc to data buffer
  542. k = x;
  543. y = 0;
  544. for (i = 0; i < neccblk1; i++) {
  545. appendrs(y, datablkw, k, eccblkwid);
  546. y += datablkw;
  547. k += eccblkwid;
  548. }
  549. for (i = 0; i < neccblk2; i++) {
  550. appendrs(y, datablkw + 1, k, eccblkwid);
  551. y += datablkw + 1;
  552. k += eccblkwid;
  553. }
  554. // interleave blocks
  555. y = 0;
  556. for (i = 0; i < datablkw; i++) {
  557. for (j = 0; j < neccblk1; j++)
  558. eccbuf[y++] = strinbuf[i + j * datablkw];
  559. for (j = 0; j < neccblk2; j++)
  560. eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
  561. }
  562. for (j = 0; j < neccblk2; j++)
  563. eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))];
  564. for (i = 0; i < eccblkwid; i++)
  565. for (j = 0; j < neccblk1 + neccblk2; j++)
  566. eccbuf[y++] = strinbuf[x + i + j * eccblkwid];
  567. strinbuf = eccbuf;
  568. // pack bits into frame avoiding masked area.
  569. x = y = width - 1;
  570. k = v = 1; // up, minus
  571. /* inteleaved data and ecc codes */
  572. m = (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2;
  573. for (i = 0; i < m; i++) {
  574. t = strinbuf[i];
  575. for (j = 0; j < 8; j++, t <<= 1) {
  576. if (0x80 & t)
  577. qrframe[x + width * y] = 1;
  578. do { // find next fill position
  579. if (v)
  580. x--;
  581. else {
  582. x++;
  583. if (k) {
  584. if (y != 0)
  585. y--;
  586. else {
  587. x -= 2;
  588. k = !k;
  589. if (x == 6) {
  590. x--;
  591. y = 9;
  592. }
  593. }
  594. }
  595. else {
  596. if (y != width - 1)
  597. y++;
  598. else {
  599. x -= 2;
  600. k = !k;
  601. if (x == 6) {
  602. x--;
  603. y -= 8;
  604. }
  605. }
  606. }
  607. }
  608. v = !v;
  609. } while (ismasked(x, y));
  610. }
  611. }
  612. // save pre-mask copy of frame
  613. strinbuf = qrframe.slice(0);
  614. t = 0; // best
  615. y = 30000; // demerit
  616. // for instead of while since in original arduino code
  617. // if an early mask was "good enough" it wouldn't try for a better one
  618. // since they get more complex and take longer.
  619. for (k = 0; k < 8; k++) {
  620. applymask(k); // returns black-white imbalance
  621. x = badcheck();
  622. if (x < y) { // current mask better than previous best?
  623. y = x;
  624. t = k;
  625. }
  626. if (t == 7)
  627. break; // don't increment i to a void redoing mask
  628. qrframe = strinbuf.slice(0); // reset for next pass
  629. }
  630. if (t != k) // redo best mask - none good enough, last wasn't t
  631. applymask(t);
  632. // add in final mask/ecclevel bytes
  633. y = fmtword[t + ((ecclevel - 1) << 3)];
  634. // low byte
  635. for (k = 0; k < 8; k++, y >>= 1)
  636. if (y & 1) {
  637. qrframe[(width - 1 - k) + width * 8] = 1;
  638. if (k < 6)
  639. qrframe[8 + width * k] = 1;
  640. else
  641. qrframe[8 + width * (k + 1)] = 1;
  642. }
  643. // high byte
  644. for (k = 0; k < 7; k++, y >>= 1)
  645. if (y & 1) {
  646. qrframe[8 + width * (width - 7 + k)] = 1;
  647. if (k)
  648. qrframe[(6 - k) + width * 8] = 1;
  649. else
  650. qrframe[7 + width * 8] = 1;
  651. }
  652. // return image
  653. return qrframe;
  654. }
  655. var _canvas = null,
  656. _size = null;
  657. var api = {
  658. get ecclevel () {
  659. return ecclevel;
  660. },
  661. set ecclevel (val) {
  662. ecclevel = val;
  663. },
  664. get size () {
  665. return _size;
  666. },
  667. set size (val) {
  668. _size = val
  669. },
  670. get canvas () {
  671. return _canvas;
  672. },
  673. set canvas (el) {
  674. _canvas = el;
  675. },
  676. getFrame: function (string) {
  677. return genframe(string);
  678. },
  679. draw: function (string, canvas, size, ecc) {
  680. ecclevel = ecc || ecclevel;
  681. canvas = canvas || _canvas;
  682. if (!canvas) {
  683. console.warn('No canvas provided to draw QR code in!')
  684. return;
  685. }
  686. size = size || _size || Math.min(canvas.width, canvas.height);
  687. var frame = genframe(string),
  688. ctx = canvas.ctx,
  689. px = Math.round(size / (width + 8));
  690. var roundedSize = px * (width + 8),
  691. offset = Math.floor((size - roundedSize) / 2);
  692. size = roundedSize;
  693. ctx.clearRect(0, 0, canvas.width, canvas.height);
  694. ctx.setFillStyle('#000000');
  695. for (var i = 0; i < width; i++) {
  696. for (var j = 0; j < width; j++) {
  697. if (frame[j * width + i]) {
  698. ctx.fillRect(px * (4 + i) + offset, px * (4 + j) + offset, px, px);
  699. }
  700. }
  701. }
  702. ctx.draw();
  703. }
  704. }
  705. module.exports = {
  706. api: api
  707. }
  708. })()