qrcode.php 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
  1. <?php
  2. //---------------------------------------------------------------
  3. // QRCode for PHP4
  4. //
  5. // Copyright (c) 2009 Kazuhiko Arase
  6. //
  7. // URL: http://www.d-project.com/
  8. //
  9. // Licensed under the MIT license:
  10. // http://www.opensource.org/licenses/mit-license.php
  11. //
  12. // The word "QR Code" is registered trademark of
  13. // DENSO WAVE INCORPORATED
  14. // http://www.denso-wave.com/qrcode/faqpatent-e.html
  15. //
  16. //---------------------------------------------------------------------
  17. //---------------------------------------------------------------
  18. // QRCode
  19. //---------------------------------------------------------------
  20. define("QR_PAD0", 0xEC);
  21. define("QR_PAD1", 0x11);
  22. class QRCode {
  23. var $typeNumber;
  24. var $modules;
  25. var $moduleCount;
  26. var $errorCorrectLevel;
  27. var $qrDataList;
  28. function QRCode() {
  29. $this->typeNumber = 1;
  30. $this->errorCorrectLevel = QR_ERROR_CORRECT_LEVEL_H;
  31. $this->qrDataList = array();
  32. }
  33. function getTypeNumber() {
  34. return $this->typeNumber;
  35. }
  36. function setTypeNumber($typeNumber) {
  37. $this->typeNumber = $typeNumber;
  38. }
  39. function getErrorCorrectLevel() {
  40. return $this->errorCorrectLevel;
  41. }
  42. function setErrorCorrectLevel($errorCorrectLevel) {
  43. $this->errorCorrectLevel = $errorCorrectLevel;
  44. }
  45. function addData($data, $mode = 0) {
  46. if ($mode == 0) {
  47. $mode = QRUtil::getMode($data);
  48. }
  49. switch($mode) {
  50. case QR_MODE_NUMBER :
  51. $this->addDataImpl(new QRNumber($data) );
  52. break;
  53. case QR_MODE_ALPHA_NUM :
  54. $this->addDataImpl(new QRAlphaNum($data) );
  55. break;
  56. case QR_MODE_8BIT_BYTE :
  57. $this->addDataImpl(new QR8BitByte($data) );
  58. break;
  59. case QR_MODE_KANJI :
  60. $this->addDataImpl(new QRKanji($data) );
  61. break;
  62. default :
  63. trigger_error("mode:$mode", E_USER_ERROR);
  64. }
  65. }
  66. function clearData() {
  67. $qrDataList = array();
  68. }
  69. function addDataImpl(&$qrData) {
  70. $this->qrDataList[] = $qrData;
  71. }
  72. function getDataCount() {
  73. return count($this->qrDataList);
  74. }
  75. function getData($index) {
  76. return $this->qrDataList[$index];
  77. }
  78. function isDark($row, $col) {
  79. if ($this->modules[$row][$col] !== null) {
  80. return $this->modules[$row][$col];
  81. } else {
  82. return false;
  83. }
  84. }
  85. function getModuleCount() {
  86. return $this->moduleCount;
  87. }
  88. function make() {
  89. $this->makeImpl(false, $this->getBestMaskPattern() );
  90. }
  91. function getBestMaskPattern() {
  92. $minLostPoint = 0;
  93. $pattern = 0;
  94. for ($i = 0; $i < 8; $i++) {
  95. $this->makeImpl(true, $i);
  96. $lostPoint = QRUtil::getLostPoint($this);
  97. if ($i == 0 || $minLostPoint > $lostPoint) {
  98. $minLostPoint = $lostPoint;
  99. $pattern = $i;
  100. }
  101. }
  102. return $pattern;
  103. }
  104. function createNullArray($length) {
  105. $nullArray = array();
  106. for ($i = 0; $i < $length; $i++) {
  107. $nullArray[] = null;
  108. }
  109. return $nullArray;
  110. }
  111. function makeImpl($test, $maskPattern) {
  112. $this->moduleCount = $this->typeNumber * 4 + 17;
  113. $this->modules = array();
  114. for ($i = 0; $i < $this->moduleCount; $i++) {
  115. $this->modules[] = QRCode::createNullArray($this->moduleCount);
  116. }
  117. $this->setupPositionProbePattern(0, 0);
  118. $this->setupPositionProbePattern($this->moduleCount - 7, 0);
  119. $this->setupPositionProbePattern(0, $this->moduleCount - 7);
  120. $this->setupPositionAdjustPattern();
  121. $this->setupTimingPattern();
  122. $this->setupTypeInfo($test, $maskPattern);
  123. if ($this->typeNumber >= 7) {
  124. $this->setupTypeNumber($test);
  125. }
  126. $dataArray = $this->qrDataList;
  127. $data = QRCode::createData($this->typeNumber, $this->errorCorrectLevel, $dataArray);
  128. $this->mapData($data, $maskPattern);
  129. }
  130. function mapData(&$data, $maskPattern) {
  131. $inc = -1;
  132. $row = $this->moduleCount - 1;
  133. $bitIndex = 7;
  134. $byteIndex = 0;
  135. for ($col = $this->moduleCount - 1; $col > 0; $col -= 2) {
  136. if ($col == 6) $col--;
  137. while (true) {
  138. for ($c = 0; $c < 2; $c++) {
  139. if ($this->modules[$row][$col - $c] === null) {
  140. $dark = false;
  141. if ($byteIndex < count($data) ) {
  142. $dark = ( ( ($data[$byteIndex] >> $bitIndex) & 1) == 1);
  143. }
  144. $mask = QRUtil::getMask($maskPattern, $row, $col - $c);
  145. if ($mask) {
  146. $dark = !$dark;
  147. }
  148. $this->modules[$row][$col - $c] = $dark;
  149. $bitIndex--;
  150. if ($bitIndex == -1) {
  151. $byteIndex++;
  152. $bitIndex = 7;
  153. }
  154. }
  155. }
  156. $row += $inc;
  157. if ($row < 0 || $this->moduleCount <= $row) {
  158. $row -= $inc;
  159. $inc = -$inc;
  160. break;
  161. }
  162. }
  163. }
  164. }
  165. function setupPositionAdjustPattern() {
  166. $pos = QRUtil::getPatternPosition($this->typeNumber);
  167. for ($i = 0; $i < count($pos); $i++) {
  168. for ($j = 0; $j < count($pos); $j++) {
  169. $row = $pos[$i];
  170. $col = $pos[$j];
  171. if ($this->modules[$row][$col] !== null) {
  172. continue;
  173. }
  174. for ($r = -2; $r <= 2; $r++) {
  175. for ($c = -2; $c <= 2; $c++) {
  176. if ($r == -2 || $r == 2 || $c == -2 || $c == 2
  177. || ($r == 0 && $c == 0) ) {
  178. $this->modules[$row + $r][$col + $c] = true;
  179. } else {
  180. $this->modules[$row + $r][$col + $c] = false;
  181. }
  182. }
  183. }
  184. }
  185. }
  186. }
  187. function setupPositionProbePattern($row, $col) {
  188. for ($r = -1; $r <= 7; $r++) {
  189. for ($c = -1; $c <= 7; $c++) {
  190. if ($row + $r <= -1 || $this->moduleCount <= $row + $r
  191. || $col + $c <= -1 || $this->moduleCount <= $col + $c) {
  192. continue;
  193. }
  194. if ( (0 <= $r && $r <= 6 && ($c == 0 || $c == 6) )
  195. || (0 <= $c && $c <= 6 && ($r == 0 || $r == 6) )
  196. || (2 <= $r && $r <= 4 && 2 <= $c && $c <= 4) ) {
  197. $this->modules[$row + $r][$col + $c] = true;
  198. } else {
  199. $this->modules[$row + $r][$col + $c] = false;
  200. }
  201. }
  202. }
  203. }
  204. function setupTimingPattern() {
  205. for ($r = 8; $r < $this->moduleCount - 8; $r++) {
  206. if ($this->modules[$r][6] !== null) {
  207. continue;
  208. }
  209. $this->modules[$r][6] = ($r % 2 == 0);
  210. }
  211. for ($c = 8; $c < $this->moduleCount - 8; $c++) {
  212. if ($this->modules[6][$c] !== null) {
  213. continue;
  214. }
  215. $this->modules[6][$c] = ($c % 2 == 0);
  216. }
  217. }
  218. function setupTypeNumber($test) {
  219. $bits = QRUtil::getBCHTypeNumber($this->typeNumber);
  220. for ($i = 0; $i < 18; $i++) {
  221. $mod = (!$test && ( ($bits >> $i) & 1) == 1);
  222. $this->modules[floor($i / 3)][$i % 3 + $this->moduleCount - 8 - 3] = $mod;
  223. }
  224. for ($i = 0; $i < 18; $i++) {
  225. $mod = (!$test && ( ($bits >> $i) & 1) == 1);
  226. $this->modules[$i % 3 + $this->moduleCount - 8 - 3][floor($i / 3)] = $mod;
  227. }
  228. }
  229. function setupTypeInfo($test, $maskPattern) {
  230. $data = ($this->errorCorrectLevel << 3) | $maskPattern;
  231. $bits = QRUtil::getBCHTypeInfo($data);
  232. for ($i = 0; $i < 15; $i++) {
  233. $mod = (!$test && ( ($bits >> $i) & 1) == 1);
  234. if ($i < 6) {
  235. $this->modules[$i][8] = $mod;
  236. } else if ($i < 8) {
  237. $this->modules[$i + 1][8] = $mod;
  238. } else {
  239. $this->modules[$this->moduleCount - 15 + $i][8] = $mod;
  240. }
  241. }
  242. for ($i = 0; $i < 15; $i++) {
  243. $mod = (!$test && ( ($bits >> $i) & 1) == 1);
  244. if ($i < 8) {
  245. $this->modules[8][$this->moduleCount - $i - 1] = $mod;
  246. } else if ($i < 9) {
  247. $this->modules[8][15 - $i - 1 + 1] = $mod;
  248. } else {
  249. $this->modules[8][15 - $i - 1] = $mod;
  250. }
  251. }
  252. $this->modules[$this->moduleCount - 8][8] = !$test;
  253. }
  254. function createData($typeNumber, $errorCorrectLevel, $dataArray) {
  255. $rsBlocks = QRRSBlock::getRSBlocks($typeNumber, $errorCorrectLevel);
  256. $buffer = new QRBitBuffer();
  257. for ($i = 0; $i < count($dataArray); $i++) {
  258. $data = $dataArray[$i];
  259. $buffer->put($data->getMode(), 4);
  260. $buffer->put($data->getLength(), $data->getLengthInBits($typeNumber) );
  261. $data->write($buffer);
  262. }
  263. $totalDataCount = 0;
  264. for ($i = 0; $i < count($rsBlocks); $i++) {
  265. $totalDataCount += $rsBlocks[$i]->getDataCount();
  266. }
  267. /*
  268. if ($buffer->getLengthInBits() > $totalDataCount * 8) {
  269. trigger_error("code length overflow. ("
  270. . $buffer->getLengthInBits()
  271. . ">"
  272. . $totalDataCount * 8
  273. . ")", E_USER_ERROR);
  274. }
  275. */
  276. // end code.
  277. if ($buffer->getLengthInBits() + 4 <= $totalDataCount * 8) {
  278. $buffer->put(0, 4);
  279. }
  280. // padding
  281. while ($buffer->getLengthInBits() % 8 != 0) {
  282. $buffer->putBit(false);
  283. }
  284. // padding
  285. while (true) {
  286. if ($buffer->getLengthInBits() >= $totalDataCount * 8) {
  287. break;
  288. }
  289. $buffer->put(QR_PAD0, 8);
  290. if ($buffer->getLengthInBits() >= $totalDataCount * 8) {
  291. break;
  292. }
  293. $buffer->put(QR_PAD1, 8);
  294. }
  295. return QRCode::createBytes($buffer, $rsBlocks);
  296. }
  297. function createBytes(&$buffer, &$rsBlocks) {
  298. $offset = 0;
  299. $maxDcCount = 0;
  300. $maxEcCount = 0;
  301. $dcdata = QRCode::createNullArray(count($rsBlocks) );
  302. $ecdata = QRCode::createNullArray(count($rsBlocks) );
  303. for ($r = 0; $r < count($rsBlocks); $r++) {
  304. $dcCount = $rsBlocks[$r]->getDataCount();
  305. $ecCount = $rsBlocks[$r]->getTotalCount() - $dcCount;
  306. $maxDcCount = max($maxDcCount, $dcCount);
  307. $maxEcCount = max($maxEcCount, $ecCount);
  308. $dcdata[$r] = QRCode::createNullArray($dcCount);
  309. for ($i = 0; $i < count($dcdata[$r]); $i++) {
  310. $bdata = $buffer->getBuffer();
  311. $dcdata[$r][$i] = 0xff & $bdata[$i + $offset];
  312. }
  313. $offset += $dcCount;
  314. $rsPoly = QRUtil::getErrorCorrectPolynomial($ecCount);
  315. $rawPoly = new QRPolynomial($dcdata[$r], $rsPoly->getLength() - 1);
  316. $modPoly = $rawPoly->mod($rsPoly);
  317. $ecdata[$r] = QRCode::createNullArray($rsPoly->getLength() - 1);
  318. for ($i = 0; $i < count($ecdata[$r]); $i++) {
  319. $modIndex = $i + $modPoly->getLength() - count($ecdata[$r]);
  320. $ecdata[$r][$i] = ($modIndex >= 0)? $modPoly->get($modIndex) : 0;
  321. }
  322. }
  323. $totalCodeCount = 0;
  324. for ($i = 0; $i < count($rsBlocks); $i++) {
  325. $totalCodeCount += $rsBlocks[$i]->getTotalCount();
  326. }
  327. $data = QRCode::createNullArray($totalCodeCount);
  328. $index = 0;
  329. for ($i = 0; $i < $maxDcCount; $i++) {
  330. for ($r = 0; $r < count($rsBlocks); $r++) {
  331. if ($i < count($dcdata[$r]) ) {
  332. $data[$index++] = $dcdata[$r][$i];
  333. }
  334. }
  335. }
  336. for ($i = 0; $i < $maxEcCount; $i++) {
  337. for ($r = 0; $r < count($rsBlocks); $r++) {
  338. if ($i < count($ecdata[$r]) ) {
  339. $data[$index++] = $ecdata[$r][$i];
  340. }
  341. }
  342. }
  343. return $data;
  344. }
  345. function getMinimumQRCode($data, $errorCorrectLevel) {
  346. $mode = QRUtil::getMode($data);
  347. $qr = new QRCode();
  348. $qr->setErrorCorrectLevel($errorCorrectLevel);
  349. $qr->addData($data, $mode);
  350. $qrData = $qr->getData(0);
  351. $length = $qrData->getLength();
  352. for ($typeNumber = 1; $typeNumber <= 10; $typeNumber++) {
  353. if ($length <= QRUtil::getMaxLength($typeNumber, $mode, $errorCorrectLevel) ) {
  354. $qr->setTypeNumber($typeNumber);
  355. break;
  356. }
  357. }
  358. $qr->make();
  359. return $qr;
  360. }
  361. function createImage($size = 2, $margin = 2) {
  362. $image_size = $this->getModuleCount() * $size + $margin * 2;
  363. $image = imagecreatetruecolor($image_size, $image_size);
  364. $black = imagecolorallocate($image, 0, 0, 0);
  365. $white = imagecolorallocate($image, 255, 255, 255);
  366. imagefilledrectangle($image, 0, 0, $image_size, $image_size, $white);
  367. for ($r = 0; $r < $this->getModuleCount(); $r++) {
  368. for ($c = 0; $c < $this->getModuleCount(); $c++) {
  369. if ($this->isDark($r, $c) ) {
  370. imagefilledrectangle($image,
  371. $margin + $c * $size,
  372. $margin + $r * $size,
  373. $margin + ($c + 1) * $size - 1,
  374. $margin + ($r + 1) * $size - 1,
  375. $black);
  376. }
  377. }
  378. }
  379. return $image;
  380. }
  381. function printHTML($size = "2px") {
  382. $style = "border-style:none;border-collapse:collapse;margin:0px;padding:0px;";
  383. print("<table style='$style'>");
  384. for ($r = 0; $r < $this->getModuleCount(); $r++) {
  385. print("<tr style='$style'>");
  386. for ($c = 0; $c < $this->getModuleCount(); $c++) {
  387. $color = $this->isDark($r, $c)? "#000000" : "#ffffff";
  388. print("<td style='$style;width:$size;height:$size;background-color:$color'></td>");
  389. }
  390. print("</tr>");
  391. }
  392. print("</table>");
  393. }
  394. }
  395. //---------------------------------------------------------------
  396. // QRUtil
  397. //---------------------------------------------------------------
  398. $QR_PATTERN_POSITION_TABLE = array(
  399. array(),
  400. array(6, 18),
  401. array(6, 22),
  402. array(6, 26),
  403. array(6, 30),
  404. array(6, 34),
  405. array(6, 22, 38),
  406. array(6, 24, 42),
  407. array(6, 26, 46),
  408. array(6, 28, 50),
  409. array(6, 30, 54),
  410. array(6, 32, 58),
  411. array(6, 34, 62),
  412. array(6, 26, 46, 66),
  413. array(6, 26, 48, 70),
  414. array(6, 26, 50, 74),
  415. array(6, 30, 54, 78),
  416. array(6, 30, 56, 82),
  417. array(6, 30, 58, 86),
  418. array(6, 34, 62, 90),
  419. array(6, 28, 50, 72, 94),
  420. array(6, 26, 50, 74, 98),
  421. array(6, 30, 54, 78, 102),
  422. array(6, 28, 54, 80, 106),
  423. array(6, 32, 58, 84, 110),
  424. array(6, 30, 58, 86, 114),
  425. array(6, 34, 62, 90, 118),
  426. array(6, 26, 50, 74, 98, 122),
  427. array(6, 30, 54, 78, 102, 126),
  428. array(6, 26, 52, 78, 104, 130),
  429. array(6, 30, 56, 82, 108, 134),
  430. array(6, 34, 60, 86, 112, 138),
  431. array(6, 30, 58, 86, 114, 142),
  432. array(6, 34, 62, 90, 118, 146),
  433. array(6, 30, 54, 78, 102, 126, 150),
  434. array(6, 24, 50, 76, 102, 128, 154),
  435. array(6, 28, 54, 80, 106, 132, 158),
  436. array(6, 32, 58, 84, 110, 136, 162),
  437. array(6, 26, 54, 82, 110, 138, 166),
  438. array(6, 30, 58, 86, 114, 142, 170)
  439. );
  440. $QR_MAX_LENGTH = array(
  441. array( array(41, 25, 17, 10), array(34, 20, 14, 8), array(27, 16, 11, 7), array(17, 10, 7, 4) ),
  442. array( array(77, 47, 32, 20), array(63, 38, 26, 16), array(48, 29, 20, 12), array(34, 20, 14, 8) ),
  443. array( array(127, 77, 53, 32), array(101, 61, 42, 26), array(77, 47, 32, 20), array(58, 35, 24, 15) ),
  444. array( array(187, 114, 78, 48), array(149, 90, 62, 38), array(111, 67, 46, 28), array(82, 50, 34, 21) ),
  445. array( array(255, 154, 106, 65), array(202, 122, 84, 52), array(144, 87, 60, 37), array(106, 64, 44, 27) ),
  446. array( array(322, 195, 134, 82), array(255, 154, 106, 65), array(178, 108, 74, 45), array(139, 84, 58, 36) ),
  447. array( array(370, 224, 154, 95), array(293, 178, 122, 75), array(207, 125, 86, 53), array(154, 93, 64, 39) ),
  448. array( array(461, 279, 192, 118), array(365, 221, 152, 93), array(259, 157, 108, 66), array(202, 122, 84, 52) ),
  449. array( array(552, 335, 230, 141), array(432, 262, 180, 111), array(312, 189, 130, 80), array(235, 143, 98, 60) ),
  450. array( array(652, 395, 271, 167), array(513, 311, 213, 131), array(364, 221, 151, 93), array(288, 174, 119, 74) )
  451. );
  452. define("QR_G15", (1 << 10) | (1 << 8) | (1 << 5)
  453. | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0) );
  454. define("QR_G18", (1 << 12) | (1 << 11) | (1 << 10)
  455. | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0) );
  456. define("QR_G15_MASK", (1 << 14) | (1 << 12) | (1 << 10)
  457. | (1 << 4) | (1 << 1) );
  458. class QRUtil {
  459. function getPatternPosition($typeNumber) {
  460. global $QR_PATTERN_POSITION_TABLE;
  461. return $QR_PATTERN_POSITION_TABLE[$typeNumber - 1];
  462. }
  463. function getMaxLength($typeNumber, $mode, $errorCorrectLevel) {
  464. global $QR_MAX_LENGTH;
  465. $t = $typeNumber - 1;
  466. $e = 0;
  467. $m = 0;
  468. switch($errorCorrectLevel) {
  469. case QR_ERROR_CORRECT_LEVEL_L : $e = 0; break;
  470. case QR_ERROR_CORRECT_LEVEL_M : $e = 1; break;
  471. case QR_ERROR_CORRECT_LEVEL_Q : $e = 2; break;
  472. case QR_ERROR_CORRECT_LEVEL_H : $e = 3; break;
  473. default :
  474. trigger_error("e:$errorCorrectLevel", E_USER_ERROR);
  475. }
  476. switch($mode) {
  477. case QR_MODE_NUMBER : $m = 0; break;
  478. case QR_MODE_ALPHA_NUM : $m = 1; break;
  479. case QR_MODE_8BIT_BYTE : $m = 2; break;
  480. case QR_MODE_KANJI : $m = 3; break;
  481. default :
  482. trigger_error("m:$mode", E_USER_ERROR);
  483. }
  484. return $QR_MAX_LENGTH[$t][$e][$m];
  485. }
  486. function getErrorCorrectPolynomial($errorCorrectLength) {
  487. $a = new QRPolynomial(array(1) );
  488. for ($i = 0; $i < $errorCorrectLength; $i++) {
  489. $a = $a->multiply(new QRPolynomial(array(1, QRMath::gexp($i) ) ) );
  490. }
  491. return $a;
  492. }
  493. function getMask($maskPattern, $i, $j) {
  494. switch ($maskPattern) {
  495. case QR_MASK_PATTERN000 : return ($i + $j) % 2 == 0;
  496. case QR_MASK_PATTERN001 : return $i % 2 == 0;
  497. case QR_MASK_PATTERN010 : return $j % 3 == 0;
  498. case QR_MASK_PATTERN011 : return ($i + $j) % 3 == 0;
  499. case QR_MASK_PATTERN100 : return (floor($i / 2) + floor($j / 3) ) % 2 == 0;
  500. case QR_MASK_PATTERN101 : return ($i * $j) % 2 + ($i * $j) % 3 == 0;
  501. case QR_MASK_PATTERN110 : return ( ($i * $j) % 2 + ($i * $j) % 3) % 2 == 0;
  502. case QR_MASK_PATTERN111 : return ( ($i * $j) % 3 + ($i + $j) % 2) % 2 == 0;
  503. default :
  504. trigger_error("mask:$maskPattern", E_USER_ERROR);
  505. }
  506. }
  507. function getLostPoint($qrCode) {
  508. $moduleCount = $qrCode->getModuleCount();
  509. $lostPoint = 0;
  510. // LEVEL1
  511. for ($row = 0; $row < $moduleCount; $row++) {
  512. for ($col = 0; $col < $moduleCount; $col++) {
  513. $sameCount = 0;
  514. $dark = $qrCode->isDark($row, $col);
  515. for ($r = -1; $r <= 1; $r++) {
  516. if ($row + $r < 0 || $moduleCount <= $row + $r) {
  517. continue;
  518. }
  519. for ($c = -1; $c <= 1; $c++) {
  520. if ($col + $c < 0 || $moduleCount <= $col + $c) {
  521. continue;
  522. }
  523. if ($r == 0 && $c == 0) {
  524. continue;
  525. }
  526. if ($dark == $qrCode->isDark($row + $r, $col + $c) ) {
  527. $sameCount++;
  528. }
  529. }
  530. }
  531. if ($sameCount > 5) {
  532. $lostPoint += (3 + $sameCount - 5);
  533. }
  534. }
  535. }
  536. // LEVEL2
  537. for ($row = 0; $row < $moduleCount - 1; $row++) {
  538. for ($col = 0; $col < $moduleCount - 1; $col++) {
  539. $count = 0;
  540. if ($qrCode->isDark($row, $col ) ) $count++;
  541. if ($qrCode->isDark($row + 1, $col ) ) $count++;
  542. if ($qrCode->isDark($row, $col + 1) ) $count++;
  543. if ($qrCode->isDark($row + 1, $col + 1) ) $count++;
  544. if ($count == 0 || $count == 4) {
  545. $lostPoint += 3;
  546. }
  547. }
  548. }
  549. // LEVEL3
  550. for ($row = 0; $row < $moduleCount; $row++) {
  551. for ($col = 0; $col < $moduleCount - 6; $col++) {
  552. if ($qrCode->isDark($row, $col)
  553. && !$qrCode->isDark($row, $col + 1)
  554. && $qrCode->isDark($row, $col + 2)
  555. && $qrCode->isDark($row, $col + 3)
  556. && $qrCode->isDark($row, $col + 4)
  557. && !$qrCode->isDark($row, $col + 5)
  558. && $qrCode->isDark($row, $col + 6) ) {
  559. $lostPoint += 40;
  560. }
  561. }
  562. }
  563. for ($col = 0; $col < $moduleCount; $col++) {
  564. for ($row = 0; $row < $moduleCount - 6; $row++) {
  565. if ($qrCode->isDark($row, $col)
  566. && !$qrCode->isDark($row + 1, $col)
  567. && $qrCode->isDark($row + 2, $col)
  568. && $qrCode->isDark($row + 3, $col)
  569. && $qrCode->isDark($row + 4, $col)
  570. && !$qrCode->isDark($row + 5, $col)
  571. && $qrCode->isDark($row + 6, $col) ) {
  572. $lostPoint += 40;
  573. }
  574. }
  575. }
  576. // LEVEL4
  577. $darkCount = 0;
  578. for ($col = 0; $col < $moduleCount; $col++) {
  579. for ($row = 0; $row < $moduleCount; $row++) {
  580. if ($qrCode->isDark($row, $col) ) {
  581. $darkCount++;
  582. }
  583. }
  584. }
  585. $ratio = abs(100 * $darkCount / $moduleCount / $moduleCount - 50) / 5;
  586. $lostPoint += $ratio * 10;
  587. return $lostPoint;
  588. }
  589. function getMode($s) {
  590. if (QRUtil::isAlphaNum($s) ) {
  591. if (QRUtil::isNumber($s) ) {
  592. return QR_MODE_NUMBER;
  593. }
  594. return QR_MODE_ALPHA_NUM;
  595. } else if (QRUtil::isKanji($s) ) {
  596. return QR_MODE_KANJI;
  597. } else {
  598. return QR_MODE_8BIT_BYTE;
  599. }
  600. }
  601. function isNumber($s) {
  602. for ($i = 0; $i < strlen($s); $i++) {
  603. $c = ord($s[$i]);
  604. if (!(QRUtil::toCharCode('0') <= $c && $c <= QRUtil::toCharCode('9') ) ) {
  605. return false;
  606. }
  607. }
  608. return true;
  609. }
  610. function isAlphaNum($s) {
  611. for ($i = 0; $i < strlen($s); $i++) {
  612. $c = ord($s[$i]);
  613. if (!(QRUtil::toCharCode('0') <= $c && $c <= QRUtil::toCharCode('9') )
  614. && !(QRUtil::toCharCode('A') <= $c && $c <= QRUtil::toCharCode('Z') )
  615. && strpos(" $%*+-./:", $s[$i]) === false) {
  616. return false;
  617. }
  618. }
  619. return true;
  620. }
  621. function isKanji($s) {
  622. $data = $s;
  623. $i = 0;
  624. while ($i + 1 < strlen($data) ) {
  625. $c = ( (0xff & ord($data[$i]) ) << 8) | (0xff & ord($data[$i + 1]) );
  626. if (!(0x8140 <= $c && $c <= 0x9FFC) && !(0xE040 <= $c && $c <= 0xEBBF) ) {
  627. return false;
  628. }
  629. $i += 2;
  630. }
  631. if ($i < strlen($data) ) {
  632. return false;
  633. }
  634. return true;
  635. }
  636. function toCharCode($s) {
  637. return ord($s[0]);
  638. }
  639. function getBCHTypeInfo($data) {
  640. $d = $data << 10;
  641. while (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G15) >= 0) {
  642. $d ^= (QR_G15 << (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G15) ) );
  643. }
  644. return ( ($data << 10) | $d) ^ QR_G15_MASK;
  645. }
  646. function getBCHTypeNumber($data) {
  647. $d = $data << 12;
  648. while (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G18) >= 0) {
  649. $d ^= (QR_G18 << (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G18) ) );
  650. }
  651. return ($data << 12) | $d;
  652. }
  653. function getBCHDigit($data) {
  654. $digit = 0;
  655. while ($data != 0) {
  656. $digit++;
  657. $data >>= 1;
  658. }
  659. return $digit;
  660. }
  661. }
  662. //---------------------------------------------------------------
  663. // QRRSBlock
  664. //---------------------------------------------------------------
  665. $QR_RS_BLOCK_TABLE = array(
  666. // L
  667. // M
  668. // Q
  669. // H
  670. // 1
  671. array(1, 26, 19),
  672. array(1, 26, 16),
  673. array(1, 26, 13),
  674. array(1, 26, 9),
  675. // 2
  676. array(1, 44, 34),
  677. array(1, 44, 28),
  678. array(1, 44, 22),
  679. array(1, 44, 16),
  680. // 3
  681. array(1, 70, 55),
  682. array(1, 70, 44),
  683. array(2, 35, 17),
  684. array(2, 35, 13),
  685. // 4
  686. array(1, 100, 80),
  687. array(2, 50, 32),
  688. array(2, 50, 24),
  689. array(4, 25, 9),
  690. // 5
  691. array(1, 134, 108),
  692. array(2, 67, 43),
  693. array(2, 33, 15, 2, 34, 16),
  694. array(2, 33, 11, 2, 34, 12),
  695. // 6
  696. array(2, 86, 68),
  697. array(4, 43, 27),
  698. array(4, 43, 19),
  699. array(4, 43, 15),
  700. // 7
  701. array(2, 98, 78),
  702. array(4, 49, 31),
  703. array(2, 32, 14, 4, 33, 15),
  704. array(4, 39, 13, 1, 40, 14),
  705. // 8
  706. array(2, 121, 97),
  707. array(2, 60, 38, 2, 61, 39),
  708. array(4, 40, 18, 2, 41, 19),
  709. array(4, 40, 14, 2, 41, 15),
  710. // 9
  711. array(2, 146, 116),
  712. array(3, 58, 36, 2, 59, 37),
  713. array(4, 36, 16, 4, 37, 17),
  714. array(4, 36, 12, 4, 37, 13),
  715. // 10
  716. array(2, 86, 68, 2, 87, 69),
  717. array(4, 69, 43, 1, 70, 44),
  718. array(6, 43, 19, 2, 44, 20),
  719. array(6, 43, 15, 2, 44, 16)
  720. );
  721. class QRRSBlock {
  722. var $totalCount;
  723. var $dataCount;
  724. function QRRSBlock($totalCount, $dataCount) {
  725. $this->totalCount = $totalCount;
  726. $this->dataCount = $dataCount;
  727. }
  728. function getDataCount() {
  729. return $this->dataCount;
  730. }
  731. function getTotalCount() {
  732. return $this->totalCount;
  733. }
  734. function getRSBlocks($typeNumber, $errorCorrectLevel) {
  735. $rsBlock = QRRSBlock::getRsBlockTable($typeNumber, $errorCorrectLevel);
  736. $length = count($rsBlock) / 3;
  737. $list = array();
  738. for ($i = 0; $i < $length; $i++) {
  739. $count = $rsBlock[$i * 3 + 0];
  740. $totalCount = $rsBlock[$i * 3 + 1];
  741. $dataCount = $rsBlock[$i * 3 + 2];
  742. for ($j = 0; $j < $count; $j++) {
  743. $list[] = new QRRSBlock($totalCount, $dataCount);
  744. }
  745. }
  746. return $list;
  747. }
  748. function getRsBlockTable($typeNumber, $errorCorrectLevel) {
  749. global $QR_RS_BLOCK_TABLE;
  750. switch($errorCorrectLevel) {
  751. case QR_ERROR_CORRECT_LEVEL_L :
  752. return $QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 0];
  753. case QR_ERROR_CORRECT_LEVEL_M :
  754. return $QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 1];
  755. case QR_ERROR_CORRECT_LEVEL_Q :
  756. return $QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 2];
  757. case QR_ERROR_CORRECT_LEVEL_H :
  758. return $QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 3];
  759. default :
  760. trigger_error("tn:$typeNumber/ecl:$errorCorrectLevel", E_USER_ERROR);
  761. }
  762. }
  763. }
  764. //---------------------------------------------------------------
  765. // QRNumber
  766. //---------------------------------------------------------------
  767. class QRNumber extends QRData {
  768. function QRNumber($data) {
  769. QRData::QRData(QR_MODE_NUMBER, $data);
  770. }
  771. function write(&$buffer) {
  772. $data = $this->getData();
  773. $i = 0;
  774. while ($i + 2 < strlen($data) ) {
  775. $num = QRNumber::parseInt(substr($data, $i, 3) );
  776. $buffer->put($num, 10);
  777. $i += 3;
  778. }
  779. if ($i < strlen($data) ) {
  780. if (strlen($data) - $i == 1) {
  781. $num = QRNumber::parseInt(substr($data, $i, $i + 1) );
  782. $buffer->put($num, 4);
  783. } else if (strlen($data) - $i == 2) {
  784. $num = QRNumber::parseInt(substr($data, $i, $i + 2) );
  785. $buffer->put($num, 7);
  786. }
  787. }
  788. }
  789. function getLength() {
  790. return strlen($this->getData() );
  791. }
  792. function parseInt($s) {
  793. $num = 0;
  794. for ($i = 0; $i < strlen($s); $i++) {
  795. $num = $num * 10 + QRNumber::parseIntAt(ord($s[$i]) );
  796. }
  797. return $num;
  798. }
  799. function parseIntAt($c) {
  800. if (QRUtil::toCharCode('0') <= $c && $c <= QRUtil::toCharCode('9') ) {
  801. return $c - QRUtil::toCharCode('0');
  802. }
  803. trigger_error("illegal char : $c", E_USER_ERROR);
  804. }
  805. }
  806. //---------------------------------------------------------------
  807. // QRKanji
  808. //---------------------------------------------------------------
  809. class QRKanji extends QRData {
  810. function QRKanji($data) {
  811. QRData::QRData(QR_MODE_KANJI, $data);
  812. }
  813. function write(&$buffer) {
  814. $data = $this->getData();
  815. $i = 0;
  816. while ($i + 1 < strlen($data) ) {
  817. $c = ( (0xff & ord($data[$i]) ) << 8) | (0xff & ord($data[$i + 1]) );
  818. if (0x8140 <= $c && $c <= 0x9FFC) {
  819. $c -= 0x8140;
  820. } else if (0xE040 <= $c && $c <= 0xEBBF) {
  821. $c -= 0xC140;
  822. } else {
  823. trigger_error("illegal char at " . ($i + 1) . "/$c", E_USER_ERROR);
  824. }
  825. $c = ( ($c >> 8) & 0xff) * 0xC0 + ($c & 0xff);
  826. $buffer->put($c, 13);
  827. $i += 2;
  828. }
  829. if ($i < strlen($data) ) {
  830. trigger_error("illegal char at " . ($i + 1), E_USER_ERROR);
  831. }
  832. }
  833. function getLength() {
  834. return floor(strlen($this->getData() ) / 2);
  835. }
  836. }
  837. //---------------------------------------------------------------
  838. // QRAlphaNum
  839. //---------------------------------------------------------------
  840. class QRAlphaNum extends QRData {
  841. function QRAlphaNum($data) {
  842. QRData::QRData(QR_MODE_ALPHA_NUM, $data);
  843. }
  844. function write(&$buffer) {
  845. $i = 0;
  846. $c = $this->getData();
  847. while ($i + 1 < strlen($c) ) {
  848. $buffer->put(QRAlphaNum::getCode(ord($c[$i]) ) * 45
  849. + QRAlphaNum::getCode(ord($c[$i + 1]) ), 11);
  850. $i += 2;
  851. }
  852. if ($i < strlen($c) ) {
  853. $buffer->put(QRAlphaNum::getCode(ord($c[$i])), 6);
  854. }
  855. }
  856. function getLength() {
  857. return strlen($this->getData() );
  858. }
  859. function getCode($c) {
  860. if (QRUtil::toCharCode('0') <= $c
  861. && $c <= QRUtil::toCharCode('9') ) {
  862. return $c - QRUtil::toCharCode('0');
  863. } else if (QRUtil::toCharCode('A') <= $c
  864. && $c <= QRUtil::toCharCode('Z') ) {
  865. return $c - QRUtil::toCharCode('A') + 10;
  866. } else {
  867. switch ($c) {
  868. case QRUtil::toCharCode(' ') : return 36;
  869. case QRUtil::toCharCode('$') : return 37;
  870. case QRUtil::toCharCode('%') : return 38;
  871. case QRUtil::toCharCode('*') : return 39;
  872. case QRUtil::toCharCode('+') : return 40;
  873. case QRUtil::toCharCode('-') : return 41;
  874. case QRUtil::toCharCode('.') : return 42;
  875. case QRUtil::toCharCode('/') : return 43;
  876. case QRUtil::toCharCode(':') : return 44;
  877. default :
  878. trigger_error("illegal char : $c", E_USER_ERROR);
  879. }
  880. }
  881. }
  882. }
  883. //---------------------------------------------------------------
  884. // QR8BitByte
  885. //---------------------------------------------------------------
  886. class QR8BitByte extends QRData {
  887. function QR8BitByte($data) {
  888. QRData::QRData(QR_MODE_8BIT_BYTE, $data);
  889. }
  890. function write(&$buffer) {
  891. $data = $this->getData();
  892. for ($i = 0; $i < strlen($data); $i++) {
  893. $buffer->put(ord($data[$i]), 8);
  894. }
  895. }
  896. function getLength() {
  897. return strlen($this->getData() );
  898. }
  899. }
  900. //---------------------------------------------------------------
  901. // QRData
  902. //---------------------------------------------------------------
  903. class QRData {
  904. var $mode;
  905. var $data;
  906. function QRData($mode, $data) {
  907. $this->mode = $mode;
  908. $this->data = $data;
  909. }
  910. function getMode() {
  911. return $this->mode;
  912. }
  913. function getData() {
  914. return $this->data;
  915. }
  916. function getLength() {
  917. trigger_error("not implemented.", E_USER_ERROR);
  918. }
  919. function write(&$buffer) {
  920. trigger_error("not implemented.", E_USER_ERROR);
  921. }
  922. function getLengthInBits($type) {
  923. if (1 <= $type && $type < 10) {
  924. // 1 - 9
  925. switch($this->mode) {
  926. case QR_MODE_NUMBER : return 10;
  927. case QR_MODE_ALPHA_NUM : return 9;
  928. case QR_MODE_8BIT_BYTE : return 8;
  929. case QR_MODE_KANJI : return 8;
  930. default :
  931. trigger_error("mode:$this->mode", E_USER_ERROR);
  932. }
  933. } else if ($type < 27) {
  934. // 10 - 26
  935. switch($this->mode) {
  936. case QR_MODE_NUMBER : return 12;
  937. case QR_MODE_ALPHA_NUM : return 11;
  938. case QR_MODE_8BIT_BYTE : return 16;
  939. case QR_MODE_KANJI : return 10;
  940. default :
  941. trigger_error("mode:$this->mode", E_USER_ERROR);
  942. }
  943. } else if ($type < 41) {
  944. // 27 - 40
  945. switch($this->mode) {
  946. case QR_MODE_NUMBER : return 14;
  947. case QR_MODE_ALPHA_NUM : return 13;
  948. case QR_MODE_8BIT_BYTE : return 16;
  949. case QR_MODE_KANJI : return 12;
  950. default :
  951. trigger_error("mode:$this->mode", E_USER_ERROR);
  952. }
  953. } else {
  954. trigger_error("mode:$this->mode", E_USER_ERROR);
  955. }
  956. }
  957. }
  958. //---------------------------------------------------------------
  959. // QRMath
  960. //---------------------------------------------------------------
  961. $QR_MATH_EXP_TABLE = null;
  962. $QR_MATH_LOG_TABLE = null;
  963. class QRMath {
  964. function init() {
  965. global $QR_MATH_EXP_TABLE;
  966. global $QR_MATH_LOG_TABLE;
  967. $QR_MATH_EXP_TABLE = QRMath::createNumArray(256);
  968. for ($i = 0; $i < 8; $i++) {
  969. $QR_MATH_EXP_TABLE[$i] = 1 << $i;
  970. }
  971. for ($i = 8; $i < 256; $i++) {
  972. $QR_MATH_EXP_TABLE[$i] = $QR_MATH_EXP_TABLE[$i - 4]
  973. ^ $QR_MATH_EXP_TABLE[$i - 5]
  974. ^ $QR_MATH_EXP_TABLE[$i - 6]
  975. ^ $QR_MATH_EXP_TABLE[$i - 8];
  976. }
  977. $QR_MATH_LOG_TABLE = QRMath::createNumArray(256);
  978. for ($i = 0; $i < 255; $i++) {
  979. $QR_MATH_LOG_TABLE[$QR_MATH_EXP_TABLE[$i] ] = $i;
  980. }
  981. }
  982. function createNumArray($length) {
  983. $num_array = array();
  984. for ($i = 0; $i < $length; $i++) {
  985. $num_array[] = 0;
  986. }
  987. return $num_array;
  988. }
  989. function glog($n) {
  990. global $QR_MATH_LOG_TABLE;
  991. if ($n < 1) {
  992. trigger_error("log($n)", E_USER_ERROR);
  993. }
  994. return $QR_MATH_LOG_TABLE[$n];
  995. }
  996. function gexp($n) {
  997. global $QR_MATH_EXP_TABLE;
  998. while ($n < 0) {
  999. $n += 255;
  1000. }
  1001. while ($n >= 256) {
  1002. $n -= 255;
  1003. }
  1004. return $QR_MATH_EXP_TABLE[$n];
  1005. }
  1006. }
  1007. // init static table
  1008. QRMath::init();
  1009. //---------------------------------------------------------------
  1010. // QRPolynomial
  1011. //---------------------------------------------------------------
  1012. class QRPolynomial {
  1013. var $num;
  1014. function QRPolynomial($num, $shift = 0) {
  1015. $offset = 0;
  1016. while ($offset < count($num) && $num[$offset] == 0) {
  1017. $offset++;
  1018. }
  1019. $this->num = QRMath::createNumArray(count($num) - $offset + $shift);
  1020. for ($i = 0; $i < count($num) - $offset; $i++) {
  1021. $this->num[$i] = $num[$i + $offset];
  1022. }
  1023. }
  1024. function get($index) {
  1025. return $this->num[$index];
  1026. }
  1027. function getLength() {
  1028. return count($this->num);
  1029. }
  1030. // PHP5
  1031. function __toString() {
  1032. return $this->toString();
  1033. }
  1034. function toString() {
  1035. $buffer = "";
  1036. for ($i = 0; $i < $this->getLength(); $i++) {
  1037. if ($i > 0) {
  1038. $buffer .= ",";
  1039. }
  1040. $buffer .= $this->get($i);
  1041. }
  1042. return $buffer;
  1043. }
  1044. function toLogString() {
  1045. $buffer = "";
  1046. for ($i = 0; $i < $this->getLength(); $i++) {
  1047. if ($i > 0) {
  1048. $buffer .= ",";
  1049. }
  1050. $buffer .= QRMath::glog($this->get(i) );
  1051. }
  1052. return $buffer;
  1053. }
  1054. function multiply($e) {
  1055. $num = QRMath::createNumArray($this->getLength() + $e->getLength() - 1);
  1056. for ($i = 0; $i < $this->getLength(); $i++) {
  1057. for ($j = 0; $j < $e->getLength(); $j++) {
  1058. $num[$i + $j] ^= QRMath::gexp(QRMath::glog($this->get($i) ) + QRMath::glog($e->get($j) ) );
  1059. }
  1060. }
  1061. return new QRPolynomial($num);
  1062. }
  1063. function mod($e) {
  1064. if ($this->getLength() - $e->getLength() < 0) {
  1065. return $this;
  1066. }
  1067. $ratio = QRMath::glog($this->get(0) ) - QRMath::glog($e->get(0) );
  1068. $num = QRMath::createNumArray($this->getLength() );
  1069. for ($i = 0; $i < $this->getLength(); $i++) {
  1070. $num[$i] = $this->get($i);
  1071. }
  1072. for ($i = 0; $i < $e->getLength(); $i++) {
  1073. $num[$i] ^= QRMath::gexp(QRMath::glog($e->get($i) ) + $ratio);
  1074. }
  1075. $newPolynomial = new QRPolynomial($num);
  1076. return $newPolynomial->mod($e);
  1077. }
  1078. }
  1079. //---------------------------------------------------------------
  1080. // Mode
  1081. //---------------------------------------------------------------
  1082. define("QR_MODE_NUMBER", 1 << 0);
  1083. define("QR_MODE_ALPHA_NUM", 1 << 1);
  1084. define("QR_MODE_8BIT_BYTE", 1 << 2);
  1085. define("QR_MODE_KANJI", 1 << 3);
  1086. //---------------------------------------------------------------
  1087. // MaskPattern
  1088. //---------------------------------------------------------------
  1089. define("QR_MASK_PATTERN000", 0);
  1090. define("QR_MASK_PATTERN001", 1);
  1091. define("QR_MASK_PATTERN010", 2);
  1092. define("QR_MASK_PATTERN011", 3);
  1093. define("QR_MASK_PATTERN100", 4);
  1094. define("QR_MASK_PATTERN101", 5);
  1095. define("QR_MASK_PATTERN110", 6);
  1096. define("QR_MASK_PATTERN111", 7);
  1097. //---------------------------------------------------------------
  1098. // ErrorCorrectLevel
  1099. // 7%.
  1100. define("QR_ERROR_CORRECT_LEVEL_L", 1);
  1101. // 15%.
  1102. define("QR_ERROR_CORRECT_LEVEL_M", 0);
  1103. // 25%.
  1104. define("QR_ERROR_CORRECT_LEVEL_Q", 3);
  1105. // 30%.
  1106. define("QR_ERROR_CORRECT_LEVEL_H", 2);
  1107. //---------------------------------------------------------------
  1108. // QRBitBuffer
  1109. //---------------------------------------------------------------
  1110. class QRBitBuffer {
  1111. var $buffer;
  1112. var $length;
  1113. function QRBitBuffer() {
  1114. $this->buffer = array();
  1115. $this->length = 0;
  1116. }
  1117. function getBuffer() {
  1118. return $this->buffer;
  1119. }
  1120. function getLengthInBits() {
  1121. return $this->length;
  1122. }
  1123. function __toString() {
  1124. $buffer = "";
  1125. for ($i = 0; $i < $this->getLengthInBits(); $i++) {
  1126. $buffer .= $this->get($i)? '1' : '0';
  1127. }
  1128. return $buffer;
  1129. }
  1130. function get($index) {
  1131. $bufIndex = floor($index / 8);
  1132. return ( ($this->buffer[$bufIndex] >> (7 - $index % 8) ) & 1) == 1;
  1133. }
  1134. function put($num, $length) {
  1135. for ($i = 0; $i < $length; $i++) {
  1136. $this->putBit( ( ($num >> ($length - $i - 1) ) & 1) == 1);
  1137. }
  1138. }
  1139. function putBit($bit) {
  1140. $bufIndex = floor($this->length / 8);
  1141. if (count($this->buffer) <= $bufIndex) {
  1142. $this->buffer[] = 0;
  1143. }
  1144. if ($bit) {
  1145. $this->buffer[$bufIndex] |= (0x80 >> ($this->length % 8) );
  1146. }
  1147. $this->length++;
  1148. }
  1149. }
  1150. ?>