frame.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. import ErrorCorrection from './correction.js'
  2. import Alignment from './alignment.js'
  3. import Galois from './galois.js'
  4. import Version from './version.js'
  5. class Frame {
  6. _addAlignment(x, y) {
  7. let i;
  8. let buffer = this.buffer;
  9. let width = this.width;
  10. buffer[x + (width * y)] = 1;
  11. for (i = -2; i < 2; i++) {
  12. buffer[x + i + (width * (y - 2))] = 1;
  13. buffer[x - 2 + (width * (y + i + 1))] = 1;
  14. buffer[x + 2 + (width * (y + i))] = 1;
  15. buffer[x + i + 1 + (width * (y + 2))] = 1;
  16. }
  17. for (i = 0; i < 2; i++) {
  18. this._setMask(x - 1, y + i);
  19. this._setMask(x + 1, y - i);
  20. this._setMask(x - i, y - 1);
  21. this._setMask(x + i, y + 1);
  22. }
  23. }
  24. _appendData(data, dataLength, ecc, eccLength) {
  25. let bit, i, j;
  26. let polynomial = this._polynomial;
  27. let stringBuffer = this._stringBuffer;
  28. for (i = 0; i < eccLength; i++) {
  29. stringBuffer[ecc + i] = 0;
  30. }
  31. for (i = 0; i < dataLength; i++) {
  32. bit = Galois.LOG[stringBuffer[data + i] ^ stringBuffer[ecc]];
  33. if (bit !== 255) {
  34. for (j = 1; j < eccLength; j++) {
  35. stringBuffer[ecc + j - 1] = stringBuffer[ecc + j] ^
  36. Galois.EXPONENT[this._modN(bit + polynomial[eccLength - j])];
  37. }
  38. } else {
  39. for (j = ecc; j < ecc + eccLength; j++) {
  40. stringBuffer[j] = stringBuffer[j + 1];
  41. }
  42. }
  43. stringBuffer[ecc + eccLength - 1] = bit === 255 ? 0 : Galois.EXPONENT[this._modN(bit + polynomial[0])];
  44. }
  45. }
  46. _appendEccToData() {
  47. let i;
  48. let data = 0;
  49. let dataBlock = this._dataBlock;
  50. let ecc = this._calculateMaxLength();
  51. let eccBlock = this._eccBlock;
  52. for (i = 0; i < this._neccBlock1; i++) {
  53. this._appendData(data, dataBlock, ecc, eccBlock);
  54. data += dataBlock;
  55. ecc += eccBlock;
  56. }
  57. for (i = 0; i < this._neccBlock2; i++) {
  58. this._appendData(data, dataBlock + 1, ecc, eccBlock);
  59. data += dataBlock + 1;
  60. ecc += eccBlock;
  61. }
  62. }
  63. _applyMask(mask) {
  64. let r3x, r3y, x, y;
  65. let buffer = this.buffer;
  66. let width = this.width;
  67. switch (mask) {
  68. case 0:
  69. for (y = 0; y < width; y++) {
  70. for (x = 0; x < width; x++) {
  71. if (!((x + y) & 1) && !this._isMasked(x, y)) {
  72. buffer[x + (y * width)] ^= 1;
  73. }
  74. }
  75. }
  76. break;
  77. case 1:
  78. for (y = 0; y < width; y++) {
  79. for (x = 0; x < width; x++) {
  80. if (!(y & 1) && !this._isMasked(x, y)) {
  81. buffer[x + (y * width)] ^= 1;
  82. }
  83. }
  84. }
  85. break;
  86. case 2:
  87. for (y = 0; y < width; y++) {
  88. for (r3x = 0, x = 0; x < width; x++, r3x++) {
  89. if (r3x === 3) {
  90. r3x = 0;
  91. }
  92. if (!r3x && !this._isMasked(x, y)) {
  93. buffer[x + (y * width)] ^= 1;
  94. }
  95. }
  96. }
  97. break;
  98. case 3:
  99. for (r3y = 0, y = 0; y < width; y++, r3y++) {
  100. if (r3y === 3) {
  101. r3y = 0;
  102. }
  103. for (r3x = r3y, x = 0; x < width; x++, r3x++) {
  104. if (r3x === 3) {
  105. r3x = 0;
  106. }
  107. if (!r3x && !this._isMasked(x, y)) {
  108. buffer[x + (y * width)] ^= 1;
  109. }
  110. }
  111. }
  112. break;
  113. case 4:
  114. for (y = 0; y < width; y++) {
  115. for (r3x = 0, r3y = (y >> 1) & 1, x = 0; x < width; x++, r3x++) {
  116. if (r3x === 3) {
  117. r3x = 0;
  118. r3y = !r3y;
  119. }
  120. if (!r3y && !this._isMasked(x, y)) {
  121. buffer[x + (y * width)] ^= 1;
  122. }
  123. }
  124. }
  125. break;
  126. case 5:
  127. for (r3y = 0, y = 0; y < width; y++, r3y++) {
  128. if (r3y === 3) {
  129. r3y = 0;
  130. }
  131. for (r3x = 0, x = 0; x < width; x++, r3x++) {
  132. if (r3x === 3) {
  133. r3x = 0;
  134. }
  135. if (!((x & y & 1) + !(!r3x | !r3y)) && !this._isMasked(x, y)) {
  136. buffer[x + (y * width)] ^= 1;
  137. }
  138. }
  139. }
  140. break;
  141. case 6:
  142. for (r3y = 0, y = 0; y < width; y++, r3y++) {
  143. if (r3y === 3) {
  144. r3y = 0;
  145. }
  146. for (r3x = 0, x = 0; x < width; x++, r3x++) {
  147. if (r3x === 3) {
  148. r3x = 0;
  149. }
  150. if (!((x & y & 1) + (r3x && r3x === r3y) & 1) && !this._isMasked(x, y)) {
  151. buffer[x + (y * width)] ^= 1;
  152. }
  153. }
  154. }
  155. break;
  156. case 7:
  157. for (r3y = 0, y = 0; y < width; y++, r3y++) {
  158. if (r3y === 3) {
  159. r3y = 0;
  160. }
  161. for (r3x = 0, x = 0; x < width; x++, r3x++) {
  162. if (r3x === 3) {
  163. r3x = 0;
  164. }
  165. if (!((r3x && r3x === r3y) + (x + y & 1) & 1) && !this._isMasked(x, y)) {
  166. buffer[x + (y * width)] ^= 1;
  167. }
  168. }
  169. }
  170. break;
  171. }
  172. }
  173. _calculateMaxLength() {
  174. return (this._dataBlock * (this._neccBlock1 + this._neccBlock2)) + this._neccBlock2;
  175. }
  176. _calculatePolynomial() {
  177. let i, j;
  178. let eccBlock = this._eccBlock;
  179. let polynomial = this._polynomial;
  180. polynomial[0] = 1;
  181. for (i = 0; i < eccBlock; i++) {
  182. polynomial[i + 1] = 1;
  183. for (j = i; j > 0; j--) {
  184. polynomial[j] = polynomial[j] ? polynomial[j - 1] ^
  185. Galois.EXPONENT[this._modN(Galois.LOG[polynomial[j]] + i)] : polynomial[j - 1];
  186. }
  187. polynomial[0] = Galois.EXPONENT[this._modN(Galois.LOG[polynomial[0]] + i)];
  188. }
  189. // Use logs for generator polynomial to save calculation step.
  190. for (i = 0; i <= eccBlock; i++) {
  191. polynomial[i] = Galois.LOG[polynomial[i]];
  192. }
  193. }
  194. _checkBadness() {
  195. let b, b1, h, x, y;
  196. let bad = 0;
  197. let badness = this._badness;
  198. let buffer = this.buffer;
  199. let width = this.width;
  200. // Blocks of same colour.
  201. for (y = 0; y < width - 1; y++) {
  202. for (x = 0; x < width - 1; x++) {
  203. // All foreground colour.
  204. if ((buffer[x + (width * y)] &&
  205. buffer[x + 1 + (width * y)] &&
  206. buffer[x + (width * (y + 1))] &&
  207. buffer[x + 1 + (width * (y + 1))]) ||
  208. // All background colour.
  209. !(buffer[x + (width * y)] ||
  210. buffer[x + 1 + (width * y)] ||
  211. buffer[x + (width * (y + 1))] ||
  212. buffer[x + 1 + (width * (y + 1))])) {
  213. bad += this.N2;
  214. }
  215. }
  216. }
  217. let bw = 0;
  218. // X runs.
  219. for (y = 0; y < width; y++) {
  220. h = 0;
  221. badness[0] = 0;
  222. for (b = 0, x = 0; x < width; x++) {
  223. b1 = buffer[x + (width * y)];
  224. if (b === b1) {
  225. badness[h]++;
  226. } else {
  227. badness[++h] = 1;
  228. }
  229. b = b1;
  230. bw += b ? 1 : -1;
  231. }
  232. bad += this._getBadness(h);
  233. }
  234. if (bw < 0) {
  235. bw = -bw;
  236. }
  237. let count = 0;
  238. let big = bw;
  239. big += big << 2;
  240. big <<= 1;
  241. while (big > width * width) {
  242. big -= width * width;
  243. count++;
  244. }
  245. bad += count * this.N4;
  246. // Y runs.
  247. for (x = 0; x < width; x++) {
  248. h = 0;
  249. badness[0] = 0;
  250. for (b = 0, y = 0; y < width; y++) {
  251. b1 = buffer[x + (width * y)];
  252. if (b === b1) {
  253. badness[h]++;
  254. } else {
  255. badness[++h] = 1;
  256. }
  257. b = b1;
  258. }
  259. bad += this._getBadness(h);
  260. }
  261. return bad;
  262. }
  263. _convertBitStream(length) {
  264. let bit, i;
  265. let ecc = this._ecc;
  266. let version = this._version;
  267. // Convert string to bit stream. 8-bit data to QR-coded 8-bit data (numeric, alphanumeric, or kanji not supported).
  268. for (i = 0; i < length; i++) {
  269. ecc[i] = this._value.charCodeAt(i);
  270. }
  271. let stringBuffer = this._stringBuffer = ecc.slice();
  272. let maxLength = this._calculateMaxLength();
  273. if (length >= maxLength - 2) {
  274. length = maxLength - 2;
  275. if (version > 9) {
  276. length--;
  277. }
  278. }
  279. // Shift and re-pack to insert length prefix.
  280. let index = length;
  281. if (version > 9) {
  282. stringBuffer[index + 2] = 0;
  283. stringBuffer[index + 3] = 0;
  284. while (index--) {
  285. bit = stringBuffer[index];
  286. stringBuffer[index + 3] |= 255 & (bit << 4);
  287. stringBuffer[index + 2] = bit >> 4;
  288. }
  289. stringBuffer[2] |= 255 & (length << 4);
  290. stringBuffer[1] = length >> 4;
  291. stringBuffer[0] = 0x40 | (length >> 12);
  292. } else {
  293. stringBuffer[index + 1] = 0;
  294. stringBuffer[index + 2] = 0;
  295. while (index--) {
  296. bit = stringBuffer[index];
  297. stringBuffer[index + 2] |= 255 & (bit << 4);
  298. stringBuffer[index + 1] = bit >> 4;
  299. }
  300. stringBuffer[1] |= 255 & (length << 4);
  301. stringBuffer[0] = 0x40 | (length >> 4);
  302. }
  303. // Fill to end with pad pattern.
  304. index = length + 3 - (version < 10);
  305. while (index < maxLength) {
  306. stringBuffer[index++] = 0xec;
  307. stringBuffer[index++] = 0x11;
  308. }
  309. }
  310. _getBadness(length) {
  311. let i;
  312. let badRuns = 0;
  313. let badness = this._badness;
  314. for (i = 0; i <= length; i++) {
  315. if (badness[i] >= 5) {
  316. badRuns += this.N1 + badness[i] - 5;
  317. }
  318. }
  319. // FBFFFBF as in finder.
  320. for (i = 3; i < length - 1; i += 2) {
  321. if (badness[i - 2] === badness[i + 2] &&
  322. badness[i + 2] === badness[i - 1] &&
  323. badness[i - 1] === badness[i + 1] &&
  324. badness[i - 1] * 3 === badness[i] &&
  325. // Background around the foreground pattern? Not part of the specs.
  326. (badness[i - 3] === 0 || i + 3 > length ||
  327. badness[i - 3] * 3 >= badness[i] * 4 ||
  328. badness[i + 3] * 3 >= badness[i] * 4)) {
  329. badRuns += this.N3;
  330. }
  331. }
  332. return badRuns;
  333. }
  334. _finish() {
  335. // Save pre-mask copy of frame.
  336. this._stringBuffer = this.buffer.slice();
  337. let currentMask, i;
  338. let bit = 0;
  339. let mask = 30000;
  340. /*
  341. * Using for instead of while since in original Arduino code if an early mask was "good enough" it wouldn't try for
  342. * a better one since they get more complex and take longer.
  343. */
  344. for (i = 0; i < 8; i++) {
  345. // Returns foreground-background imbalance.
  346. this._applyMask(i);
  347. currentMask = this._checkBadness();
  348. // Is current mask better than previous best?
  349. if (currentMask < mask) {
  350. mask = currentMask;
  351. bit = i;
  352. }
  353. // Don't increment "i" to a void redoing mask.
  354. if (bit === 7) {
  355. break;
  356. }
  357. // Reset for next pass.
  358. this.buffer = this._stringBuffer.slice();
  359. }
  360. // Redo best mask as none were "good enough" (i.e. last wasn't bit).
  361. if (bit !== i) {
  362. this._applyMask(bit);
  363. }
  364. // Add in final mask/ECC level bytes.
  365. mask = ErrorCorrection.FINAL_FORMAT[bit + (this._level - 1 << 3)];
  366. let buffer = this.buffer;
  367. let width = this.width;
  368. // Low byte.
  369. for (i = 0; i < 8; i++, mask >>= 1) {
  370. if (mask & 1) {
  371. buffer[width - 1 - i + (width * 8)] = 1;
  372. if (i < 6) {
  373. buffer[8 + (width * i)] = 1;
  374. } else {
  375. buffer[8 + (width * (i + 1))] = 1;
  376. }
  377. }
  378. }
  379. // High byte.
  380. for (i = 0; i < 7; i++, mask >>= 1) {
  381. if (mask & 1) {
  382. buffer[8 + (width * (width - 7 + i))] = 1;
  383. if (i) {
  384. buffer[6 - i + (width * 8)] = 1;
  385. } else {
  386. buffer[7 + (width * 8)] = 1;
  387. }
  388. }
  389. }
  390. }
  391. _interleaveBlocks() {
  392. let i, j;
  393. let dataBlock = this._dataBlock;
  394. let ecc = this._ecc;
  395. let eccBlock = this._eccBlock;
  396. let k = 0;
  397. let maxLength = this._calculateMaxLength();
  398. let neccBlock1 = this._neccBlock1;
  399. let neccBlock2 = this._neccBlock2;
  400. let stringBuffer = this._stringBuffer;
  401. for (i = 0; i < dataBlock; i++) {
  402. for (j = 0; j < neccBlock1; j++) {
  403. ecc[k++] = stringBuffer[i + (j * dataBlock)];
  404. }
  405. for (j = 0; j < neccBlock2; j++) {
  406. ecc[k++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))];
  407. }
  408. }
  409. for (j = 0; j < neccBlock2; j++) {
  410. ecc[k++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))];
  411. }
  412. for (i = 0; i < eccBlock; i++) {
  413. for (j = 0; j < neccBlock1 + neccBlock2; j++) {
  414. ecc[k++] = stringBuffer[maxLength + i + (j * eccBlock)];
  415. }
  416. }
  417. this._stringBuffer = ecc;
  418. }
  419. _insertAlignments() {
  420. let i, x, y;
  421. let version = this._version;
  422. let width = this.width;
  423. if (version > 1) {
  424. i = Alignment.BLOCK[version];
  425. y = width - 7;
  426. for (; ;) {
  427. x = width - 7;
  428. while (x > i - 3) {
  429. this._addAlignment(x, y);
  430. if (x < i) {
  431. break;
  432. }
  433. x -= i;
  434. }
  435. if (y <= i + 9) {
  436. break;
  437. }
  438. y -= i;
  439. this._addAlignment(6, y);
  440. this._addAlignment(y, 6);
  441. }
  442. }
  443. }
  444. _insertFinders() {
  445. let i, j, x, y;
  446. let buffer = this.buffer;
  447. let width = this.width;
  448. for (i = 0; i < 3; i++) {
  449. j = 0;
  450. y = 0;
  451. if (i === 1) {
  452. j = width - 7;
  453. }
  454. if (i === 2) {
  455. y = width - 7;
  456. }
  457. buffer[y + 3 + (width * (j + 3))] = 1;
  458. for (x = 0; x < 6; x++) {
  459. buffer[y + x + (width * j)] = 1;
  460. buffer[y + (width * (j + x + 1))] = 1;
  461. buffer[y + 6 + (width * (j + x))] = 1;
  462. buffer[y + x + 1 + (width * (j + 6))] = 1;
  463. }
  464. for (x = 1; x < 5; x++) {
  465. this._setMask(y + x, j + 1);
  466. this._setMask(y + 1, j + x + 1);
  467. this._setMask(y + 5, j + x);
  468. this._setMask(y + x + 1, j + 5);
  469. }
  470. for (x = 2; x < 4; x++) {
  471. buffer[y + x + (width * (j + 2))] = 1;
  472. buffer[y + 2 + (width * (j + x + 1))] = 1;
  473. buffer[y + 4 + (width * (j + x))] = 1;
  474. buffer[y + x + 1 + (width * (j + 4))] = 1;
  475. }
  476. }
  477. }
  478. _insertTimingGap() {
  479. let x, y;
  480. let width = this.width;
  481. for (y = 0; y < 7; y++) {
  482. this._setMask(7, y);
  483. this._setMask(width - 8, y);
  484. this._setMask(7, y + width - 7);
  485. }
  486. for (x = 0; x < 8; x++) {
  487. this._setMask(x, 7);
  488. this._setMask(x + width - 8, 7);
  489. this._setMask(x, width - 8);
  490. }
  491. }
  492. _insertTimingRowAndColumn() {
  493. let x;
  494. let buffer = this.buffer;
  495. let width = this.width;
  496. for (x = 0; x < width - 14; x++) {
  497. if (x & 1) {
  498. this._setMask(8 + x, 6);
  499. this._setMask(6, 8 + x);
  500. } else {
  501. buffer[8 + x + (width * 6)] = 1;
  502. buffer[6 + (width * (8 + x))] = 1;
  503. }
  504. }
  505. }
  506. _insertVersion() {
  507. let i, j, x, y;
  508. let buffer = this.buffer;
  509. let version = this._version;
  510. let width = this.width;
  511. if (version > 6) {
  512. i = Version.BLOCK[version - 7];
  513. j = 17;
  514. for (x = 0; x < 6; x++) {
  515. for (y = 0; y < 3; y++, j--) {
  516. if (1 & (j > 11 ? version >> j - 12 : i >> j)) {
  517. buffer[5 - x + (width * (2 - y + width - 11))] = 1;
  518. buffer[2 - y + width - 11 + (width * (5 - x))] = 1;
  519. } else {
  520. this._setMask(5 - x, 2 - y + width - 11);
  521. this._setMask(2 - y + width - 11, 5 - x);
  522. }
  523. }
  524. }
  525. }
  526. }
  527. _isMasked(x, y) {
  528. let bit = this._getMaskBit(x, y);
  529. return this._mask[bit] === 1;
  530. }
  531. _pack() {
  532. let bit, i, j;
  533. let k = 1;
  534. let v = 1;
  535. let width = this.width;
  536. let x = width - 1;
  537. let y = width - 1;
  538. // Interleaved data and ECC codes.
  539. let length = ((this._dataBlock + this._eccBlock) * (this._neccBlock1 + this._neccBlock2)) + this._neccBlock2;
  540. for (i = 0; i < length; i++) {
  541. bit = this._stringBuffer[i];
  542. for (j = 0; j < 8; j++, bit <<= 1) {
  543. if (0x80 & bit) {
  544. this.buffer[x + (width * y)] = 1;
  545. }
  546. // Find next fill position.
  547. do {
  548. if (v) {
  549. x--;
  550. } else {
  551. x++;
  552. if (k) {
  553. if (y !== 0) {
  554. y--;
  555. } else {
  556. x -= 2;
  557. k = !k;
  558. if (x === 6) {
  559. x--;
  560. y = 9;
  561. }
  562. }
  563. } else if (y !== width - 1) {
  564. y++;
  565. } else {
  566. x -= 2;
  567. k = !k;
  568. if (x === 6) {
  569. x--;
  570. y -= 8;
  571. }
  572. }
  573. }
  574. v = !v;
  575. } while (this._isMasked(x, y));
  576. }
  577. }
  578. }
  579. _reverseMask() {
  580. let x, y;
  581. let width = this.width;
  582. for (x = 0; x < 9; x++) {
  583. this._setMask(x, 8);
  584. }
  585. for (x = 0; x < 8; x++) {
  586. this._setMask(x + width - 8, 8);
  587. this._setMask(8, x);
  588. }
  589. for (y = 0; y < 7; y++) {
  590. this._setMask(8, y + width - 7);
  591. }
  592. }
  593. _setMask(x, y) {
  594. let bit = this._getMaskBit(x, y);
  595. this._mask[bit] = 1;
  596. }
  597. _syncMask() {
  598. let x, y;
  599. let width = this.width;
  600. for (y = 0; y < width; y++) {
  601. for (x = 0; x <= y; x++) {
  602. if (this.buffer[x + (width * y)]) {
  603. this._setMask(x, y);
  604. }
  605. }
  606. }
  607. }
  608. _createArray(length) {
  609. let i;
  610. let array = [];
  611. for (i = 0; i < length; i++) {
  612. array[i] = 0;
  613. }
  614. return array;
  615. }
  616. _getMaskBit(x, y) {
  617. let bit;
  618. if (x > y) {
  619. bit = x;
  620. x = y;
  621. y = bit;
  622. }
  623. bit = y;
  624. bit += y * y;
  625. bit >>= 1;
  626. bit += x;
  627. return bit;
  628. }
  629. _modN(x) {
  630. while (x >= 255) {
  631. x -= 255;
  632. x = (x >> 8) + (x & 255);
  633. }
  634. return x;
  635. }
  636. // *Badness* coefficients.
  637. N1 = 3;
  638. N2 = 3;
  639. N3 = 40;
  640. N4 = 10;
  641. constructor(options) {
  642. let dataBlock, eccBlock, index, neccBlock1, neccBlock2;
  643. let valueLength = options.value.length;
  644. this._badness = [];
  645. this._level = ErrorCorrection.LEVELS[options.level];
  646. this._polynomial = [];
  647. this._value = options.value;
  648. this._version = 0;
  649. this._stringBuffer = [];
  650. while (this._version < 40) {
  651. this._version++;
  652. index = ((this._level - 1) * 4) + ((this._version - 1) * 16);
  653. neccBlock1 = ErrorCorrection.BLOCKS[index++];
  654. neccBlock2 = ErrorCorrection.BLOCKS[index++];
  655. dataBlock = ErrorCorrection.BLOCKS[index++];
  656. eccBlock = ErrorCorrection.BLOCKS[index];
  657. index = (dataBlock * (neccBlock1 + neccBlock2)) + neccBlock2 - 3 + (this._version <= 9);
  658. if (valueLength <= index) {
  659. break;
  660. }
  661. }
  662. this._dataBlock = dataBlock;
  663. this._eccBlock = eccBlock;
  664. this._neccBlock1 = neccBlock1;
  665. this._neccBlock2 = neccBlock2;
  666. /**
  667. * The data width is based on version.
  668. *
  669. * @public
  670. * @type {number}
  671. * @memberof Frame#
  672. */
  673. // FIXME: Ensure that it fits instead of being truncated.
  674. let width = this.width = 17 + (4 * this._version);
  675. /**
  676. * The image buffer.
  677. *
  678. * @public
  679. * @type {number[]}
  680. * @memberof Frame#
  681. */
  682. this.buffer = this._createArray(width * width);
  683. this._ecc = this._createArray(dataBlock + ((dataBlock + eccBlock) * (neccBlock1 + neccBlock2)) + neccBlock2);
  684. this._mask = this._createArray(((width * (width + 1)) + 1) / 2);
  685. this._insertFinders();
  686. this._insertAlignments();
  687. // Insert single foreground cell.
  688. this.buffer[8 + (width * (width - 8))] = 1;
  689. this._insertTimingGap();
  690. this._reverseMask();
  691. this._insertTimingRowAndColumn();
  692. this._insertVersion();
  693. this._syncMask();
  694. this._convertBitStream(valueLength);
  695. this._calculatePolynomial();
  696. this._appendEccToData();
  697. this._interleaveBlocks();
  698. this._pack();
  699. this._finish();
  700. }
  701. }
  702. export default Frame