qrcode.php 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732
  1. <?php
  2. if (!defined('QRCODEDEFS')) {
  3. define('QRCODEDEFS', true);
  4. define('QR_MODE_NL', -1);
  5. define('QR_MODE_NM', 0);
  6. define('QR_MODE_AN', 1);
  7. define('QR_MODE_8B', 2);
  8. define('QR_MODE_KJ', 3);
  9. define('QR_MODE_ST', 4);
  10. define('QR_ECLEVEL_L', 0);
  11. define('QR_ECLEVEL_M', 1);
  12. define('QR_ECLEVEL_Q', 2);
  13. define('QR_ECLEVEL_H', 3);
  14. define('QRSPEC_VERSION_MAX', 40);
  15. define('QRSPEC_WIDTH_MAX', 177);
  16. define('QRCAP_WIDTH', 0);
  17. define('QRCAP_WORDS', 1);
  18. define('QRCAP_REMINDER', 2);
  19. define('QRCAP_EC', 3);
  20. define('STRUCTURE_HEADER_BITS', 20);
  21. define('MAX_STRUCTURED_SYMBOLS', 16);
  22. define('N1', 3);
  23. define('N2', 3);
  24. define('N3', 40);
  25. define('N4', 10);
  26. define('QR_FIND_BEST_MASK', true);
  27. define('QR_FIND_FROM_RANDOM', 2);
  28. define('QR_DEFAULT_MASK', 2);
  29. }
  30. if (!class_exists('QRcode', false)) {
  31. if (!function_exists('str_split')) {
  32. function str_split($string, $split_length = 1)
  33. {
  34. if ($split_length < strlen($string) || !$split_length) {
  35. do {
  36. $c = strlen($string);
  37. $parts[] = substr($string, 0, $split_length);
  38. $string = substr($string, $split_length);
  39. } while ($string !== false);
  40. }
  41. else {
  42. $parts = array($string);
  43. }
  44. return $parts;
  45. }
  46. }
  47. class QRcode
  48. {
  49. /**
  50. * @var barcode array to be returned which is readable by TCPDF
  51. * @access protected
  52. */
  53. protected $barcode_array = array();
  54. /**
  55. * @var QR code version. Size of QRcode is defined as version. Version is from 1 to 40. Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases. So version 40 is 177*177 matrix.
  56. * @access protected
  57. */
  58. protected $version = 0;
  59. /**
  60. * @var Levels of error correction. See definitions for possible values.
  61. * @access protected
  62. */
  63. protected $level = QR_ECLEVEL_L;
  64. /**
  65. * @var Encoding mode
  66. * @access protected
  67. */
  68. protected $hint = QR_MODE_8B;
  69. /**
  70. * @var if true the input string will be converted to uppercase
  71. * @access protected
  72. */
  73. protected $casesensitive = true;
  74. /**
  75. * @var structured QR code (not supported yet)
  76. * @access protected
  77. */
  78. protected $structured = 0;
  79. /**
  80. * @var mask data
  81. * @access protected
  82. */
  83. protected $data;
  84. /**
  85. * @var width
  86. * @access protected
  87. */
  88. protected $width;
  89. /**
  90. * @var frame
  91. * @access protected
  92. */
  93. protected $frame;
  94. /**
  95. * @var X position of bit
  96. * @access protected
  97. */
  98. protected $x;
  99. /**
  100. * @var Y position of bit
  101. * @access protected
  102. */
  103. protected $y;
  104. /**
  105. * @var direction
  106. * @access protected
  107. */
  108. protected $dir;
  109. /**
  110. * @var single bit
  111. * @access protected
  112. */
  113. protected $bit;
  114. /**
  115. * @var data code
  116. * @access protected
  117. */
  118. protected $datacode = array();
  119. /**
  120. * @var error correction code
  121. * @access protected
  122. */
  123. protected $ecccode = array();
  124. /**
  125. * @var blocks
  126. * @access protected
  127. */
  128. protected $blocks;
  129. /**
  130. * @var Reed-Solomon blocks
  131. * @access protected
  132. */
  133. protected $rsblocks = array();
  134. /**
  135. * @var counter
  136. * @access protected
  137. */
  138. protected $count;
  139. /**
  140. * @var data length
  141. * @access protected
  142. */
  143. protected $dataLength;
  144. /**
  145. * @var error correction length
  146. * @access protected
  147. */
  148. protected $eccLength;
  149. /**
  150. * @var b1
  151. * @access protected
  152. */
  153. protected $b1;
  154. /**
  155. * @var run length
  156. * @access protected
  157. */
  158. protected $runLength = array();
  159. /**
  160. * @var input data string
  161. * @access protected
  162. */
  163. protected $dataStr = '';
  164. /**
  165. * @var input items
  166. * @access protected
  167. */
  168. protected $items;
  169. /**
  170. * @var Reed-Solomon items
  171. * @access protected
  172. */
  173. protected $rsitems = array();
  174. /**
  175. * @var array of frames
  176. * @access protected
  177. */
  178. protected $frames = array();
  179. /**
  180. * @var alphabet-numeric convesion table
  181. * @access protected
  182. */
  183. protected $anTable = array(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
  184. /**
  185. * @var array Table of the capacity of symbols
  186. * See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004.
  187. * @access protected
  188. */
  189. protected $capacity = array(
  190. array(
  191. 0,
  192. 0,
  193. 0,
  194. array(0, 0, 0, 0)
  195. ),
  196. array(
  197. 21,
  198. 26,
  199. 0,
  200. array(7, 10, 13, 17)
  201. ),
  202. array(
  203. 25,
  204. 44,
  205. 7,
  206. array(10, 16, 22, 28)
  207. ),
  208. array(
  209. 29,
  210. 70,
  211. 7,
  212. array(15, 26, 36, 44)
  213. ),
  214. array(
  215. 33,
  216. 100,
  217. 7,
  218. array(20, 36, 52, 64)
  219. ),
  220. array(
  221. 37,
  222. 134,
  223. 7,
  224. array(26, 48, 72, 88)
  225. ),
  226. array(
  227. 41,
  228. 172,
  229. 7,
  230. array(36, 64, 96, 112)
  231. ),
  232. array(
  233. 45,
  234. 196,
  235. 0,
  236. array(40, 72, 108, 130)
  237. ),
  238. array(
  239. 49,
  240. 242,
  241. 0,
  242. array(48, 88, 132, 156)
  243. ),
  244. array(
  245. 53,
  246. 292,
  247. 0,
  248. array(60, 110, 160, 192)
  249. ),
  250. array(
  251. 57,
  252. 346,
  253. 0,
  254. array(72, 130, 192, 224)
  255. ),
  256. array(
  257. 61,
  258. 404,
  259. 0,
  260. array(80, 150, 224, 264)
  261. ),
  262. array(
  263. 65,
  264. 466,
  265. 0,
  266. array(96, 176, 260, 308)
  267. ),
  268. array(
  269. 69,
  270. 532,
  271. 0,
  272. array(104, 198, 288, 352)
  273. ),
  274. array(
  275. 73,
  276. 581,
  277. 3,
  278. array(120, 216, 320, 384)
  279. ),
  280. array(
  281. 77,
  282. 655,
  283. 3,
  284. array(132, 240, 360, 432)
  285. ),
  286. array(
  287. 81,
  288. 733,
  289. 3,
  290. array(144, 280, 408, 480)
  291. ),
  292. array(
  293. 85,
  294. 815,
  295. 3,
  296. array(168, 308, 448, 532)
  297. ),
  298. array(
  299. 89,
  300. 901,
  301. 3,
  302. array(180, 338, 504, 588)
  303. ),
  304. array(
  305. 93,
  306. 991,
  307. 3,
  308. array(196, 364, 546, 650)
  309. ),
  310. array(
  311. 97,
  312. 1085,
  313. 3,
  314. array(224, 416, 600, 700)
  315. ),
  316. array(
  317. 101,
  318. 1156,
  319. 4,
  320. array(224, 442, 644, 750)
  321. ),
  322. array(
  323. 105,
  324. 1258,
  325. 4,
  326. array(252, 476, 690, 816)
  327. ),
  328. array(
  329. 109,
  330. 1364,
  331. 4,
  332. array(270, 504, 750, 900)
  333. ),
  334. array(
  335. 113,
  336. 1474,
  337. 4,
  338. array(300, 560, 810, 960)
  339. ),
  340. array(
  341. 117,
  342. 1588,
  343. 4,
  344. array(312, 588, 870, 1050)
  345. ),
  346. array(
  347. 121,
  348. 1706,
  349. 4,
  350. array(336, 644, 952, 1110)
  351. ),
  352. array(
  353. 125,
  354. 1828,
  355. 4,
  356. array(360, 700, 1020, 1200)
  357. ),
  358. array(
  359. 129,
  360. 1921,
  361. 3,
  362. array(390, 728, 1050, 1260)
  363. ),
  364. array(
  365. 133,
  366. 2051,
  367. 3,
  368. array(420, 784, 1140, 1350)
  369. ),
  370. array(
  371. 137,
  372. 2185,
  373. 3,
  374. array(450, 812, 1200, 1440)
  375. ),
  376. array(
  377. 141,
  378. 2323,
  379. 3,
  380. array(480, 868, 1290, 1530)
  381. ),
  382. array(
  383. 145,
  384. 2465,
  385. 3,
  386. array(510, 924, 1350, 1620)
  387. ),
  388. array(
  389. 149,
  390. 2611,
  391. 3,
  392. array(540, 980, 1440, 1710)
  393. ),
  394. array(
  395. 153,
  396. 2761,
  397. 3,
  398. array(570, 1036, 1530, 1800)
  399. ),
  400. array(
  401. 157,
  402. 2876,
  403. 0,
  404. array(570, 1064, 1590, 1890)
  405. ),
  406. array(
  407. 161,
  408. 3034,
  409. 0,
  410. array(600, 1120, 1680, 1980)
  411. ),
  412. array(
  413. 165,
  414. 3196,
  415. 0,
  416. array(630, 1204, 1770, 2100)
  417. ),
  418. array(
  419. 169,
  420. 3362,
  421. 0,
  422. array(660, 1260, 1860, 2220)
  423. ),
  424. array(
  425. 173,
  426. 3532,
  427. 0,
  428. array(720, 1316, 1950, 2310)
  429. ),
  430. array(
  431. 177,
  432. 3706,
  433. 0,
  434. array(750, 1372, 2040, 2430)
  435. )
  436. );
  437. /**
  438. * @var array Length indicator
  439. * @access protected
  440. */
  441. protected $lengthTableBits = array(
  442. array(10, 12, 14),
  443. array(9, 11, 13),
  444. array(8, 16, 16),
  445. array(8, 10, 12)
  446. );
  447. /**
  448. * @var array Table of the error correction code (Reed-Solomon block)
  449. * See Table 12-16 (pp.30-36), JIS X0510:2004.
  450. * @access protected
  451. */
  452. protected $eccTable = array(
  453. array(
  454. array(0, 0),
  455. array(0, 0),
  456. array(0, 0),
  457. array(0, 0)
  458. ),
  459. array(
  460. array(1, 0),
  461. array(1, 0),
  462. array(1, 0),
  463. array(1, 0)
  464. ),
  465. array(
  466. array(1, 0),
  467. array(1, 0),
  468. array(1, 0),
  469. array(1, 0)
  470. ),
  471. array(
  472. array(1, 0),
  473. array(1, 0),
  474. array(2, 0),
  475. array(2, 0)
  476. ),
  477. array(
  478. array(1, 0),
  479. array(2, 0),
  480. array(2, 0),
  481. array(4, 0)
  482. ),
  483. array(
  484. array(1, 0),
  485. array(2, 0),
  486. array(2, 2),
  487. array(2, 2)
  488. ),
  489. array(
  490. array(2, 0),
  491. array(4, 0),
  492. array(4, 0),
  493. array(4, 0)
  494. ),
  495. array(
  496. array(2, 0),
  497. array(4, 0),
  498. array(2, 4),
  499. array(4, 1)
  500. ),
  501. array(
  502. array(2, 0),
  503. array(2, 2),
  504. array(4, 2),
  505. array(4, 2)
  506. ),
  507. array(
  508. array(2, 0),
  509. array(3, 2),
  510. array(4, 4),
  511. array(4, 4)
  512. ),
  513. array(
  514. array(2, 2),
  515. array(4, 1),
  516. array(6, 2),
  517. array(6, 2)
  518. ),
  519. array(
  520. array(4, 0),
  521. array(1, 4),
  522. array(4, 4),
  523. array(3, 8)
  524. ),
  525. array(
  526. array(2, 2),
  527. array(6, 2),
  528. array(4, 6),
  529. array(7, 4)
  530. ),
  531. array(
  532. array(4, 0),
  533. array(8, 1),
  534. array(8, 4),
  535. array(12, 4)
  536. ),
  537. array(
  538. array(3, 1),
  539. array(4, 5),
  540. array(11, 5),
  541. array(11, 5)
  542. ),
  543. array(
  544. array(5, 1),
  545. array(5, 5),
  546. array(5, 7),
  547. array(11, 7)
  548. ),
  549. array(
  550. array(5, 1),
  551. array(7, 3),
  552. array(15, 2),
  553. array(3, 13)
  554. ),
  555. array(
  556. array(1, 5),
  557. array(10, 1),
  558. array(1, 15),
  559. array(2, 17)
  560. ),
  561. array(
  562. array(5, 1),
  563. array(9, 4),
  564. array(17, 1),
  565. array(2, 19)
  566. ),
  567. array(
  568. array(3, 4),
  569. array(3, 11),
  570. array(17, 4),
  571. array(9, 16)
  572. ),
  573. array(
  574. array(3, 5),
  575. array(3, 13),
  576. array(15, 5),
  577. array(15, 10)
  578. ),
  579. array(
  580. array(4, 4),
  581. array(17, 0),
  582. array(17, 6),
  583. array(19, 6)
  584. ),
  585. array(
  586. array(2, 7),
  587. array(17, 0),
  588. array(7, 16),
  589. array(34, 0)
  590. ),
  591. array(
  592. array(4, 5),
  593. array(4, 14),
  594. array(11, 14),
  595. array(16, 14)
  596. ),
  597. array(
  598. array(6, 4),
  599. array(6, 14),
  600. array(11, 16),
  601. array(30, 2)
  602. ),
  603. array(
  604. array(8, 4),
  605. array(8, 13),
  606. array(7, 22),
  607. array(22, 13)
  608. ),
  609. array(
  610. array(10, 2),
  611. array(19, 4),
  612. array(28, 6),
  613. array(33, 4)
  614. ),
  615. array(
  616. array(8, 4),
  617. array(22, 3),
  618. array(8, 26),
  619. array(12, 28)
  620. ),
  621. array(
  622. array(3, 10),
  623. array(3, 23),
  624. array(4, 31),
  625. array(11, 31)
  626. ),
  627. array(
  628. array(7, 7),
  629. array(21, 7),
  630. array(1, 37),
  631. array(19, 26)
  632. ),
  633. array(
  634. array(5, 10),
  635. array(19, 10),
  636. array(15, 25),
  637. array(23, 25)
  638. ),
  639. array(
  640. array(13, 3),
  641. array(2, 29),
  642. array(42, 1),
  643. array(23, 28)
  644. ),
  645. array(
  646. array(17, 0),
  647. array(10, 23),
  648. array(10, 35),
  649. array(19, 35)
  650. ),
  651. array(
  652. array(17, 1),
  653. array(14, 21),
  654. array(29, 19),
  655. array(11, 46)
  656. ),
  657. array(
  658. array(13, 6),
  659. array(14, 23),
  660. array(44, 7),
  661. array(59, 1)
  662. ),
  663. array(
  664. array(12, 7),
  665. array(12, 26),
  666. array(39, 14),
  667. array(22, 41)
  668. ),
  669. array(
  670. array(6, 14),
  671. array(6, 34),
  672. array(46, 10),
  673. array(2, 64)
  674. ),
  675. array(
  676. array(17, 4),
  677. array(29, 14),
  678. array(49, 10),
  679. array(24, 46)
  680. ),
  681. array(
  682. array(4, 18),
  683. array(13, 32),
  684. array(48, 14),
  685. array(42, 32)
  686. ),
  687. array(
  688. array(20, 4),
  689. array(40, 7),
  690. array(43, 22),
  691. array(10, 67)
  692. ),
  693. array(
  694. array(19, 6),
  695. array(18, 31),
  696. array(34, 34),
  697. array(20, 61)
  698. )
  699. );
  700. /**
  701. * @var array Positions of alignment patterns.
  702. * This array includes only the second and the third position of the alignment patterns. Rest of them can be calculated from the distance between them.
  703. * See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
  704. * @access protected
  705. */
  706. protected $alignmentPattern = array(
  707. array(0, 0),
  708. array(0, 0),
  709. array(18, 0),
  710. array(22, 0),
  711. array(26, 0),
  712. array(30, 0),
  713. array(34, 0),
  714. array(22, 38),
  715. array(24, 42),
  716. array(26, 46),
  717. array(28, 50),
  718. array(30, 54),
  719. array(32, 58),
  720. array(34, 62),
  721. array(26, 46),
  722. array(26, 48),
  723. array(26, 50),
  724. array(30, 54),
  725. array(30, 56),
  726. array(30, 58),
  727. array(34, 62),
  728. array(28, 50),
  729. array(26, 50),
  730. array(30, 54),
  731. array(28, 54),
  732. array(32, 58),
  733. array(30, 58),
  734. array(34, 62),
  735. array(26, 50),
  736. array(30, 54),
  737. array(26, 52),
  738. array(30, 56),
  739. array(34, 60),
  740. array(30, 58),
  741. array(34, 62),
  742. array(30, 54),
  743. array(24, 50),
  744. array(28, 54),
  745. array(32, 58),
  746. array(26, 54),
  747. array(30, 58)
  748. );
  749. /**
  750. * @var array Version information pattern (BCH coded).
  751. * See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
  752. * size: [QRSPEC_VERSION_MAX - 6]
  753. * @access protected
  754. */
  755. protected $versionPattern = array(31892, 34236, 39577, 42195, 48118, 51042, 55367, 58893, 63784, 68472, 70749, 76311, 79154, 84390, 87683, 92361, 96236, 102084, 102881, 110507, 110734, 117786, 119615, 126325, 127568, 133589, 136944, 141498, 145311, 150283, 152622, 158308, 161089, 167017);
  756. /**
  757. * @var array Format information
  758. * @access protected
  759. */
  760. protected $formatInfo = array(
  761. array(30660, 29427, 32170, 30877, 26159, 25368, 27713, 26998),
  762. array(21522, 20773, 24188, 23371, 17913, 16590, 20375, 19104),
  763. array(13663, 12392, 16177, 14854, 9396, 8579, 11994, 11245),
  764. array(5769, 5054, 7399, 6608, 1890, 597, 3340, 2107)
  765. );
  766. public function __construct($code, $eclevel = 'L')
  767. {
  768. $barcode_array = array();
  769. if (is_null($code) || $code == '\\0' || $code == '') {
  770. return false;
  771. }
  772. $this->level = array_search($eclevel, array('L', 'M', 'Q', 'H'));
  773. if ($this->level === false) {
  774. $this->level = QR_ECLEVEL_L;
  775. }
  776. if ($this->hint != QR_MODE_8B && $this->hint != QR_MODE_KJ) {
  777. return false;
  778. }
  779. if ($this->version < 0 || QRSPEC_VERSION_MAX < $this->version) {
  780. return false;
  781. }
  782. $this->items = array();
  783. $this->encodeString($code);
  784. $qrTab = $this->binarize($this->data);
  785. $size = count($qrTab);
  786. $barcode_array['num_rows'] = $size;
  787. $barcode_array['num_cols'] = $size;
  788. $barcode_array['bcode'] = array();
  789. foreach ($qrTab as $line) {
  790. $arrAdd = array();
  791. foreach (str_split($line) as $char) {
  792. $arrAdd[] = $char == '1' ? 1 : 0;
  793. }
  794. $barcode_array['bcode'][] = $arrAdd;
  795. }
  796. $this->barcode_array = $barcode_array;
  797. }
  798. public function getBarcodeArray()
  799. {
  800. return $this->barcode_array;
  801. }
  802. protected function binarize($frame)
  803. {
  804. $len = count($frame);
  805. foreach ($frame as &$frameLine) {
  806. for ($i = 0; $i < $len; $i++) {
  807. $frameLine[$i] = ord($frameLine[$i]) & 1 ? '1' : '0';
  808. }
  809. }
  810. return $frame;
  811. }
  812. protected function encodeString($string)
  813. {
  814. $this->dataStr = $string;
  815. if (!$this->casesensitive) {
  816. $this->toUpper();
  817. }
  818. $ret = $this->splitString();
  819. if ($ret < 0) {
  820. return NULL;
  821. }
  822. $this->encodeMask(-1);
  823. }
  824. protected function encodeMask($mask)
  825. {
  826. $spec = array(0, 0, 0, 0, 0);
  827. $this->datacode = $this->getByteStream($this->items);
  828. if (is_null($this->datacode)) {
  829. return NULL;
  830. }
  831. $spec = $this->getEccSpec($this->version, $this->level, $spec);
  832. $this->b1 = $this->rsBlockNum1($spec);
  833. $this->dataLength = $this->rsDataLength($spec);
  834. $this->eccLength = $this->rsEccLength($spec);
  835. $this->ecccode = array_fill(0, $this->eccLength, 0);
  836. $this->blocks = $this->rsBlockNum($spec);
  837. $ret = $this->init($spec);
  838. if ($ret < 0) {
  839. return NULL;
  840. }
  841. $this->count = 0;
  842. $this->width = $this->getWidth($this->version);
  843. $this->frame = $this->newFrame($this->version);
  844. $this->x = $this->width - 1;
  845. $this->y = $this->width - 1;
  846. $this->dir = -1;
  847. $this->bit = -1;
  848. for ($i = 0; $i < $this->dataLength + $this->eccLength; $i++) {
  849. $code = $this->getCode();
  850. $bit = 128;
  851. for ($j = 0; $j < 8; $j++) {
  852. $addr = $this->getNextPosition();
  853. $this->setFrameAt($addr, 2 | ($bit & $code) != 0);
  854. $bit = $bit >> 1;
  855. }
  856. }
  857. $j = $this->getRemainder($this->version);
  858. for ($i = 0; $i < $j; $i++) {
  859. $addr = $this->getNextPosition();
  860. $this->setFrameAt($addr, 2);
  861. }
  862. $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
  863. if ($mask < 0) {
  864. if (QR_FIND_BEST_MASK) {
  865. $masked = $this->mask($this->width, $this->frame, $this->level);
  866. }
  867. else {
  868. $masked = $this->makeMask($this->width, $this->frame, intval(QR_DEFAULT_MASK) % 8, $this->level);
  869. }
  870. }
  871. else {
  872. $masked = $this->makeMask($this->width, $this->frame, $mask, $this->level);
  873. }
  874. if ($masked == NULL) {
  875. return NULL;
  876. }
  877. $this->data = $masked;
  878. }
  879. protected function setFrameAt($at, $val)
  880. {
  881. $this->frame[$at['y']][$at['x']] = chr($val);
  882. }
  883. protected function getFrameAt($at)
  884. {
  885. return ord($this->frame[$at['y']][$at['x']]);
  886. }
  887. protected function getNextPosition()
  888. {
  889. do {
  890. if ($this->bit == -1) {
  891. $this->bit = 0;
  892. return array('x' => $this->x, 'y' => $this->y);
  893. }
  894. $x = $this->x;
  895. $y = $this->y;
  896. $w = $this->width;
  897. if ($this->bit == 0) {
  898. $x--;
  899. $this->bit++;
  900. }
  901. else {
  902. $x++;
  903. $y += $this->dir;
  904. $this->bit--;
  905. }
  906. if ($this->dir < 0) {
  907. if ($y < 0) {
  908. $y = 0;
  909. $x -= 2;
  910. $this->dir = 1;
  911. if ($x == 6) {
  912. $x--;
  913. $y = 9;
  914. }
  915. }
  916. }
  917. else if ($y == $w) {
  918. $y = $w - 1;
  919. $x -= 2;
  920. $this->dir = -1;
  921. if ($x == 6) {
  922. $x--;
  923. $y -= 8;
  924. }
  925. }
  926. if ($x < 0 || $y < 0) {
  927. return NULL;
  928. }
  929. $this->x = $x;
  930. $this->y = $y;
  931. } while (ord($this->frame[$y][$x]) & 128);
  932. return array('x' => $x, 'y' => $y);
  933. }
  934. protected function init($spec)
  935. {
  936. $dl = $this->rsDataCodes1($spec);
  937. $el = $this->rsEccCodes1($spec);
  938. $rs = $this->init_rs(8, 285, 0, 1, $el, 255 - $dl - $el);
  939. $blockNo = 0;
  940. $dataPos = 0;
  941. $eccPos = 0;
  942. $endfor = $this->rsBlockNum1($spec);
  943. for ($i = 0; $i < $endfor; ++$i) {
  944. $ecc = array_slice($this->ecccode, $eccPos);
  945. $this->rsblocks[$blockNo] = array();
  946. $this->rsblocks[$blockNo]['dataLength'] = $dl;
  947. $this->rsblocks[$blockNo]['data'] = array_slice($this->datacode, $dataPos);
  948. $this->rsblocks[$blockNo]['eccLength'] = $el;
  949. $ecc = $this->encode_rs_char($rs, $this->rsblocks[$blockNo]['data'], $ecc);
  950. $this->rsblocks[$blockNo]['ecc'] = $ecc;
  951. $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc);
  952. $dataPos += $dl;
  953. $eccPos += $el;
  954. $blockNo++;
  955. }
  956. if ($this->rsBlockNum2($spec) == 0) {
  957. return 0;
  958. }
  959. $dl = $this->rsDataCodes2($spec);
  960. $el = $this->rsEccCodes2($spec);
  961. $rs = $this->init_rs(8, 285, 0, 1, $el, 255 - $dl - $el);
  962. if ($rs == NULL) {
  963. return -1;
  964. }
  965. $endfor = $this->rsBlockNum2($spec);
  966. for ($i = 0; $i < $endfor; ++$i) {
  967. $ecc = array_slice($this->ecccode, $eccPos);
  968. $this->rsblocks[$blockNo] = array();
  969. $this->rsblocks[$blockNo]['dataLength'] = $dl;
  970. $this->rsblocks[$blockNo]['data'] = array_slice($this->datacode, $dataPos);
  971. $this->rsblocks[$blockNo]['eccLength'] = $el;
  972. $ecc = $this->encode_rs_char($rs, $this->rsblocks[$blockNo]['data'], $ecc);
  973. $this->rsblocks[$blockNo]['ecc'] = $ecc;
  974. $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc);
  975. $dataPos += $dl;
  976. $eccPos += $el;
  977. $blockNo++;
  978. }
  979. return 0;
  980. }
  981. protected function getCode()
  982. {
  983. if ($this->count < $this->dataLength) {
  984. $row = $this->count % $this->blocks;
  985. $col = $this->count / $this->blocks;
  986. if ($this->rsblocks[0]['dataLength'] <= $col) {
  987. $row += $this->b1;
  988. }
  989. $ret = $this->rsblocks[$row]['data'][$col];
  990. }
  991. else if ($this->count < $this->dataLength + $this->eccLength) {
  992. $row = ($this->count - $this->dataLength) % $this->blocks;
  993. $col = ($this->count - $this->dataLength) / $this->blocks;
  994. $ret = $this->rsblocks[$row]['ecc'][$col];
  995. }
  996. else {
  997. return 0;
  998. }
  999. $this->count++;
  1000. return $ret;
  1001. }
  1002. protected function writeFormatInformation($width, &$frame, $mask, $level)
  1003. {
  1004. $blacks = 0;
  1005. $format = $this->getFormatInfo($mask, $level);
  1006. for ($i = 0; $i < 8; ++$i) {
  1007. if ($format & 1) {
  1008. $blacks += 2;
  1009. $v = 133;
  1010. }
  1011. else {
  1012. $v = 132;
  1013. }
  1014. $frame[8][$width - 1 - $i] = chr($v);
  1015. if ($i < 6) {
  1016. $frame[$i][8] = chr($v);
  1017. }
  1018. else {
  1019. $frame[$i + 1][8] = chr($v);
  1020. }
  1021. $format = $format >> 1;
  1022. }
  1023. for ($i = 0; $i < 7; ++$i) {
  1024. if ($format & 1) {
  1025. $blacks += 2;
  1026. $v = 133;
  1027. }
  1028. else {
  1029. $v = 132;
  1030. }
  1031. $frame[$width - 7 + $i][8] = chr($v);
  1032. if ($i == 0) {
  1033. $frame[8][7] = chr($v);
  1034. }
  1035. else {
  1036. $frame[8][6 - $i] = chr($v);
  1037. }
  1038. $format = $format >> 1;
  1039. }
  1040. return $blacks;
  1041. }
  1042. protected function mask0($x, $y)
  1043. {
  1044. return $x + $y & 1;
  1045. }
  1046. protected function mask1($x, $y)
  1047. {
  1048. return $y & 1;
  1049. }
  1050. protected function mask2($x, $y)
  1051. {
  1052. return $x % 3;
  1053. }
  1054. protected function mask3($x, $y)
  1055. {
  1056. return ($x + $y) % 3;
  1057. }
  1058. protected function mask4($x, $y)
  1059. {
  1060. return (int) ($y / 2) + (int) ($x / 3) & 1;
  1061. }
  1062. protected function mask5($x, $y)
  1063. {
  1064. return ($x * $y & 1) + $x * $y % 3;
  1065. }
  1066. protected function mask6($x, $y)
  1067. {
  1068. return ($x * $y & 1) + $x * $y % 3 & 1;
  1069. }
  1070. protected function mask7($x, $y)
  1071. {
  1072. return $x * $y % 3 + ($x + $y & 1) & 1;
  1073. }
  1074. protected function generateMaskNo($maskNo, $width, $frame)
  1075. {
  1076. $bitMask = array_fill(0, $width, array_fill(0, $width, 0));
  1077. for ($y = 0; $y < $width; ++$y) {
  1078. for ($x = 0; $x < $width; ++$x) {
  1079. if (ord($frame[$y][$x]) & 128) {
  1080. $bitMask[$y][$x] = 0;
  1081. }
  1082. else {
  1083. $maskFunc = call_user_func(array($this, 'mask' . $maskNo), $x, $y);
  1084. $bitMask[$y][$x] = $maskFunc == 0 ? 1 : 0;
  1085. }
  1086. }
  1087. }
  1088. return $bitMask;
  1089. }
  1090. protected function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false)
  1091. {
  1092. $b = 0;
  1093. $bitMask = array();
  1094. $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
  1095. if ($maskGenOnly) {
  1096. return NULL;
  1097. }
  1098. $d = $s;
  1099. for ($y = 0; $y < $width; ++$y) {
  1100. for ($x = 0; $x < $width; ++$x) {
  1101. if ($bitMask[$y][$x] == 1) {
  1102. $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int) $bitMask[$y][$x]);
  1103. }
  1104. $b += (int) (ord($d[$y][$x]) & 1);
  1105. }
  1106. }
  1107. return $b;
  1108. }
  1109. protected function makeMask($width, $frame, $maskNo, $level)
  1110. {
  1111. $masked = array_fill(0, $width, str_repeat('', $width));
  1112. $this->makeMaskNo($maskNo, $width, $frame, $masked);
  1113. $this->writeFormatInformation($width, $masked, $maskNo, $level);
  1114. return $masked;
  1115. }
  1116. protected function calcN1N3($length)
  1117. {
  1118. $demerit = 0;
  1119. for ($i = 0; $i < $length; ++$i) {
  1120. if (5 <= $this->runLength[$i]) {
  1121. $demerit += N1 + ($this->runLength[$i] - 5);
  1122. }
  1123. if ($i & 1) {
  1124. if (3 <= $i && $i < $length - 2 && $this->runLength[$i] % 3 == 0) {
  1125. $fact = (int) ($this->runLength[$i] / 3);
  1126. if ($this->runLength[$i - 2] == $fact && $this->runLength[$i - 1] == $fact && $this->runLength[$i + 1] == $fact && $this->runLength[$i + 2] == $fact) {
  1127. if ($this->runLength[$i - 3] < 0 || 4 * $fact <= $this->runLength[$i - 3]) {
  1128. $demerit += N3;
  1129. }
  1130. else {
  1131. if ($length <= $i + 3 || 4 * $fact <= $this->runLength[$i + 3]) {
  1132. $demerit += N3;
  1133. }
  1134. }
  1135. }
  1136. }
  1137. }
  1138. }
  1139. return $demerit;
  1140. }
  1141. protected function evaluateSymbol($width, $frame)
  1142. {
  1143. $head = 0;
  1144. $demerit = 0;
  1145. for ($y = 0; $y < $width; ++$y) {
  1146. $head = 0;
  1147. $this->runLength[0] = 1;
  1148. $frameY = $frame[$y];
  1149. if (0 < $y) {
  1150. $frameYM = $frame[$y - 1];
  1151. }
  1152. for ($x = 0; $x < $width; ++$x) {
  1153. if (0 < $x && 0 < $y) {
  1154. $b22 = ord($frameY[$x]) & ord($frameY[$x - 1]) & ord($frameYM[$x]) & ord($frameYM[$x - 1]);
  1155. $w22 = ord($frameY[$x]) | ord($frameY[$x - 1]) | ord($frameYM[$x]) | ord($frameYM[$x - 1]);
  1156. if (($b22 | $w22 ^ 1) & 1) {
  1157. $demerit += N2;
  1158. }
  1159. }
  1160. if ($x == 0 && ord($frameY[$x]) & 1) {
  1161. $this->runLength[0] = -1;
  1162. $head = 1;
  1163. $this->runLength[$head] = 1;
  1164. }
  1165. else if (0 < $x) {
  1166. if ((ord($frameY[$x]) ^ ord($frameY[$x - 1])) & 1) {
  1167. $head++;
  1168. $this->runLength[$head] = 1;
  1169. }
  1170. else {
  1171. $this->runLength[$head]++;
  1172. }
  1173. }
  1174. }
  1175. $demerit += $this->calcN1N3($head + 1);
  1176. }
  1177. for ($x = 0; $x < $width; ++$x) {
  1178. $head = 0;
  1179. $this->runLength[0] = 1;
  1180. for ($y = 0; $y < $width; ++$y) {
  1181. if ($y == 0 && ord($frame[$y][$x]) & 1) {
  1182. $this->runLength[0] = -1;
  1183. $head = 1;
  1184. $this->runLength[$head] = 1;
  1185. }
  1186. else if (0 < $y) {
  1187. if ((ord($frame[$y][$x]) ^ ord($frame[$y - 1][$x])) & 1) {
  1188. $head++;
  1189. $this->runLength[$head] = 1;
  1190. }
  1191. else {
  1192. $this->runLength[$head]++;
  1193. }
  1194. }
  1195. }
  1196. $demerit += $this->calcN1N3($head + 1);
  1197. }
  1198. return $demerit;
  1199. }
  1200. protected function mask($width, $frame, $level)
  1201. {
  1202. $minDemerit = PHP_INT_MAX;
  1203. $bestMaskNum = 0;
  1204. $bestMask = array();
  1205. $checked_masks = array(0, 1, 2, 3, 4, 5, 6, 7);
  1206. if (QR_FIND_FROM_RANDOM !== false) {
  1207. $howManuOut = 8 - QR_FIND_FROM_RANDOM % 9;
  1208. for ($i = 0; $i < $howManuOut; ++$i) {
  1209. $remPos = rand(0, count($checked_masks) - 1);
  1210. unset($checked_masks[$remPos]);
  1211. $checked_masks = array_values($checked_masks);
  1212. }
  1213. }
  1214. $bestMask = $frame;
  1215. foreach ($checked_masks as $i) {
  1216. $mask = array_fill(0, $width, str_repeat('', $width));
  1217. $demerit = 0;
  1218. $blacks = 0;
  1219. $blacks = $this->makeMaskNo($i, $width, $frame, $mask);
  1220. $blacks += $this->writeFormatInformation($width, $mask, $i, $level);
  1221. $blacks = (int) (100 * $blacks / ($width * $width));
  1222. $demerit = (int) ((int) (abs($blacks - 50) / 5) * N4);
  1223. $demerit += $this->evaluateSymbol($width, $mask);
  1224. if ($demerit < $minDemerit) {
  1225. $minDemerit = $demerit;
  1226. $bestMask = $mask;
  1227. $bestMaskNum = $i;
  1228. }
  1229. }
  1230. return $bestMask;
  1231. }
  1232. protected function isdigitat($str, $pos)
  1233. {
  1234. if (strlen($str) <= $pos) {
  1235. return false;
  1236. }
  1237. return ord('0') <= ord($str[$pos]) && ord($str[$pos]) <= ord('9');
  1238. }
  1239. protected function isalnumat($str, $pos)
  1240. {
  1241. if (strlen($str) <= $pos) {
  1242. return false;
  1243. }
  1244. return 0 <= $this->lookAnTable(ord($str[$pos]));
  1245. }
  1246. protected function identifyMode($pos)
  1247. {
  1248. if (strlen($this->dataStr) <= $pos) {
  1249. return QR_MODE_NL;
  1250. }
  1251. $c = $this->dataStr[$pos];
  1252. if ($this->isdigitat($this->dataStr, $pos)) {
  1253. return QR_MODE_NM;
  1254. }
  1255. else if ($this->isalnumat($this->dataStr, $pos)) {
  1256. return QR_MODE_AN;
  1257. }
  1258. else if ($this->hint == QR_MODE_KJ) {
  1259. if ($pos + 1 < strlen($this->dataStr)) {
  1260. $d = $this->dataStr[$pos + 1];
  1261. $word = ord($c) << 8 | ord($d);
  1262. if (33088 <= $word && $word <= 40956 || 57408 <= $word && $word <= 60351) {
  1263. return QR_MODE_KJ;
  1264. }
  1265. }
  1266. }
  1267. return QR_MODE_8B;
  1268. }
  1269. protected function eatNum()
  1270. {
  1271. $ln = $this->lengthIndicator(QR_MODE_NM, $this->version);
  1272. $p = 0;
  1273. while ($this->isdigitat($this->dataStr, $p)) {
  1274. $p++;
  1275. }
  1276. $run = $p;
  1277. $mode = $this->identifyMode($p);
  1278. if ($mode == QR_MODE_8B) {
  1279. $dif = $this->estimateBitsModeNum($run) + 4 + $ln + $this->estimateBitsMode8(1) - $this->estimateBitsMode8($run + 1);
  1280. if (0 < $dif) {
  1281. return $this->eat8();
  1282. }
  1283. }
  1284. if ($mode == QR_MODE_AN) {
  1285. $dif = $this->estimateBitsModeNum($run) + 4 + $ln + $this->estimateBitsModeAn(1) - $this->estimateBitsModeAn($run + 1);
  1286. if (0 < $dif) {
  1287. return $this->eatAn();
  1288. }
  1289. }
  1290. $this->items = $this->appendNewInputItem($this->items, QR_MODE_NM, $run, str_split($this->dataStr));
  1291. return $run;
  1292. }
  1293. protected function eatAn()
  1294. {
  1295. $la = $this->lengthIndicator(QR_MODE_AN, $this->version);
  1296. $ln = $this->lengthIndicator(QR_MODE_NM, $this->version);
  1297. $p = 0;
  1298. while ($this->isalnumat($this->dataStr, $p)) {
  1299. if ($this->isdigitat($this->dataStr, $p)) {
  1300. $q = $p;
  1301. while ($this->isdigitat($this->dataStr, $q)) {
  1302. $q++;
  1303. }
  1304. $dif = $this->estimateBitsModeAn($p) + $this->estimateBitsModeNum($q - $p) + 4 + $ln - $this->estimateBitsModeAn($q);
  1305. if ($dif < 0) {
  1306. break;
  1307. }
  1308. else {
  1309. $p = $q;
  1310. }
  1311. }
  1312. else {
  1313. $p++;
  1314. }
  1315. }
  1316. $run = $p;
  1317. if (!$this->isalnumat($this->dataStr, $p)) {
  1318. $dif = $this->estimateBitsModeAn($run) + 4 + $la + $this->estimateBitsMode8(1) - $this->estimateBitsMode8($run + 1);
  1319. if (0 < $dif) {
  1320. return $this->eat8();
  1321. }
  1322. }
  1323. $this->items = $this->appendNewInputItem($this->items, QR_MODE_AN, $run, str_split($this->dataStr));
  1324. return $run;
  1325. }
  1326. protected function eatKanji()
  1327. {
  1328. $p = 0;
  1329. while ($this->identifyMode($p) == QR_MODE_KJ) {
  1330. $p += 2;
  1331. }
  1332. $this->items = $this->appendNewInputItem($this->items, QR_MODE_KJ, $p, str_split($this->dataStr));
  1333. return $run;
  1334. }
  1335. protected function eat8()
  1336. {
  1337. $la = $this->lengthIndicator(QR_MODE_AN, $this->version);
  1338. $ln = $this->lengthIndicator(QR_MODE_NM, $this->version);
  1339. $p = 1;
  1340. $dataStrLen = strlen($this->dataStr);
  1341. while ($p < $dataStrLen) {
  1342. $mode = $this->identifyMode($p);
  1343. if ($mode == QR_MODE_KJ) {
  1344. break;
  1345. }
  1346. if ($mode == QR_MODE_NM) {
  1347. $q = $p;
  1348. while ($this->isdigitat($this->dataStr, $q)) {
  1349. $q++;
  1350. }
  1351. $dif = $this->estimateBitsMode8($p) + $this->estimateBitsModeNum($q - $p) + 4 + $ln - $this->estimateBitsMode8($q);
  1352. if ($dif < 0) {
  1353. break;
  1354. }
  1355. else {
  1356. $p = $q;
  1357. }
  1358. }
  1359. else if ($mode == QR_MODE_AN) {
  1360. $q = $p;
  1361. while ($this->isalnumat($this->dataStr, $q)) {
  1362. $q++;
  1363. }
  1364. $dif = $this->estimateBitsMode8($p) + $this->estimateBitsModeAn($q - $p) + 4 + $la - $this->estimateBitsMode8($q);
  1365. if ($dif < 0) {
  1366. break;
  1367. }
  1368. else {
  1369. $p = $q;
  1370. }
  1371. }
  1372. else {
  1373. $p++;
  1374. }
  1375. }
  1376. $run = $p;
  1377. $this->items = $this->appendNewInputItem($this->items, QR_MODE_8B, $run, str_split($this->dataStr));
  1378. return $run;
  1379. }
  1380. protected function splitString()
  1381. {
  1382. while (0 < strlen($this->dataStr)) {
  1383. if ($this->dataStr == '') {
  1384. return 0;
  1385. }
  1386. $mode = $this->identifyMode(0);
  1387. switch ($mode) {
  1388. case QR_MODE_NM:
  1389. $length = $this->eatNum();
  1390. break;
  1391. case QR_MODE_AN:
  1392. $length = $this->eatAn();
  1393. break;
  1394. case QR_MODE_KJ:
  1395. if ($hint == QR_MODE_KJ) {
  1396. $length = $this->eatKanji();
  1397. }
  1398. else {
  1399. $length = $this->eat8();
  1400. }
  1401. break;
  1402. default:
  1403. $length = $this->eat8();
  1404. break;
  1405. }
  1406. if ($length == 0) {
  1407. return 0;
  1408. }
  1409. if ($length < 0) {
  1410. return -1;
  1411. }
  1412. $this->dataStr = substr($this->dataStr, $length);
  1413. }
  1414. }
  1415. protected function toUpper()
  1416. {
  1417. $stringLen = strlen($this->dataStr);
  1418. $p = 0;
  1419. while ($p < $stringLen) {
  1420. $mode = $this->identifyMode(substr($this->dataStr, $p), $this->hint);
  1421. if ($mode == QR_MODE_KJ) {
  1422. $p += 2;
  1423. }
  1424. else {
  1425. if (ord('a') <= ord($this->dataStr[$p]) && ord($this->dataStr[$p]) <= ord('z')) {
  1426. $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
  1427. }
  1428. $p++;
  1429. }
  1430. }
  1431. return $this->dataStr;
  1432. }
  1433. protected function newInputItem($mode, $size, $data, $bstream = NULL)
  1434. {
  1435. $setData = array_slice($data, 0, $size);
  1436. if (count($setData) < $size) {
  1437. $setData = array_merge($setData, array_fill(0, $size - count($setData), 0));
  1438. }
  1439. if (!$this->check($mode, $size, $setData)) {
  1440. return NULL;
  1441. }
  1442. $inputitem = array();
  1443. $inputitem['mode'] = $mode;
  1444. $inputitem['size'] = $size;
  1445. $inputitem['data'] = $setData;
  1446. $inputitem['bstream'] = $bstream;
  1447. return $inputitem;
  1448. }
  1449. protected function encodeModeNum($inputitem, $version)
  1450. {
  1451. $words = (int) ($inputitem['size'] / 3);
  1452. $inputitem['bstream'] = array();
  1453. $val = 1;
  1454. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, $val);
  1455. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_NM, $version), $inputitem['size']);
  1456. for ($i = 0; $i < $words; ++$i) {
  1457. $val = (ord($inputitem['data'][$i * 3]) - ord('0')) * 100;
  1458. $val += (ord($inputitem['data'][$i * 3 + 1]) - ord('0')) * 10;
  1459. $val += ord($inputitem['data'][$i * 3 + 2]) - ord('0');
  1460. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 10, $val);
  1461. }
  1462. if ($inputitem['size'] - $words * 3 == 1) {
  1463. $val = ord($inputitem['data'][$words * 3]) - ord('0');
  1464. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, $val);
  1465. }
  1466. else if ($inputitem['size'] - $words * 3 == 2) {
  1467. $val = (ord($inputitem['data'][$words * 3]) - ord('0')) * 10;
  1468. $val += ord($inputitem['data'][$words * 3 + 1]) - ord('0');
  1469. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 7, $val);
  1470. }
  1471. return $inputitem;
  1472. }
  1473. protected function encodeModeAn($inputitem, $version)
  1474. {
  1475. $words = (int) ($inputitem['size'] / 2);
  1476. $inputitem['bstream'] = array();
  1477. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 2);
  1478. $inputitem['bstream'] = $this->appendNum(v, $this->lengthIndicator(QR_MODE_AN, $version), $inputitem['size']);
  1479. for ($i = 0; $i < $words; ++$i) {
  1480. $val = (int) $this->lookAnTable(ord($inputitem['data'][$i * 2])) * 45;
  1481. $val += (int) $this->lookAnTable(ord($inputitem['data'][$i * 2 + 1]));
  1482. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 11, $val);
  1483. }
  1484. if ($inputitem['size'] & 1) {
  1485. $val = $this->lookAnTable(ord($inputitem['data'][$words * 2]));
  1486. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 6, $val);
  1487. }
  1488. return $inputitem;
  1489. }
  1490. protected function encodeMode8($inputitem, $version)
  1491. {
  1492. $inputitem['bstream'] = array();
  1493. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 4);
  1494. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_8B, $version), $inputitem['size']);
  1495. for ($i = 0; $i < $inputitem['size']; ++$i) {
  1496. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 8, ord($inputitem['data'][$i]));
  1497. }
  1498. return $inputitem;
  1499. }
  1500. protected function encodeModeKanji($inputitem, $version)
  1501. {
  1502. $inputitem['bstream'] = array();
  1503. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 8);
  1504. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_KJ, $version), (int) ($inputitem['size'] / 2));
  1505. for ($i = 0; $i < $inputitem['size']; $i += 2) {
  1506. $val = ord($inputitem['data'][$i]) << 8 | ord($inputitem['data'][$i + 1]);
  1507. if ($val <= 40956) {
  1508. $val -= 33088;
  1509. }
  1510. else {
  1511. $val -= 49472;
  1512. }
  1513. $h = ($val >> 8) * 192;
  1514. $val = ($val & 255) + $h;
  1515. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 13, $val);
  1516. }
  1517. return $inputitem;
  1518. }
  1519. protected function encodeModeStructure($inputitem)
  1520. {
  1521. $inputitem['bstream'] = array();
  1522. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 3);
  1523. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, ord($inputitem['data'][1]) - 1);
  1524. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, ord($inputitem['data'][0]) - 1);
  1525. $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 8, ord($inputitem['data'][2]));
  1526. return $inputitem;
  1527. }
  1528. protected function encodeBitStream($inputitem, $version)
  1529. {
  1530. $inputitem['bstream'] = array();
  1531. $words = $this->maximumWords($inputitem['mode'], $version);
  1532. if ($words < $inputitem['size']) {
  1533. $st1 = $this->newInputItem($inputitem['mode'], $words, $inputitem['data']);
  1534. $st2 = $this->newInputItem($inputitem['mode'], $inputitem['size'] - $words, array_slice($inputitem['data'], $words));
  1535. $st1 = $this->encodeBitStream($st1, $version);
  1536. $st2 = $this->encodeBitStream($st2, $version);
  1537. $inputitem['bstream'] = array();
  1538. $inputitem['bstream'] = $this->appendBitstream($inputitem['bstream'], $st1['bstream']);
  1539. $inputitem['bstream'] = $this->appendBitstream($inputitem['bstream'], $st2['bstream']);
  1540. }
  1541. else {
  1542. switch ($inputitem['mode']) {
  1543. case QR_MODE_NM:
  1544. $inputitem = $this->encodeModeNum($inputitem, $version);
  1545. break;
  1546. case QR_MODE_AN:
  1547. $inputitem = $this->encodeModeAn($inputitem, $version);
  1548. break;
  1549. case QR_MODE_8B:
  1550. $inputitem = $this->encodeMode8($inputitem, $version);
  1551. break;
  1552. case QR_MODE_KJ:
  1553. $inputitem = $this->encodeModeKanji($inputitem, $version);
  1554. break;
  1555. case QR_MODE_ST:
  1556. $inputitem = $this->encodeModeStructure($inputitem);
  1557. break;
  1558. default:
  1559. break;
  1560. }
  1561. }
  1562. return $inputitem;
  1563. }
  1564. protected function appendNewInputItem($items, $mode, $size, $data)
  1565. {
  1566. $items[] = $this->newInputItem($mode, $size, $data);
  1567. return $items;
  1568. }
  1569. protected function insertStructuredAppendHeader($items, $size, $index, $parity)
  1570. {
  1571. if (MAX_STRUCTURED_SYMBOLS < $size) {
  1572. return -1;
  1573. }
  1574. if ($index <= 0 || MAX_STRUCTURED_SYMBOLS < $index) {
  1575. return -1;
  1576. }
  1577. $buf = array($size, $index, $parity);
  1578. $entry = $this->newInputItem(QR_MODE_ST, 3, buf);
  1579. array_unshift($items, $entry);
  1580. return $items;
  1581. }
  1582. protected function calcParity($items)
  1583. {
  1584. $parity = 0;
  1585. foreach ($items as $item) {
  1586. if ($item['mode'] != QR_MODE_ST) {
  1587. for ($i = $item['size'] - 1; 0 <= $i; --$i) {
  1588. $parity ^= $item['data'][$i];
  1589. }
  1590. }
  1591. }
  1592. return $parity;
  1593. }
  1594. protected function checkModeNum($size, $data)
  1595. {
  1596. for ($i = 0; $i < $size; ++$i) {
  1597. if (ord($data[$i]) < ord('0') || ord('9') < ord($data[$i])) {
  1598. return false;
  1599. }
  1600. }
  1601. return true;
  1602. }
  1603. protected function estimateBitsModeNum($size)
  1604. {
  1605. $w = (int) $size / 3;
  1606. $bits = $w * 10;
  1607. switch ($size - $w * 3) {
  1608. case 1:
  1609. $bits += 4;
  1610. break;
  1611. case 2:
  1612. $bits += 7;
  1613. break;
  1614. default:
  1615. break;
  1616. }
  1617. return $bits;
  1618. }
  1619. protected function lookAnTable($c)
  1620. {
  1621. return 127 < $c ? -1 : $this->anTable[$c];
  1622. }
  1623. protected function checkModeAn($size, $data)
  1624. {
  1625. for ($i = 0; $i < $size; ++$i) {
  1626. if ($this->lookAnTable(ord($data[$i])) == -1) {
  1627. return false;
  1628. }
  1629. }
  1630. return true;
  1631. }
  1632. protected function estimateBitsModeAn($size)
  1633. {
  1634. $w = (int) ($size / 2);
  1635. $bits = $w * 11;
  1636. if ($size & 1) {
  1637. $bits += 6;
  1638. }
  1639. return $bits;
  1640. }
  1641. protected function estimateBitsMode8($size)
  1642. {
  1643. return $size * 8;
  1644. }
  1645. protected function estimateBitsModeKanji($size)
  1646. {
  1647. return (int) ($size / 2 * 13);
  1648. }
  1649. protected function checkModeKanji($size, $data)
  1650. {
  1651. if ($size & 1) {
  1652. return false;
  1653. }
  1654. for ($i = 0; $i < $size; $i += 2) {
  1655. $val = ord($data[$i]) << 8 | ord($data[$i + 1]);
  1656. if ($val < 33088 || 40956 < $val && $val < 57408 || 60351 < $val) {
  1657. return false;
  1658. }
  1659. }
  1660. return true;
  1661. }
  1662. protected function check($mode, $size, $data)
  1663. {
  1664. if ($size <= 0) {
  1665. return false;
  1666. }
  1667. switch ($mode) {
  1668. case QR_MODE_NM:
  1669. return $this->checkModeNum($size, $data);
  1670. case QR_MODE_AN:
  1671. return $this->checkModeAn($size, $data);
  1672. case QR_MODE_KJ:
  1673. return $this->checkModeKanji($size, $data);
  1674. case QR_MODE_8B:
  1675. return true;
  1676. case QR_MODE_ST:
  1677. return true;
  1678. default:
  1679. break;
  1680. }
  1681. return false;
  1682. }
  1683. protected function estimateBitStreamSize($items, $version)
  1684. {
  1685. $bits = 0;
  1686. if ($version == 0) {
  1687. $version = 1;
  1688. }
  1689. foreach ($items as $item) {
  1690. switch ($item['mode']) {
  1691. case QR_MODE_NM:
  1692. $bits = $this->estimateBitsModeNum($item['size']);
  1693. break;
  1694. case QR_MODE_AN:
  1695. $bits = $this->estimateBitsModeAn($item['size']);
  1696. break;
  1697. case QR_MODE_8B:
  1698. $bits = $this->estimateBitsMode8($item['size']);
  1699. break;
  1700. case QR_MODE_KJ:
  1701. $bits = $this->estimateBitsModeKanji($item['size']);
  1702. break;
  1703. case QR_MODE_ST:
  1704. return STRUCTURE_HEADER_BITS;
  1705. default:
  1706. return 0;
  1707. }
  1708. $l = $this->lengthIndicator($item['mode'], $version);
  1709. $m = 1 << $l;
  1710. $num = (int) (($item['size'] + $m - 1) / $m);
  1711. $bits += $num * (4 + $l);
  1712. }
  1713. return $bits;
  1714. }
  1715. protected function estimateVersion($items)
  1716. {
  1717. $version = 0;
  1718. $prev = 0;
  1719. do {
  1720. $prev = $version;
  1721. $bits = $this->estimateBitStreamSize($items, $prev);
  1722. $version = $this->getMinimumVersion((int) (($bits + 7) / 8), $this->level);
  1723. if ($version < 0) {
  1724. return -1;
  1725. }
  1726. } while ($prev < $version);
  1727. return $version;
  1728. }
  1729. protected function lengthOfCode($mode, $version, $bits)
  1730. {
  1731. $payload = $bits - 4 - $this->lengthIndicator($mode, $version);
  1732. switch ($mode) {
  1733. case QR_MODE_NM:
  1734. $chunks = (int) ($payload / 10);
  1735. $remain = $payload - $chunks * 10;
  1736. $size = $chunks * 3;
  1737. if (7 <= $remain) {
  1738. $size += 2;
  1739. }
  1740. else if (4 <= $remain) {
  1741. $size += 1;
  1742. }
  1743. break;
  1744. case QR_MODE_AN:
  1745. $chunks = (int) ($payload / 11);
  1746. $remain = $payload - $chunks * 11;
  1747. $size = $chunks * 2;
  1748. if (6 <= $remain) {
  1749. ++$size;
  1750. }
  1751. break;
  1752. case QR_MODE_8B:
  1753. $size = (int) ($payload / 8);
  1754. break;
  1755. case QR_MODE_KJ:
  1756. $size = (int) ($payload / 13 * 2);
  1757. break;
  1758. case QR_MODE_ST:
  1759. $size = (int) ($payload / 8);
  1760. break;
  1761. default:
  1762. $size = 0;
  1763. break;
  1764. }
  1765. $maxsize = $this->maximumWords($mode, $version);
  1766. if ($size < 0) {
  1767. $size = 0;
  1768. }
  1769. if ($maxsize < $size) {
  1770. $size = $maxsize;
  1771. }
  1772. return $size;
  1773. }
  1774. protected function createBitStream($items)
  1775. {
  1776. $total = 0;
  1777. foreach ($items as $key => $item) {
  1778. $items[$key] = $this->encodeBitStream($item, $this->version);
  1779. $bits = count($items[$key]['bstream']);
  1780. $total += $bits;
  1781. }
  1782. return array($items, $total);
  1783. }
  1784. protected function convertData($items)
  1785. {
  1786. $ver = $this->estimateVersion($items);
  1787. if ($this->version < $ver) {
  1788. $this->version = $ver;
  1789. }
  1790. for (; ; ) {
  1791. $cbs = $this->createBitStream($items);
  1792. $items = $cbs[0];
  1793. $bits = $cbs[1];
  1794. if ($bits < 0) {
  1795. return -1;
  1796. }
  1797. $ver = $this->getMinimumVersion((int) (($bits + 7) / 8), $this->level);
  1798. if ($ver < 0) {
  1799. return -1;
  1800. }
  1801. else if ($this->version < $ver) {
  1802. $this->version = $ver;
  1803. }
  1804. else {
  1805. break;
  1806. }
  1807. }
  1808. return $items;
  1809. }
  1810. protected function appendPaddingBit($bstream)
  1811. {
  1812. $bits = count($bstream);
  1813. $maxwords = $this->getDataLength($this->version, $this->level);
  1814. $maxbits = $maxwords * 8;
  1815. if ($maxbits == $bits) {
  1816. return 0;
  1817. }
  1818. if ($maxbits - $bits < 5) {
  1819. return $this->appendNum($bstream, $maxbits - $bits, 0);
  1820. }
  1821. $bits += 4;
  1822. $words = (int) (($bits + 7) / 8);
  1823. $padding = array();
  1824. $padding = $this->appendNum($padding, $words * 8 - $bits + 4, 0);
  1825. $padlen = $maxwords - $words;
  1826. if (0 < $padlen) {
  1827. $padbuf = array();
  1828. for ($i = 0; $i < $padlen; ++$i) {
  1829. $padbuf[$i] = $i & 1 ? 17 : 236;
  1830. }
  1831. $padding = $this->appendBytes($padding, $padlen, $padbuf);
  1832. }
  1833. return $this->appendBitstream($bstream, $padding);
  1834. }
  1835. protected function mergeBitStream($items)
  1836. {
  1837. $items = $this->convertData($items);
  1838. $bstream = array();
  1839. foreach ($items as $item) {
  1840. $bstream = $this->appendBitstream($bstream, $item['bstream']);
  1841. }
  1842. return $bstream;
  1843. }
  1844. protected function getBitStream($items)
  1845. {
  1846. $bstream = $this->mergeBitStream($items);
  1847. return $this->appendPaddingBit($bstream);
  1848. }
  1849. protected function getByteStream($items)
  1850. {
  1851. $bstream = $this->getBitStream($items);
  1852. return $this->bitstreamToByte($bstream);
  1853. }
  1854. protected function allocate($setLength)
  1855. {
  1856. return array_fill(0, $setLength, 0);
  1857. }
  1858. protected function newFromNum($bits, $num)
  1859. {
  1860. $bstream = $this->allocate($bits);
  1861. $mask = 1 << $bits - 1;
  1862. for ($i = 0; $i < $bits; ++$i) {
  1863. if ($num & $mask) {
  1864. $bstream[$i] = 1;
  1865. }
  1866. else {
  1867. $bstream[$i] = 0;
  1868. }
  1869. $mask = $mask >> 1;
  1870. }
  1871. return $bstream;
  1872. }
  1873. protected function newFromBytes($size, $data)
  1874. {
  1875. $bstream = $this->allocate($size * 8);
  1876. $p = 0;
  1877. for ($i = 0; $i < $size; ++$i) {
  1878. $mask = 128;
  1879. for ($j = 0; $j < 8; ++$j) {
  1880. if ($data[$i] & $mask) {
  1881. $bstream[$p] = 1;
  1882. }
  1883. else {
  1884. $bstream[$p] = 0;
  1885. }
  1886. $p++;
  1887. $mask = $mask >> 1;
  1888. }
  1889. }
  1890. return $bstream;
  1891. }
  1892. protected function appendBitstream($bitstream, $append)
  1893. {
  1894. if (!is_array($append) || count($append) == 0) {
  1895. return $bitstream;
  1896. }
  1897. if (count($bitstream) == 0) {
  1898. return $append;
  1899. }
  1900. return array_values(array_merge($bitstream, $append));
  1901. }
  1902. protected function appendNum($bitstream, $bits, $num)
  1903. {
  1904. if ($bits == 0) {
  1905. return 0;
  1906. }
  1907. $b = $this->newFromNum($bits, $num);
  1908. return $this->appendBitstream($bitstream, $b);
  1909. }
  1910. protected function appendBytes($bitstream, $size, $data)
  1911. {
  1912. if ($size == 0) {
  1913. return 0;
  1914. }
  1915. $b = $this->newFromBytes($size, $data);
  1916. return $this->appendBitstream($bitstream, $b);
  1917. }
  1918. protected function bitstreamToByte($bstream)
  1919. {
  1920. $size = count($bstream);
  1921. if ($size == 0) {
  1922. return array();
  1923. }
  1924. $data = array_fill(0, (int) (($size + 7) / 8), 0);
  1925. $bytes = (int) ($size / 8);
  1926. $p = 0;
  1927. for ($i = 0; $i < $bytes; $i++) {
  1928. $v = 0;
  1929. for ($j = 0; $j < 8; $j++) {
  1930. $v = $v << 1;
  1931. $v |= $bstream[$p];
  1932. $p++;
  1933. }
  1934. $data[$i] = $v;
  1935. }
  1936. if ($size & 7) {
  1937. $v = 0;
  1938. for ($j = 0; $j < ($size & 7); $j++) {
  1939. $v = $v << 1;
  1940. $v |= $bstream[$p];
  1941. $p++;
  1942. }
  1943. $data[$bytes] = $v;
  1944. }
  1945. return $data;
  1946. }
  1947. protected function qrstrset($srctab, $x, $y, $repl, $replLen = false)
  1948. {
  1949. $srctab[$y] = substr_replace($srctab[$y], $replLen !== false ? substr($repl, 0, $replLen) : $repl, $x, $replLen !== false ? $replLen : strlen($repl));
  1950. return $srctab;
  1951. }
  1952. protected function getDataLength($version, $level)
  1953. {
  1954. return $this->capacity[$version][QRCAP_WORDS] - $this->capacity[$version][QRCAP_EC][$level];
  1955. }
  1956. protected function getECCLength($version, $level)
  1957. {
  1958. return $this->capacity[$version][QRCAP_EC][$level];
  1959. }
  1960. protected function getWidth($version)
  1961. {
  1962. return $this->capacity[$version][QRCAP_WIDTH];
  1963. }
  1964. protected function getRemainder($version)
  1965. {
  1966. return $this->capacity[$version][QRCAP_REMINDER];
  1967. }
  1968. protected function getMinimumVersion($size, $level)
  1969. {
  1970. for ($i = 1; $i <= QRSPEC_VERSION_MAX; ++$i) {
  1971. $words = $this->capacity[$i][QRCAP_WORDS] - $this->capacity[$i][QRCAP_EC][$level];
  1972. if ($size <= $words) {
  1973. return $i;
  1974. }
  1975. }
  1976. return -1;
  1977. }
  1978. protected function lengthIndicator($mode, $version)
  1979. {
  1980. if ($mode == QR_MODE_ST) {
  1981. return 0;
  1982. }
  1983. if ($version <= 9) {
  1984. $l = 0;
  1985. }
  1986. else if ($version <= 26) {
  1987. $l = 1;
  1988. }
  1989. else {
  1990. $l = 2;
  1991. }
  1992. return $this->lengthTableBits[$mode][$l];
  1993. }
  1994. protected function maximumWords($mode, $version)
  1995. {
  1996. if ($mode == QR_MODE_ST) {
  1997. return 3;
  1998. }
  1999. if ($version <= 9) {
  2000. $l = 0;
  2001. }
  2002. else if ($version <= 26) {
  2003. $l = 1;
  2004. }
  2005. else {
  2006. $l = 2;
  2007. }
  2008. $bits = $this->lengthTableBits[$mode][$l];
  2009. $words = (1 << $bits) - 1;
  2010. if ($mode == QR_MODE_KJ) {
  2011. $words *= 2;
  2012. }
  2013. return $words;
  2014. }
  2015. protected function getEccSpec($version, $level, $spec)
  2016. {
  2017. if (count($spec) < 5) {
  2018. $spec = array(0, 0, 0, 0, 0);
  2019. }
  2020. $b1 = $this->eccTable[$version][$level][0];
  2021. $b2 = $this->eccTable[$version][$level][1];
  2022. $data = $this->getDataLength($version, $level);
  2023. $ecc = $this->getECCLength($version, $level);
  2024. if ($b2 == 0) {
  2025. $spec[0] = $b1;
  2026. $spec[1] = (int) ($data / $b1);
  2027. $spec[2] = (int) ($ecc / $b1);
  2028. $spec[3] = 0;
  2029. $spec[4] = 0;
  2030. }
  2031. else {
  2032. $spec[0] = $b1;
  2033. $spec[1] = (int) ($data / ($b1 + $b2));
  2034. $spec[2] = (int) ($ecc / ($b1 + $b2));
  2035. $spec[3] = $b2;
  2036. $spec[4] = $spec[1] + 1;
  2037. }
  2038. return $spec;
  2039. }
  2040. protected function putAlignmentMarker($frame, $ox, $oy)
  2041. {
  2042. $finder = array("\xa1\xa1\xa1\xa1\xa1", "\xa1\xa0\xa0\xa0\xa1", "\xa1\xa0\xa1\xa0\xa1", "\xa1\xa0\xa0\xa0\xa1", "\xa1\xa1\xa1\xa1\xa1");
  2043. $yStart = $oy - 2;
  2044. $xStart = $ox - 2;
  2045. for ($y = 0; $y < 5; $y++) {
  2046. $frame = $this->qrstrset($frame, $xStart, $yStart + $y, $finder[$y]);
  2047. }
  2048. return $frame;
  2049. }
  2050. protected function putAlignmentPattern($version, $frame, $width)
  2051. {
  2052. if ($version < 2) {
  2053. return $frame;
  2054. }
  2055. $d = $this->alignmentPattern[$version][1] - $this->alignmentPattern[$version][0];
  2056. if ($d < 0) {
  2057. $w = 2;
  2058. }
  2059. else {
  2060. $w = (int) (($width - $this->alignmentPattern[$version][0]) / $d + 2);
  2061. }
  2062. if ($w * $w - 3 == 1) {
  2063. $x = $this->alignmentPattern[$version][0];
  2064. $y = $this->alignmentPattern[$version][0];
  2065. $frame = $this->putAlignmentMarker($frame, $x, $y);
  2066. return $frame;
  2067. }
  2068. $cx = $this->alignmentPattern[$version][0];
  2069. $wo = $w - 1;
  2070. for ($x = 1; $x < $wo; ++$x) {
  2071. $frame = $this->putAlignmentMarker($frame, 6, $cx);
  2072. $frame = $this->putAlignmentMarker($frame, $cx, 6);
  2073. $cx += $d;
  2074. }
  2075. $cy = $this->alignmentPattern[$version][0];
  2076. for ($y = 0; $y < $wo; ++$y) {
  2077. $cx = $this->alignmentPattern[$version][0];
  2078. for ($x = 0; $x < $wo; ++$x) {
  2079. $frame = $this->putAlignmentMarker($frame, $cx, $cy);
  2080. $cx += $d;
  2081. }
  2082. $cy += $d;
  2083. }
  2084. return $frame;
  2085. }
  2086. protected function getVersionPattern($version)
  2087. {
  2088. if ($version < 7 || QRSPEC_VERSION_MAX < $version) {
  2089. return 0;
  2090. }
  2091. return $this->versionPattern[$version - 7];
  2092. }
  2093. protected function getFormatInfo($mask, $level)
  2094. {
  2095. if ($mask < 0 || 7 < $mask) {
  2096. return 0;
  2097. }
  2098. if ($level < 0 || 3 < $level) {
  2099. return 0;
  2100. }
  2101. return $this->formatInfo[$level][$mask];
  2102. }
  2103. protected function putFinderPattern($frame, $ox, $oy)
  2104. {
  2105. $finder = array("\xc1\xc1\xc1\xc1\xc1\xc1\xc1", "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", "\xc1\xc1\xc1\xc1\xc1\xc1\xc1");
  2106. for ($y = 0; $y < 7; $y++) {
  2107. $frame = $this->qrstrset($frame, $ox, $oy + $y, $finder[$y]);
  2108. }
  2109. return $frame;
  2110. }
  2111. protected function createFrame($version)
  2112. {
  2113. $width = $this->capacity[$version][QRCAP_WIDTH];
  2114. $frameLine = str_repeat('', $width);
  2115. $frame = array_fill(0, $width, $frameLine);
  2116. $frame = $this->putFinderPattern($frame, 0, 0);
  2117. $frame = $this->putFinderPattern($frame, $width - 7, 0);
  2118. $frame = $this->putFinderPattern($frame, 0, $width - 7);
  2119. $yOffset = $width - 7;
  2120. for ($y = 0; $y < 7; ++$y) {
  2121. $frame[$y][7] = "\xc0";
  2122. $frame[$y][$width - 8] = "\xc0";
  2123. $frame[$yOffset][7] = "\xc0";
  2124. ++$yOffset;
  2125. }
  2126. $setPattern = str_repeat("\xc0", 8);
  2127. $frame = $this->qrstrset($frame, 0, 7, $setPattern);
  2128. $frame = $this->qrstrset($frame, $width - 8, 7, $setPattern);
  2129. $frame = $this->qrstrset($frame, 0, $width - 8, $setPattern);
  2130. $setPattern = str_repeat("\x84", 9);
  2131. $frame = $this->qrstrset($frame, 0, 8, $setPattern);
  2132. $frame = $this->qrstrset($frame, $width - 8, 8, $setPattern, 8);
  2133. $yOffset = $width - 8;
  2134. for ($y = 0; $y < 8; ++$y, ++$yOffset) {
  2135. $frame[$y][8] = "\x84";
  2136. $frame[$yOffset][8] = "\x84";
  2137. }
  2138. $wo = $width - 15;
  2139. for ($i = 1; $i < $wo; ++$i) {
  2140. $frame[6][7 + $i] = chr(144 | $i & 1);
  2141. $frame[7 + $i][6] = chr(144 | $i & 1);
  2142. }
  2143. $frame = $this->putAlignmentPattern($version, $frame, $width);
  2144. if (7 <= $version) {
  2145. $vinf = $this->getVersionPattern($version);
  2146. $v = $vinf;
  2147. for ($x = 0; $x < 6; ++$x) {
  2148. for ($y = 0; $y < 3; ++$y) {
  2149. $frame[$width - 11 + $y][$x] = chr(136 | $v & 1);
  2150. $v = $v >> 1;
  2151. }
  2152. }
  2153. $v = $vinf;
  2154. for ($y = 0; $y < 6; ++$y) {
  2155. for ($x = 0; $x < 3; ++$x) {
  2156. $frame[$y][$x + ($width - 11)] = chr(136 | $v & 1);
  2157. $v = $v >> 1;
  2158. }
  2159. }
  2160. }
  2161. $frame[$width - 8][8] = "\x81";
  2162. return $frame;
  2163. }
  2164. protected function newFrame($version)
  2165. {
  2166. if ($version < 1 || QRSPEC_VERSION_MAX < $version) {
  2167. return NULL;
  2168. }
  2169. if (!isset($this->frames[$version])) {
  2170. $this->frames[$version] = $this->createFrame($version);
  2171. }
  2172. if (is_null($this->frames[$version])) {
  2173. return NULL;
  2174. }
  2175. return $this->frames[$version];
  2176. }
  2177. protected function rsBlockNum($spec)
  2178. {
  2179. return $spec[0] + $spec[3];
  2180. }
  2181. protected function rsBlockNum1($spec)
  2182. {
  2183. return $spec[0];
  2184. }
  2185. protected function rsDataCodes1($spec)
  2186. {
  2187. return $spec[1];
  2188. }
  2189. protected function rsEccCodes1($spec)
  2190. {
  2191. return $spec[2];
  2192. }
  2193. protected function rsBlockNum2($spec)
  2194. {
  2195. return $spec[3];
  2196. }
  2197. protected function rsDataCodes2($spec)
  2198. {
  2199. return $spec[4];
  2200. }
  2201. protected function rsEccCodes2($spec)
  2202. {
  2203. return $spec[2];
  2204. }
  2205. protected function rsDataLength($spec)
  2206. {
  2207. return $spec[0] * $spec[1] + $spec[3] * $spec[4];
  2208. }
  2209. protected function rsEccLength($spec)
  2210. {
  2211. return ($spec[0] + $spec[3]) * $spec[2];
  2212. }
  2213. protected function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
  2214. {
  2215. foreach ($this->rsitems as $rs) {
  2216. if ($rs['pad'] != $pad || $rs['nroots'] != $nroots || $rs['mm'] != $symsize || $rs['gfpoly'] != $gfpoly || $rs['fcr'] != $fcr || $rs['prim'] != $prim) {
  2217. continue;
  2218. }
  2219. return $rs;
  2220. }
  2221. $rs = $this->init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
  2222. array_unshift($this->rsitems, $rs);
  2223. return $rs;
  2224. }
  2225. protected function modnn($rs, $x)
  2226. {
  2227. while ($rs['nn'] <= $x) {
  2228. $x -= $rs['nn'];
  2229. $x = ($x >> $rs['mm']) + ($x & $rs['nn']);
  2230. }
  2231. return $x;
  2232. }
  2233. protected function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
  2234. {
  2235. $rs = NULL;
  2236. if ($symsize < 0 || 8 < $symsize) {
  2237. return $rs;
  2238. }
  2239. if ($fcr < 0 || 1 << $symsize <= $fcr) {
  2240. return $rs;
  2241. }
  2242. if ($prim <= 0 || 1 << $symsize <= $prim) {
  2243. return $rs;
  2244. }
  2245. if ($nroots < 0 || 1 << $symsize <= $nroots) {
  2246. return $rs;
  2247. }
  2248. if ($pad < 0 || (1 << $symsize) - 1 - $nroots <= $pad) {
  2249. return $rs;
  2250. }
  2251. $rs = array();
  2252. $rs['mm'] = $symsize;
  2253. $rs['nn'] = (1 << $symsize) - 1;
  2254. $rs['pad'] = $pad;
  2255. $rs['alpha_to'] = array_fill(0, $rs['nn'] + 1, 0);
  2256. $rs['index_of'] = array_fill(0, $rs['nn'] + 1, 0);
  2257. $NN = &$rs['nn'];
  2258. $A0 = &$NN;
  2259. $rs['index_of'][0] = $A0;
  2260. $rs['alpha_to'][$A0] = 0;
  2261. $sr = 1;
  2262. for ($i = 0; $i < $rs['nn']; ++$i) {
  2263. $rs['index_of'][$sr] = $i;
  2264. $rs['alpha_to'][$i] = $sr;
  2265. $sr <<= 1;
  2266. if ($sr & 1 << $symsize) {
  2267. $sr ^= $gfpoly;
  2268. }
  2269. $sr &= $rs['nn'];
  2270. }
  2271. if ($sr != 1) {
  2272. return NULL;
  2273. }
  2274. $rs['genpoly'] = array_fill(0, $nroots + 1, 0);
  2275. $rs['fcr'] = $fcr;
  2276. $rs['prim'] = $prim;
  2277. $rs['nroots'] = $nroots;
  2278. $rs['gfpoly'] = $gfpoly;
  2279. for ($iprim = 1; $iprim % $prim != 0; $iprim += $rs['nn']) {
  2280. }
  2281. $rs['iprim'] = (int) ($iprim / $prim);
  2282. $rs['genpoly'][0] = 1;
  2283. $i = 0;
  2284. for ($root = $fcr * $prim; $i < $nroots; $i++, $root += $prim) {
  2285. $rs['genpoly'][$i + 1] = 1;
  2286. for ($j = $i; 0 < $j; --$j) {
  2287. if ($rs['genpoly'][$j] != 0) {
  2288. $rs['genpoly'][$j] = $rs['genpoly'][$j - 1] ^ $rs['alpha_to'][$this->modnn($rs, $rs['index_of'][$rs['genpoly'][$j]] + $root)];
  2289. }
  2290. else {
  2291. $rs['genpoly'][$j] = $rs['genpoly'][$j - 1];
  2292. }
  2293. }
  2294. $rs['genpoly'][0] = $rs['alpha_to'][$this->modnn($rs, $rs['index_of'][$rs['genpoly'][0]] + $root)];
  2295. }
  2296. for ($i = 0; $i <= $nroots; ++$i) {
  2297. $rs['genpoly'][$i] = $rs['index_of'][$rs['genpoly'][$i]];
  2298. }
  2299. return $rs;
  2300. }
  2301. protected function encode_rs_char($rs, $data, $parity)
  2302. {
  2303. $MM = &$rs['mm'];
  2304. $NN = &$rs['nn'];
  2305. $ALPHA_TO = &$rs['alpha_to'];
  2306. $INDEX_OF = &$rs['index_of'];
  2307. $GENPOLY = &$rs['genpoly'];
  2308. $NROOTS = &$rs['nroots'];
  2309. $FCR = &$rs['fcr'];
  2310. $PRIM = &$rs['prim'];
  2311. $IPRIM = &$rs['iprim'];
  2312. $PAD = &$rs['pad'];
  2313. $A0 = &$NN;
  2314. $parity = array_fill(0, $NROOTS, 0);
  2315. for ($i = 0; $i < $NN - $NROOTS - $PAD; $i++) {
  2316. $feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
  2317. if ($feedback != $A0) {
  2318. $feedback = $this->modnn($rs, $NN - $GENPOLY[$NROOTS] + $feedback);
  2319. for ($j = 1; $j < $NROOTS; ++$j) {
  2320. $parity[$j] ^= $ALPHA_TO[$this->modnn($rs, $feedback + $GENPOLY[$NROOTS - $j])];
  2321. }
  2322. }
  2323. array_shift($parity);
  2324. if ($feedback != $A0) {
  2325. array_push($parity, $ALPHA_TO[$this->modnn($rs, $feedback + $GENPOLY[0])]);
  2326. }
  2327. else {
  2328. array_push($parity, 0);
  2329. }
  2330. }
  2331. return $parity;
  2332. }
  2333. }
  2334. }
  2335. ?>