Version.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. <?php
  2. /*
  3. * Copyright 2007 ZXing authors
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. namespace Zxing\Qrcode\Decoder;
  18. use Zxing\Common\BitMatrix;
  19. use Zxing\FormatException;
  20. /**
  21. * See ISO 18004:2006 Annex D
  22. *
  23. * @author Sean Owen
  24. */
  25. class Version
  26. {
  27. /**
  28. * See ISO 18004:2006 Annex D.
  29. * Element i represents the raw version bits that specify version i + 7
  30. */
  31. private static array $VERSION_DECODE_INFO = [
  32. 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,
  33. 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,
  34. 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683,
  35. 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,
  36. 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250,
  37. 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B,
  38. 0x2542E, 0x26A64, 0x27541, 0x28C69
  39. ];
  40. /**
  41. * @var mixed|null
  42. */
  43. private static $VERSIONS;
  44. private readonly float|int $totalCodewords;
  45. public function __construct(
  46. private $versionNumber,
  47. private $alignmentPatternCenters,
  48. private $ecBlocks
  49. )
  50. {$total = 0;
  51. if (is_array($ecBlocks)) {
  52. $ecCodewords = $ecBlocks[0]->getECCodewordsPerBlock();
  53. $ecbArray = $ecBlocks[0]->getECBlocks();
  54. } else {
  55. $ecCodewords = $ecBlocks->getECCodewordsPerBlock();
  56. $ecbArray = $ecBlocks->getECBlocks();
  57. }
  58. foreach ($ecbArray as $ecBlock) {
  59. $total += $ecBlock->getCount() * ($ecBlock->getDataCodewords() + $ecCodewords);
  60. }
  61. $this->totalCodewords = $total;
  62. }
  63. public function getVersionNumber()
  64. {
  65. return $this->versionNumber;
  66. }
  67. public function getAlignmentPatternCenters()
  68. {
  69. return $this->alignmentPatternCenters;
  70. }
  71. public function getTotalCodewords()
  72. {
  73. return $this->totalCodewords;
  74. }
  75. public function getDimensionForVersion()
  76. {
  77. return 17 + 4 * $this->versionNumber;
  78. }
  79. public function getECBlocksForLevel($ecLevel)
  80. {
  81. return $this->ecBlocks[$ecLevel->getOrdinal()];
  82. }
  83. /**
  84. * <p>Deduces version information purely from QR Code dimensions.</p>
  85. *
  86. * @param dimension $dimension in modules
  87. * @return Version for a QR Code of that dimension
  88. * @throws FormatException if dimension is not 1 mod 4
  89. */
  90. public static function getProvisionalVersionForDimension($dimension)
  91. {
  92. if ($dimension % 4 != 1) {
  93. throw FormatException::getFormatInstance();
  94. }
  95. try {
  96. return self::getVersionForNumber(($dimension - 17) / 4);
  97. } catch (\InvalidArgumentException) {
  98. throw FormatException::getFormatInstance();
  99. }
  100. }
  101. public static function getVersionForNumber($versionNumber)
  102. {
  103. if ($versionNumber < 1 || $versionNumber > 40) {
  104. throw new \InvalidArgumentException();
  105. }
  106. if (!self::$VERSIONS) {
  107. self::$VERSIONS = self::buildVersions();
  108. }
  109. return self::$VERSIONS[$versionNumber - 1];
  110. }
  111. public static function decodeVersionInformation($versionBits)
  112. {
  113. $bestDifference = PHP_INT_MAX;
  114. $bestVersion = 0;
  115. for ($i = 0; $i < count(self::$VERSION_DECODE_INFO); $i++) {
  116. $targetVersion = self::$VERSION_DECODE_INFO[$i];
  117. // Do the version info bits match exactly? done.
  118. if ($targetVersion == $versionBits) {
  119. return self::getVersionForNumber($i + 7);
  120. }
  121. // Otherwise see if this is the closest to a real version info bit string
  122. // we have seen so far
  123. $bitsDifference = FormatInformation::numBitsDiffering($versionBits, $targetVersion);
  124. if ($bitsDifference < $bestDifference) {
  125. $bestVersion = $i + 7;
  126. $bestDifference = $bitsDifference;
  127. }
  128. }
  129. // We can tolerate up to 3 bits of error since no two version info codewords will
  130. // differ in less than 8 bits.
  131. if ($bestDifference <= 3) {
  132. return self::getVersionForNumber($bestVersion);
  133. }
  134. // If we didn't find a close enough match, fail
  135. return null;
  136. }
  137. /**
  138. * See ISO 18004:2006 Annex E
  139. */
  140. public function buildFunctionPattern()
  141. {
  142. $dimension = self::getDimensionForVersion();
  143. $bitMatrix = new BitMatrix($dimension);
  144. // Top left finder pattern + separator + format
  145. $bitMatrix->setRegion(0, 0, 9, 9);
  146. // Top right finder pattern + separator + format
  147. $bitMatrix->setRegion($dimension - 8, 0, 8, 9);
  148. // Bottom left finder pattern + separator + format
  149. $bitMatrix->setRegion(0, $dimension - 8, 9, 8);
  150. // Alignment patterns
  151. $max = is_countable($this->alignmentPatternCenters) ? count($this->alignmentPatternCenters) : 0;
  152. for ($x = 0; $x < $max; $x++) {
  153. $i = $this->alignmentPatternCenters[$x] - 2;
  154. for ($y = 0; $y < $max; $y++) {
  155. if (($x == 0 && ($y == 0 || $y == $max - 1)) || ($x == $max - 1 && $y == 0)) {
  156. // No alignment patterns near the three finder paterns
  157. continue;
  158. }
  159. $bitMatrix->setRegion($this->alignmentPatternCenters[$y] - 2, $i, 5, 5);
  160. }
  161. }
  162. // Vertical timing pattern
  163. $bitMatrix->setRegion(6, 9, 1, $dimension - 17);
  164. // Horizontal timing pattern
  165. $bitMatrix->setRegion(9, 6, $dimension - 17, 1);
  166. if ($this->versionNumber > 6) {
  167. // Version info, top right
  168. $bitMatrix->setRegion($dimension - 11, 0, 3, 6);
  169. // Version info, bottom left
  170. $bitMatrix->setRegion(0, $dimension - 11, 6, 3);
  171. }
  172. return $bitMatrix;
  173. }
  174. /**
  175. * See ISO 18004:2006 6.5.1 Table 9
  176. */
  177. private static function buildVersions()
  178. {
  179. return [
  180. new Version(
  181. 1,
  182. [],
  183. [new ECBlocks(7, [new ECB(1, 19)]),
  184. new ECBlocks(10, [new ECB(1, 16)]),
  185. new ECBlocks(13, [new ECB(1, 13)]),
  186. new ECBlocks(17, [new ECB(1, 9)])]
  187. ),
  188. new Version(
  189. 2,
  190. [6, 18],
  191. [new ECBlocks(10, [new ECB(1, 34)]),
  192. new ECBlocks(16, [new ECB(1, 28)]),
  193. new ECBlocks(22, [new ECB(1, 22)]),
  194. new ECBlocks(28, [new ECB(1, 16)])]
  195. ),
  196. new Version(
  197. 3,
  198. [6, 22],
  199. [ new ECBlocks(15, [new ECB(1, 55)]),
  200. new ECBlocks(26, [new ECB(1, 44)]),
  201. new ECBlocks(18, [new ECB(2, 17)]),
  202. new ECBlocks(22, [new ECB(2, 13)])]
  203. ),
  204. new Version(
  205. 4,
  206. [6, 26],
  207. [new ECBlocks(20, [new ECB(1, 80)]),
  208. new ECBlocks(18, [new ECB(2, 32)]),
  209. new ECBlocks(26, [new ECB(2, 24)]),
  210. new ECBlocks(16, [new ECB(4, 9)])]
  211. ),
  212. new Version(
  213. 5,
  214. [6, 30],
  215. [new ECBlocks(26, [new ECB(1, 108)]),
  216. new ECBlocks(24, [new ECB(2, 43)]),
  217. new ECBlocks(18, [new ECB(2, 15),
  218. new ECB(2, 16)]),
  219. new ECBlocks(22, [new ECB(2, 11),
  220. new ECB(2, 12)])]
  221. ),
  222. new Version(
  223. 6,
  224. [6, 34],
  225. [new ECBlocks(18, [new ECB(2, 68)]),
  226. new ECBlocks(16, [new ECB(4, 27)]),
  227. new ECBlocks(24, [new ECB(4, 19)]),
  228. new ECBlocks(28, [new ECB(4, 15)])]
  229. ),
  230. new Version(
  231. 7,
  232. [6, 22, 38],
  233. [new ECBlocks(20, [new ECB(2, 78)]),
  234. new ECBlocks(18, [new ECB(4, 31)]),
  235. new ECBlocks(18, [new ECB(2, 14),
  236. new ECB(4, 15)]),
  237. new ECBlocks(26, [new ECB(4, 13),
  238. new ECB(1, 14)])]
  239. ),
  240. new Version(
  241. 8,
  242. [6, 24, 42],
  243. [new ECBlocks(24, [new ECB(2, 97)]),
  244. new ECBlocks(22, [new ECB(2, 38),
  245. new ECB(2, 39)]),
  246. new ECBlocks(22, [new ECB(4, 18),
  247. new ECB(2, 19)]),
  248. new ECBlocks(26, [new ECB(4, 14),
  249. new ECB(2, 15)])]
  250. ),
  251. new Version(
  252. 9,
  253. [6, 26, 46],
  254. [new ECBlocks(30, [new ECB(2, 116)]),
  255. new ECBlocks(22, [new ECB(3, 36),
  256. new ECB(2, 37)]),
  257. new ECBlocks(20, [new ECB(4, 16),
  258. new ECB(4, 17)]),
  259. new ECBlocks(24, [new ECB(4, 12),
  260. new ECB(4, 13)])]
  261. ),
  262. new Version(
  263. 10,
  264. [6, 28, 50],
  265. [new ECBlocks(18, [new ECB(2, 68),
  266. new ECB(2, 69)]),
  267. new ECBlocks(26, [new ECB(4, 43),
  268. new ECB(1, 44)]),
  269. new ECBlocks(24, [new ECB(6, 19),
  270. new ECB(2, 20)]),
  271. new ECBlocks(28, [new ECB(6, 15),
  272. new ECB(2, 16)])]
  273. ),
  274. new Version(
  275. 11,
  276. [6, 30, 54],
  277. [new ECBlocks(20, [new ECB(4, 81)]),
  278. new ECBlocks(30, [new ECB(1, 50),
  279. new ECB(4, 51)]),
  280. new ECBlocks(28, [new ECB(4, 22),
  281. new ECB(4, 23)]),
  282. new ECBlocks(24, [new ECB(3, 12),
  283. new ECB(8, 13)])]
  284. ),
  285. new Version(
  286. 12,
  287. [6, 32, 58],
  288. [new ECBlocks(24, [new ECB(2, 92),
  289. new ECB(2, 93)]),
  290. new ECBlocks(22, [new ECB(6, 36),
  291. new ECB(2, 37)]),
  292. new ECBlocks(26, [new ECB(4, 20),
  293. new ECB(6, 21)]),
  294. new ECBlocks(28, [new ECB(7, 14),
  295. new ECB(4, 15)])]
  296. ),
  297. new Version(
  298. 13,
  299. [6, 34, 62],
  300. [new ECBlocks(26, [new ECB(4, 107)]),
  301. new ECBlocks(22, [new ECB(8, 37),
  302. new ECB(1, 38)]),
  303. new ECBlocks(24, [new ECB(8, 20),
  304. new ECB(4, 21)]),
  305. new ECBlocks(22, [new ECB(12, 11),
  306. new ECB(4, 12)])]
  307. ),
  308. new Version(
  309. 14,
  310. [6, 26, 46, 66],
  311. [new ECBlocks(30, [new ECB(3, 115),
  312. new ECB(1, 116)]),
  313. new ECBlocks(24, [new ECB(4, 40),
  314. new ECB(5, 41)]),
  315. new ECBlocks(20, [new ECB(11, 16),
  316. new ECB(5, 17)]),
  317. new ECBlocks(24, [new ECB(11, 12),
  318. new ECB(5, 13)])]
  319. ),
  320. new Version(
  321. 15,
  322. [6, 26, 48, 70],
  323. [new ECBlocks(22, [new ECB(5, 87),
  324. new ECB(1, 88)]),
  325. new ECBlocks(24, [new ECB(5, 41),
  326. new ECB(5, 42)]),
  327. new ECBlocks(30, [new ECB(5, 24),
  328. new ECB(7, 25)]),
  329. new ECBlocks(24, [new ECB(11, 12),
  330. new ECB(7, 13)])]
  331. ),
  332. new Version(
  333. 16,
  334. [6, 26, 50, 74],
  335. [new ECBlocks(24, [new ECB(5, 98),
  336. new ECB(1, 99)]),
  337. new ECBlocks(28, [new ECB(7, 45),
  338. new ECB(3, 46)]),
  339. new ECBlocks(24, [new ECB(15, 19),
  340. new ECB(2, 20)]),
  341. new ECBlocks(30, [new ECB(3, 15),
  342. new ECB(13, 16)])]
  343. ),
  344. new Version(
  345. 17,
  346. [6, 30, 54, 78],
  347. [new ECBlocks(28, [new ECB(1, 107),
  348. new ECB(5, 108)]),
  349. new ECBlocks(28, [new ECB(10, 46),
  350. new ECB(1, 47)]),
  351. new ECBlocks(28, [new ECB(1, 22),
  352. new ECB(15, 23)]),
  353. new ECBlocks(28, [new ECB(2, 14),
  354. new ECB(17, 15)])]
  355. ),
  356. new Version(
  357. 18,
  358. [6, 30, 56, 82],
  359. [new ECBlocks(30, [new ECB(5, 120),
  360. new ECB(1, 121)]),
  361. new ECBlocks(26, [new ECB(9, 43),
  362. new ECB(4, 44)]),
  363. new ECBlocks(28, [new ECB(17, 22),
  364. new ECB(1, 23)]),
  365. new ECBlocks(28, [new ECB(2, 14),
  366. new ECB(19, 15)])]
  367. ),
  368. new Version(
  369. 19,
  370. [6, 30, 58, 86],
  371. [new ECBlocks(28, [new ECB(3, 113),
  372. new ECB(4, 114)]),
  373. new ECBlocks(26, [new ECB(3, 44),
  374. new ECB(11, 45)]),
  375. new ECBlocks(26, [new ECB(17, 21),
  376. new ECB(4, 22)]),
  377. new ECBlocks(26, [new ECB(9, 13),
  378. new ECB(16, 14)])]
  379. ),
  380. new Version(
  381. 20,
  382. [6, 34, 62, 90],
  383. [new ECBlocks(28, [new ECB(3, 107),
  384. new ECB(5, 108)]),
  385. new ECBlocks(26, [new ECB(3, 41),
  386. new ECB(13, 42)]),
  387. new ECBlocks(30, [new ECB(15, 24),
  388. new ECB(5, 25)]),
  389. new ECBlocks(28, [new ECB(15, 15),
  390. new ECB(10, 16)])]
  391. ),
  392. new Version(
  393. 21,
  394. [6, 28, 50, 72, 94],
  395. [ new ECBlocks(28, [new ECB(4, 116),
  396. new ECB(4, 117)]),
  397. new ECBlocks(26, [new ECB(17, 42)]),
  398. new ECBlocks(28, [new ECB(17, 22),
  399. new ECB(6, 23)]),
  400. new ECBlocks(30, [new ECB(19, 16),
  401. new ECB(6, 17)])]
  402. ),
  403. new Version(
  404. 22,
  405. [6, 26, 50, 74, 98],
  406. [new ECBlocks(28, [new ECB(2, 111),
  407. new ECB(7, 112)]),
  408. new ECBlocks(28, [new ECB(17, 46)]),
  409. new ECBlocks(30, [new ECB(7, 24),
  410. new ECB(16, 25)]),
  411. new ECBlocks(24, [new ECB(34, 13)])]
  412. ),
  413. new Version(
  414. 23,
  415. [6, 30, 54, 78, 102],
  416. new ECBlocks(30, [new ECB(4, 121),
  417. new ECB(5, 122)]),
  418. new ECBlocks(28, [new ECB(4, 47),
  419. new ECB(14, 48)]),
  420. new ECBlocks(30, [new ECB(11, 24),
  421. new ECB(14, 25)]),
  422. new ECBlocks(30, [new ECB(16, 15),
  423. new ECB(14, 16)])
  424. ),
  425. new Version(
  426. 24,
  427. [6, 28, 54, 80, 106],
  428. [new ECBlocks(30, [new ECB(6, 117),
  429. new ECB(4, 118)]),
  430. new ECBlocks(28, [new ECB(6, 45),
  431. new ECB(14, 46)]),
  432. new ECBlocks(30, [new ECB(11, 24),
  433. new ECB(16, 25)]),
  434. new ECBlocks(30, [new ECB(30, 16),
  435. new ECB(2, 17)])]
  436. ),
  437. new Version(
  438. 25,
  439. [6, 32, 58, 84, 110],
  440. [new ECBlocks(26, [new ECB(8, 106),
  441. new ECB(4, 107)]),
  442. new ECBlocks(28, [new ECB(8, 47),
  443. new ECB(13, 48)]),
  444. new ECBlocks(30, [new ECB(7, 24),
  445. new ECB(22, 25)]),
  446. new ECBlocks(30, [new ECB(22, 15),
  447. new ECB(13, 16)])]
  448. ),
  449. new Version(
  450. 26,
  451. [6, 30, 58, 86, 114],
  452. [new ECBlocks(28, [new ECB(10, 114),
  453. new ECB(2, 115)]),
  454. new ECBlocks(28, [new ECB(19, 46),
  455. new ECB(4, 47)]),
  456. new ECBlocks(28, [new ECB(28, 22),
  457. new ECB(6, 23)]),
  458. new ECBlocks(30, [new ECB(33, 16),
  459. new ECB(4, 17)])]
  460. ),
  461. new Version(
  462. 27,
  463. [6, 34, 62, 90, 118],
  464. [new ECBlocks(30, [new ECB(8, 122),
  465. new ECB(4, 123)]),
  466. new ECBlocks(28, [new ECB(22, 45),
  467. new ECB(3, 46)]),
  468. new ECBlocks(30, [new ECB(8, 23),
  469. new ECB(26, 24)]),
  470. new ECBlocks(30, [new ECB(12, 15),
  471. new ECB(28, 16)])]
  472. ),
  473. new Version(
  474. 28,
  475. [6, 26, 50, 74, 98, 122],
  476. [new ECBlocks(30, [new ECB(3, 117),
  477. new ECB(10, 118)]),
  478. new ECBlocks(28, [new ECB(3, 45),
  479. new ECB(23, 46)]),
  480. new ECBlocks(30, [new ECB(4, 24),
  481. new ECB(31, 25)]),
  482. new ECBlocks(30, [new ECB(11, 15),
  483. new ECB(31, 16)])]
  484. ),
  485. new Version(
  486. 29,
  487. [6, 30, 54, 78, 102, 126],
  488. [new ECBlocks(30, [new ECB(7, 116),
  489. new ECB(7, 117)]),
  490. new ECBlocks(28, [new ECB(21, 45),
  491. new ECB(7, 46)]),
  492. new ECBlocks(30, [new ECB(1, 23),
  493. new ECB(37, 24)]),
  494. new ECBlocks(30, [new ECB(19, 15),
  495. new ECB(26, 16)])]
  496. ),
  497. new Version(
  498. 30,
  499. [6, 26, 52, 78, 104, 130],
  500. [new ECBlocks(30, [new ECB(5, 115),
  501. new ECB(10, 116)]),
  502. new ECBlocks(28, [new ECB(19, 47),
  503. new ECB(10, 48)]),
  504. new ECBlocks(30, [new ECB(15, 24),
  505. new ECB(25, 25)]),
  506. new ECBlocks(30, [new ECB(23, 15),
  507. new ECB(25, 16)])]
  508. ),
  509. new Version(
  510. 31,
  511. [6, 30, 56, 82, 108, 134],
  512. [new ECBlocks(30, [new ECB(13, 115),
  513. new ECB(3, 116)]),
  514. new ECBlocks(28, [new ECB(2, 46),
  515. new ECB(29, 47)]),
  516. new ECBlocks(30, [new ECB(42, 24),
  517. new ECB(1, 25)]),
  518. new ECBlocks(30, [new ECB(23, 15),
  519. new ECB(28, 16)])]
  520. ),
  521. new Version(
  522. 32,
  523. [6, 34, 60, 86, 112, 138],
  524. [new ECBlocks(30, [new ECB(17, 115)]),
  525. new ECBlocks(28, [new ECB(10, 46),
  526. new ECB(23, 47)]),
  527. new ECBlocks(30, [new ECB(10, 24),
  528. new ECB(35, 25)]),
  529. new ECBlocks(30, [new ECB(19, 15),
  530. new ECB(35, 16)])]
  531. ),
  532. new Version(
  533. 33,
  534. [6, 30, 58, 86, 114, 142],
  535. [new ECBlocks(30, [new ECB(17, 115),
  536. new ECB(1, 116)]),
  537. new ECBlocks(28, [new ECB(14, 46),
  538. new ECB(21, 47)]),
  539. new ECBlocks(30, [new ECB(29, 24),
  540. new ECB(19, 25)]),
  541. new ECBlocks(30, [new ECB(11, 15),
  542. new ECB(46, 16)])]
  543. ),
  544. new Version(
  545. 34,
  546. [6, 34, 62, 90, 118, 146],
  547. [new ECBlocks(30, [new ECB(13, 115),
  548. new ECB(6, 116)]),
  549. new ECBlocks(28, [new ECB(14, 46),
  550. new ECB(23, 47)]),
  551. new ECBlocks(30, [new ECB(44, 24),
  552. new ECB(7, 25)]),
  553. new ECBlocks(30, [new ECB(59, 16),
  554. new ECB(1, 17)])]
  555. ),
  556. new Version(
  557. 35,
  558. [6, 30, 54, 78, 102, 126, 150],
  559. [new ECBlocks(30, [new ECB(12, 121),
  560. new ECB(7, 122)]),
  561. new ECBlocks(28, [new ECB(12, 47),
  562. new ECB(26, 48)]),
  563. new ECBlocks(30, [new ECB(39, 24),
  564. new ECB(14, 25)]),
  565. new ECBlocks(30, [new ECB(22, 15),
  566. new ECB(41, 16)])]
  567. ),
  568. new Version(
  569. 36,
  570. [6, 24, 50, 76, 102, 128, 154],
  571. [new ECBlocks(30, [new ECB(6, 121),
  572. new ECB(14, 122)]),
  573. new ECBlocks(28, [new ECB(6, 47),
  574. new ECB(34, 48)]),
  575. new ECBlocks(30, [new ECB(46, 24),
  576. new ECB(10, 25)]),
  577. new ECBlocks(30, [new ECB(2, 15),
  578. new ECB(64, 16)])]
  579. ),
  580. new Version(
  581. 37,
  582. [6, 28, 54, 80, 106, 132, 158],
  583. [new ECBlocks(30, [new ECB(17, 122),
  584. new ECB(4, 123)]),
  585. new ECBlocks(28, [new ECB(29, 46),
  586. new ECB(14, 47)]),
  587. new ECBlocks(30, [new ECB(49, 24),
  588. new ECB(10, 25)]),
  589. new ECBlocks(30, [new ECB(24, 15),
  590. new ECB(46, 16)])]
  591. ),
  592. new Version(
  593. 38,
  594. [6, 32, 58, 84, 110, 136, 162],
  595. [new ECBlocks(30, [new ECB(4, 122),
  596. new ECB(18, 123)]),
  597. new ECBlocks(28, [new ECB(13, 46),
  598. new ECB(32, 47)]),
  599. new ECBlocks(30, [new ECB(48, 24),
  600. new ECB(14, 25)]),
  601. new ECBlocks(30, [new ECB(42, 15),
  602. new ECB(32, 16)])]
  603. ),
  604. new Version(
  605. 39,
  606. [6, 26, 54, 82, 110, 138, 166],
  607. [new ECBlocks(30, [new ECB(20, 117),
  608. new ECB(4, 118)]),
  609. new ECBlocks(28, [new ECB(40, 47),
  610. new ECB(7, 48)]),
  611. new ECBlocks(30, [new ECB(43, 24),
  612. new ECB(22, 25)]),
  613. new ECBlocks(30, [new ECB(10, 15),
  614. new ECB(67, 16)])]
  615. ),
  616. new Version(
  617. 40,
  618. [6, 30, 58, 86, 114, 142, 170],
  619. [new ECBlocks(30, [new ECB(19, 118),
  620. new ECB(6, 119)]),
  621. new ECBlocks(28, [new ECB(18, 47),
  622. new ECB(31, 48)]),
  623. new ECBlocks(30, [new ECB(34, 24),
  624. new ECB(34, 25)]),
  625. new ECBlocks(30, [new ECB(20, 15),
  626. new ECB(61, 16)])]
  627. )
  628. ];
  629. }
  630. }
  631. /**
  632. * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will
  633. * use blocks of differing sizes within one version, so, this encapsulates the parameters for
  634. * each set of blocks. It also holds the number of error-correction codewords per block since it
  635. * will be the same across all blocks within one version.</p>
  636. */
  637. final class ECBlocks
  638. {
  639. public function __construct(private $ecCodewordsPerBlock, private $ecBlocks)
  640. {
  641. }
  642. public function getECCodewordsPerBlock()
  643. {
  644. return $this->ecCodewordsPerBlock;
  645. }
  646. public function getNumBlocks()
  647. {
  648. $total = 0;
  649. foreach ($this->ecBlocks as $ecBlock) {
  650. $total += $ecBlock->getCount();
  651. }
  652. return $total;
  653. }
  654. public function getTotalECCodewords()
  655. {
  656. return $this->ecCodewordsPerBlock * $this->getNumBlocks();
  657. }
  658. public function getECBlocks()
  659. {
  660. return $this->ecBlocks;
  661. }
  662. }
  663. /**
  664. * <p>Encapsualtes the parameters for one error-correction block in one symbol version.
  665. * This includes the number of data codewords, and the number of times a block with these
  666. * parameters is used consecutively in the QR code version's format.</p>
  667. */
  668. final class ECB
  669. {
  670. public function __construct(private $count, private $dataCodewords)
  671. {
  672. }
  673. public function getCount()
  674. {
  675. return $this->count;
  676. }
  677. public function getDataCodewords()
  678. {
  679. return $this->dataCodewords;
  680. }
  681. //@Override
  682. public function toString(): never
  683. {
  684. die('Version ECB toString()');
  685. // return parent::$versionNumber;
  686. }
  687. }