83 if (!defined(
'QRCODEDEFS')) {
88 define(
'QRCODEDEFS',
true);
97 define(
'QR_MODE_NL', -1);
102 define(
'QR_MODE_NM', 0);
107 define(
'QR_MODE_AN', 1);
112 define(
'QR_MODE_8B', 2);
117 define(
'QR_MODE_KJ', 3);
122 define(
'QR_MODE_ST', 4);
133 define(
'QR_ECLEVEL_L', 0);
138 define(
'QR_ECLEVEL_M', 1);
143 define(
'QR_ECLEVEL_Q', 2);
148 define(
'QR_ECLEVEL_H', 3);
160 define(
'QRSPEC_VERSION_MAX', 40);
165 define(
'QRSPEC_WIDTH_MAX', 177);
172 define(
'QRCAP_WIDTH', 0);
177 define(
'QRCAP_WORDS', 1);
182 define(
'QRCAP_REMINDER', 2);
187 define(
'QRCAP_EC', 3);
196 define(
'STRUCTURE_HEADER_BITS', 20);
201 define(
'MAX_STRUCTURED_SYMBOLS', 16);
234 define(
'QR_FIND_BEST_MASK',
true);
239 define(
'QR_FIND_FROM_RANDOM', 2);
244 define(
'QR_DEFAULT_MASK', 2);
253 if (!function_exists(
'str_split')) {
260 function str_split($string, $split_length=1) {
261 if ((strlen($string) > $split_length) OR (!$split_length)) {
263 $c = strlen($string);
264 $parts[] = substr($string, 0, $split_length);
265 $string = substr($string, $split_length);
266 }
while ($string !==
false);
268 $parts = array($string);
464 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
465 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
466 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
467 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,
468 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
469 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
470 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
471 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
480 array( 0, 0, 0, array( 0, 0, 0, 0)),
481 array( 21, 26, 0, array( 7, 10, 13, 17)),
482 array( 25, 44, 7, array( 10, 16, 22, 28)),
483 array( 29, 70, 7, array( 15, 26, 36, 44)),
484 array( 33, 100, 7, array( 20, 36, 52, 64)),
485 array( 37, 134, 7, array( 26, 48, 72, 88)),
486 array( 41, 172, 7, array( 36, 64, 96, 112)),
487 array( 45, 196, 0, array( 40, 72, 108, 130)),
488 array( 49, 242, 0, array( 48, 88, 132, 156)),
489 array( 53, 292, 0, array( 60, 110, 160, 192)),
490 array( 57, 346, 0, array( 72, 130, 192, 224)),
491 array( 61, 404, 0, array( 80, 150, 224, 264)),
492 array( 65, 466, 0, array( 96, 176, 260, 308)),
493 array( 69, 532, 0, array( 104, 198, 288, 352)),
494 array( 73, 581, 3, array( 120, 216, 320, 384)),
495 array( 77, 655, 3, array( 132, 240, 360, 432)),
496 array( 81, 733, 3, array( 144, 280, 408, 480)),
497 array( 85, 815, 3, array( 168, 308, 448, 532)),
498 array( 89, 901, 3, array( 180, 338, 504, 588)),
499 array( 93, 991, 3, array( 196, 364, 546, 650)),
500 array( 97, 1085, 3, array( 224, 416, 600, 700)),
501 array(101, 1156, 4, array( 224, 442, 644, 750)),
502 array(105, 1258, 4, array( 252, 476, 690, 816)),
503 array(109, 1364, 4, array( 270, 504, 750, 900)),
504 array(113, 1474, 4, array( 300, 560, 810, 960)),
505 array(117, 1588, 4, array( 312, 588, 870, 1050)),
506 array(121, 1706, 4, array( 336, 644, 952, 1110)),
507 array(125, 1828, 4, array( 360, 700, 1020, 1200)),
508 array(129, 1921, 3, array( 390, 728, 1050, 1260)),
509 array(133, 2051, 3, array( 420, 784, 1140, 1350)),
510 array(137, 2185, 3, array( 450, 812, 1200, 1440)),
511 array(141, 2323, 3, array( 480, 868, 1290, 1530)),
512 array(145, 2465, 3, array( 510, 924, 1350, 1620)),
513 array(149, 2611, 3, array( 540, 980, 1440, 1710)),
514 array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
515 array(157, 2876, 0, array( 570, 1064, 1590, 1890)),
516 array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
517 array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
518 array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
519 array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
520 array(177, 3706, 0, array( 750, 1372, 2040, 2430))
540 array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)),
541 array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)),
542 array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)),
543 array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)),
544 array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)),
545 array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)),
546 array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)),
547 array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)),
548 array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)),
549 array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)),
550 array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)),
551 array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)),
552 array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)),
553 array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)),
554 array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)),
555 array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)),
556 array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)),
557 array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)),
558 array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)),
559 array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)),
560 array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)),
561 array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)),
562 array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)),
563 array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)),
564 array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)),
565 array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)),
566 array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)),
567 array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)),
568 array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)),
569 array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)),
570 array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)),
571 array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)),
572 array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)),
573 array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)),
574 array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)),
575 array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)),
576 array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
577 array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)),
578 array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)),
579 array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)),
580 array(array(19, 6), array(18, 31), array(34, 34), array(20, 61))
591 array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0),
592 array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50),
593 array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48),
594 array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62),
595 array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58),
596 array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52),
597 array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54),
598 array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58)
608 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
609 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
610 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
611 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
620 array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
621 array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
622 array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed),
623 array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b)
645 $this->level = array_search($eclevel, array(
'L',
'M',
'Q',
'H'));
646 if ($this->level ===
false) {
647 $this->level = QR_ECLEVEL_L;
649 if (($this->hint != QR_MODE_8B) AND ($this->hint != QR_MODE_KJ)) {
652 if (($this->version < 0) OR ($this->version > QRSPEC_VERSION_MAX)) {
655 $this->items = array();
657 if (is_null($this->
data)) {
661 $size = count($qrTab);
665 foreach ($qrTab as $line) {
667 foreach (str_split($line) as $char) {
668 $arrAdd[] = ($char==
'1')?1:0;
692 foreach (
$frame as &$frameLine) {
693 for (
$i=0;
$i<$len;
$i++) {
694 $frameLine[
$i] = (ord($frameLine[
$i])&1)?
'1':
'0';
705 $this->dataStr = $string;
706 if (!$this->casesensitive) {
721 $spec = array(0, 0, 0, 0, 0);
724 if (is_null($this->datacode)) {
727 $spec = $this->
getEccSpec($this->version, $this->level, $spec);
731 $this->ecccode = array_fill(0, $this->eccLength, 0);
738 $this->width = $this->
getWidth($this->version);
739 $this->frame = $this->
newFrame($this->version);
740 $this->x = $this->width - 1;
741 $this->y = $this->width - 1;
748 for ($j=0; $j<8; $j++) {
761 $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
763 if (QR_FIND_BEST_MASK) {
764 $masked = $this->
mask($this->width, $this->frame, $this->level);
766 $masked = $this->
makeMask($this->width, $this->frame, (intval(QR_DEFAULT_MASK) % 8), $this->level);
769 $masked = $this->
makeMask($this->width, $this->frame,
$mask, $this->level);
771 if ($masked == NULL) {
774 $this->
data = $masked;
787 $this->frame[$at[
'y']][$at[
'x']] = chr($val);
796 return ord($this->frame[$at[
'y']][$at[
'x']]);
805 if ($this->bit == -1) {
807 return array(
'x'=>$this->x,
'y'=>$this->y);
812 if ($this->bit == 0) {
820 if ($this->dir < 0) {
841 if ((
$x < 0) OR (
$y < 0)) {
846 }
while(ord($this->frame[
$y][
$x]) & 0x80);
847 return array(
'x'=>$x,
'y'=>
$y);
859 protected function init($spec) {
862 $rs = $this->
init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
867 for (
$i=0;
$i < $endfor; ++
$i) {
868 $ecc = array_slice($this->ecccode, $eccPos);
869 $this->rsblocks[$blockNo] = array();
870 $this->rsblocks[$blockNo][
'dataLength'] = $dl;
871 $this->rsblocks[$blockNo][
'data'] = array_slice($this->datacode, $dataPos);
872 $this->rsblocks[$blockNo][
'eccLength'] = $el;
873 $ecc = $this->
encode_rs_char($rs, $this->rsblocks[$blockNo][
'data'], $ecc);
874 $this->rsblocks[$blockNo][
'ecc'] = $ecc;
875 $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
885 $rs = $this->
init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
890 for (
$i=0;
$i < $endfor; ++
$i) {
891 $ecc = array_slice($this->ecccode, $eccPos);
892 $this->rsblocks[$blockNo] = array();
893 $this->rsblocks[$blockNo][
'dataLength'] = $dl;
894 $this->rsblocks[$blockNo][
'data'] = array_slice($this->datacode, $dataPos);
895 $this->rsblocks[$blockNo][
'eccLength'] = $el;
896 $ecc = $this->
encode_rs_char($rs, $this->rsblocks[$blockNo][
'data'], $ecc);
897 $this->rsblocks[$blockNo][
'ecc'] = $ecc;
898 $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc);
911 if ($this->count < $this->dataLength) {
914 if ($col >= $this->rsblocks[0][
'dataLength']) {
917 $ret = $this->rsblocks[
$row][
'data'][$col];
918 } elseif ($this->count < $this->dataLength + $this->eccLength) {
921 $ret = $this->rsblocks[
$row][
'ecc'][$col];
984 return (
$x +
$y) & 1;
1014 return (
$x +
$y) % 3;
1024 return (((
int)(
$y / 2)) + ((
int)(
$x / 3))) & 1;
1034 return ((
$x *
$y) & 1) + (
$x *
$y) % 3;
1044 return (((
$x *
$y) & 1) + (
$x * $y) % 3) & 1;
1054 return (((
$x *
$y) % 3) + ((
$x + $y) & 1)) & 1;
1065 $bitMask = array_fill(0,
$width, array_fill(0,
$width, 0));
1069 $bitMask[
$y][
$x] = 0;
1071 $maskFunc = call_user_func(array($this,
'mask'.$maskNo), $x,
$y);
1072 $bitMask[
$y][
$x] = ($maskFunc == 0)?1:0;
1098 if ($bitMask[
$y][
$x] == 1) {
1101 $b += (int)(ord(
$d[
$y][
$x]) & 1);
1116 $masked = array_fill(0,
$width, str_repeat(
"\0",
$width));
1129 for (
$i=0;
$i<$length; ++
$i) {
1130 if ($this->runLength[
$i] >= 5) {
1131 $demerit += (N1 + ($this->runLength[
$i] - 5));
1134 if ((
$i >= 3) AND (
$i < ($length-2)) AND ($this->runLength[
$i] % 3 == 0)) {
1135 $fact = (int)($this->runLength[
$i] / 3);
1136 if (($this->runLength[
$i-2] == $fact)
1137 AND ($this->runLength[
$i-1] == $fact)
1138 AND ($this->runLength[
$i+1] == $fact)
1139 AND ($this->runLength[
$i+2] == $fact)) {
1140 if (($this->runLength[
$i-3] < 0) OR ($this->runLength[
$i-3] >= (4 * $fact))) {
1142 } elseif (((
$i+3) >= $length) OR ($this->runLength[
$i+3] >= (4 * $fact))) {
1163 $this->runLength[0] = 1;
1169 if ((
$x > 0) AND (
$y > 0)) {
1170 $b22 = ord($frameY[
$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
1171 $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
1172 if (($b22 | ($w22 ^ 1)) & 1) {
1176 if ((
$x == 0) AND (ord($frameY[
$x]) & 1)) {
1177 $this->runLength[0] = -1;
1179 $this->runLength[$head] = 1;
1181 if ((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
1183 $this->runLength[$head] = 1;
1185 $this->runLength[$head]++;
1189 $demerit += $this->
calcN1N3($head+1);
1193 $this->runLength[0] = 1;
1196 $this->runLength[0] = -1;
1198 $this->runLength[$head] = 1;
1202 $this->runLength[$head] = 1;
1204 $this->runLength[$head]++;
1208 $demerit += $this->
calcN1N3($head+1);
1221 $minDemerit = PHP_INT_MAX;
1223 $bestMask = array();
1224 $checked_masks = array(0, 1, 2, 3, 4, 5, 6, 7);
1225 if (QR_FIND_FROM_RANDOM !==
false) {
1226 $howManuOut = 8 - (QR_FIND_FROM_RANDOM % 9);
1227 for (
$i = 0;
$i < $howManuOut; ++
$i) {
1228 $remPos = rand (0, count($checked_masks)-1);
1229 unset($checked_masks[$remPos]);
1230 $checked_masks = array_values($checked_masks);
1234 foreach ($checked_masks as
$i) {
1241 $demerit = (int)((
int)(abs($blacks - 50) / 5) * N4);
1243 if ($demerit < $minDemerit) {
1244 $minDemerit = $demerit;
1263 if ($pos >= strlen($str)) {
1266 return ((ord($str[$pos]) >= ord(
'0'))&&(ord($str[$pos]) <= ord(
'9')));
1276 if ($pos >= strlen($str)) {
1279 return ($this->
lookAnTable(ord($str[$pos])) >= 0);
1288 if ($pos >= strlen($this->dataStr)) {
1291 $c = $this->dataStr[$pos];
1292 if ($this->
isdigitat($this->dataStr, $pos)) {
1294 } elseif ($this->
isalnumat($this->dataStr, $pos)) {
1296 } elseif ($this->hint == QR_MODE_KJ) {
1297 if ($pos+1 < strlen($this->dataStr)) {
1298 $d = $this->dataStr[$pos+1];
1299 $word = (ord(
$c) << 8) | ord(
$d);
1300 if (($word >= 0x8140 && $word <= 0x9ffc) OR ($word >= 0xe040 && $word <= 0xebbf)) {
1315 while($this->
isdigitat($this->dataStr, $p)) {
1320 if ($mode == QR_MODE_8B) {
1325 return $this->
eat8();
1328 if ($mode == QR_MODE_AN) {
1333 return $this->
eatAn();
1336 $this->items = $this->
appendNewInputItem($this->items, QR_MODE_NM, $run, str_split($this->dataStr));
1348 while($this->
isalnumat($this->dataStr, $p)) {
1349 if ($this->
isdigitat($this->dataStr, $p)) {
1351 while($this->
isdigitat($this->dataStr, $q)) {
1367 if (!$this->
isalnumat($this->dataStr, $p)) {
1372 return $this->
eat8();
1375 $this->items = $this->
appendNewInputItem($this->items, QR_MODE_AN, $run, str_split($this->dataStr));
1388 $this->items = $this->
appendNewInputItem($this->items, QR_MODE_KJ, $p, str_split($this->dataStr));
1400 $dataStrLen = strlen($this->dataStr);
1401 while($p < $dataStrLen) {
1403 if ($mode == QR_MODE_KJ) {
1406 if ($mode == QR_MODE_NM) {
1408 while($this->
isdigitat($this->dataStr, $q)) {
1419 } elseif ($mode == QR_MODE_AN) {
1421 while($this->
isalnumat($this->dataStr, $q)) {
1437 $this->items = $this->
appendNewInputItem($this->items, QR_MODE_8B, $run, str_split($this->dataStr));
1446 while (strlen($this->dataStr) > 0) {
1450 $length = $this->
eatNum();
1454 $length = $this->
eatAn();
1458 if (
$hint == QR_MODE_KJ) {
1461 $length = $this->
eat8();
1466 $length = $this->
eat8();
1476 $this->dataStr = substr($this->dataStr, $length);
1485 $stringLen = strlen($this->dataStr);
1487 while ($p < $stringLen) {
1488 $mode = $this->
identifyMode(substr($this->dataStr, $p), $this->hint);
1489 if ($mode == QR_MODE_KJ) {
1492 if ((ord($this->dataStr[$p]) >= ord(
'a')) AND (ord($this->dataStr[$p]) <= ord(
'z'))) {
1493 $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
1515 if (count($setData) <
$size) {
1516 $setData = array_merge($setData, array_fill(0, (
$size - count($setData)), 0));
1521 $inputitem = array();
1522 $inputitem[
'mode'] = $mode;
1523 $inputitem[
'size'] =
$size;
1524 $inputitem[
'data'] = $setData;
1525 $inputitem[
'bstream'] = $bstream;
1536 $words = (int)($inputitem[
'size'] / 3);
1537 $inputitem[
'bstream'] = array();
1539 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, $val);
1541 for (
$i=0;
$i < $words; ++
$i) {
1542 $val = (ord($inputitem[
'data'][
$i*3 ]) - ord(
'0')) * 100;
1543 $val += (ord($inputitem[
'data'][$i*3+1]) - ord(
'0')) * 10;
1544 $val += (ord($inputitem[
'data'][$i*3+2]) - ord(
'0'));
1545 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 10, $val);
1547 if ($inputitem[
'size'] - $words * 3 == 1) {
1548 $val = ord($inputitem[
'data'][$words*3]) - ord(
'0');
1549 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, $val);
1550 } elseif (($inputitem[
'size'] - ($words * 3)) == 2) {
1551 $val = (ord($inputitem[
'data'][$words*3 ]) - ord(
'0')) * 10;
1552 $val += (ord($inputitem[
'data'][$words*3+1]) - ord(
'0'));
1553 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 7, $val);
1565 $words = (int)($inputitem[
'size'] / 2);
1566 $inputitem[
'bstream'] = array();
1567 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, 0x02);
1569 for (
$i=0;
$i < $words; ++
$i) {
1570 $val = (int)($this->
lookAnTable(ord($inputitem[
'data'][
$i*2])) * 45);
1571 $val += (int)($this->
lookAnTable(ord($inputitem[
'data'][($i*2)+1])));
1572 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 11, $val);
1574 if ($inputitem[
'size'] & 1) {
1575 $val = $this->
lookAnTable(ord($inputitem[
'data'][($words * 2)]));
1576 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 6, $val);
1588 $inputitem[
'bstream'] = array();
1589 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, 0x4);
1591 for (
$i=0;
$i < $inputitem[
'size']; ++
$i) {
1592 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 8, ord($inputitem[
'data'][
$i]));
1604 $inputitem[
'bstream'] = array();
1605 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, 0x8);
1607 for (
$i=0;
$i<$inputitem[
'size'];
$i+=2) {
1608 $val = (ord($inputitem[
'data'][
$i]) << 8) | ord($inputitem[
'data'][$i+1]);
1609 if ($val <= 0x9ffc) {
1614 $h = ($val >> 8) * 0xc0;
1615 $val = ($val & 0xff) +
$h;
1616 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 13, $val);
1627 $inputitem[
'bstream'] = array();
1628 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, 0x03);
1629 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, ord($inputitem[
'data'][1]) - 1);
1630 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, ord($inputitem[
'data'][0]) - 1);
1631 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 8, ord($inputitem[
'data'][2]));
1642 $inputitem[
'bstream'] = array();
1644 if ($inputitem[
'size'] > $words) {
1645 $st1 = $this->
newInputItem($inputitem[
'mode'], $words, $inputitem[
'data']);
1646 $st2 = $this->
newInputItem($inputitem[
'mode'], $inputitem[
'size'] - $words, array_slice($inputitem[
'data'], $words));
1649 $inputitem[
'bstream'] = array();
1650 $inputitem[
'bstream'] = $this->
appendBitstream($inputitem[
'bstream'], $st1[
'bstream']);
1651 $inputitem[
'bstream'] = $this->
appendBitstream($inputitem[
'bstream'], $st2[
'bstream']);
1653 switch($inputitem[
'mode']) {
1698 if (!empty($newitem)) {
1713 if (
$size > MAX_STRUCTURED_SYMBOLS) {
1716 if ((
$index <= 0) OR (
$index > MAX_STRUCTURED_SYMBOLS)) {
1721 array_unshift(
$items, $entry);
1732 foreach (
$items as $item) {
1733 if ($item[
'mode'] != QR_MODE_ST) {
1734 for (
$i=$item[
'size']-1;
$i>=0; --
$i) {
1735 $parity ^= $item[
'data'][
$i];
1750 if ((ord(
$data[
$i]) < ord(
'0')) OR (ord(
$data[$i]) > ord(
'9'))){
1763 return ((
$c > 127)?-1:$this->anTable[
$c]);
1808 $bits = (int)(
$size * 5.5);
1821 return (
int)(
$size * 8);
1830 return (
int)(
$size * 6.5);
1845 if (($val < 0x8140) OR (($val > 0x9ffc) AND ($val < 0xe040)) OR ($val > 0xebbf)) {
1897 foreach (
$items as $item) {
1898 switch($item[
'mode']) {
1916 return STRUCTURE_HEADER_BITS;
1924 $num = (int)(($item[
'size'] +
$m - 1) /
$m);
1925 $bits += $num * (4 +
$l);
1960 $chunks = (int)($payload / 10);
1961 $remain = $payload - $chunks * 10;
1962 $size = $chunks * 3;
1965 } elseif ($remain >= 4) {
1971 $chunks = (int)($payload / 11);
1972 $remain = $payload - $chunks * 11;
1973 $size = $chunks * 2;
1980 $size = (int)($payload / 8);
1984 $size = (int)(($payload / 13) * 2);
1988 $size = (int)($payload / 8);
2000 if (
$size > $maxsize) {
2028 if ($ver > $this->version) {
2029 $this->version = $ver;
2041 } elseif ($ver > $this->version) {
2042 $this->version = $ver;
2056 if (is_null($bstream)) {
2059 $bits = count($bstream);
2060 $maxwords = $this->
getDataLength($this->version, $this->level);
2061 $maxbits = $maxwords * 8;
2062 if ($maxbits == $bits) {
2065 if ($maxbits - $bits < 5) {
2066 return $this->
appendNum($bstream, $maxbits - $bits, 0);
2069 $words = (int)(($bits + 7) / 8);
2071 $padding = $this->
appendNum($padding, $words * 8 - $bits + 4, 0);
2072 $padlen = $maxwords - $words;
2075 for (
$i=0;
$i<$padlen; ++
$i) {
2076 $padbuf[
$i] = (
$i&1)?0x11:0xec;
2078 $padding = $this->
appendBytes($padding, $padlen, $padbuf);
2094 foreach (
$items as $item) {
2130 return array_fill(0, $setLength, 0);
2141 $mask = 1 << ($bits - 1);
2142 for (
$i=0;
$i<$bits; ++
$i) {
2164 for ($j=0; $j<8; ++$j) {
2184 if ((!is_array($append)) OR (count($append) == 0)) {
2187 if (count($bitstream) == 0) {
2190 return array_values(array_merge($bitstream, $append));
2229 if (is_null($bstream)) {
2232 $size = count($bstream);
2236 $data = array_fill(0, (
int)((
$size + 7) / 8), 0);
2237 $bytes = (int)(
$size / 8);
2239 for (
$i=0;
$i<$bytes;
$i++) {
2241 for ($j=0; $j<8; $j++) {
2250 for ($j=0; $j<(
$size & 7); $j++) {
2274 $srctab[
$y] = substr_replace($srctab[
$y], ($replLen !==
false)?substr($repl,0,$replLen):$repl,
$x, ($replLen !==
false)?$replLen:strlen($repl));
2304 return $this->capacity[
$version][QRCAP_WIDTH];
2313 return $this->capacity[
$version][QRCAP_REMINDER];
2323 for (
$i = 1;
$i <= QRSPEC_VERSION_MAX; ++
$i) {
2324 $words = ($this->capacity[
$i][QRCAP_WORDS] - $this->capacity[
$i][QRCAP_EC][
$level]);
2325 if ($words >=
$size) {
2340 if ($mode == QR_MODE_ST) {
2350 return $this->lengthTableBits[$mode][
$l];
2360 if ($mode == QR_MODE_ST) {
2370 $bits = $this->lengthTableBits[$mode][
$l];
2371 $words = (1 << $bits) - 1;
2372 if ($mode == QR_MODE_KJ) {
2386 if (count($spec) < 5) {
2387 $spec = array(0, 0, 0, 0, 0);
2396 $spec[2] = (int)($ecc /
$b1);
2401 $spec[1] = (int)(
$data / (
$b1 + $b2));
2402 $spec[2] = (int)($ecc / (
$b1 + $b2));
2404 $spec[4] = $spec[1] + 1;
2418 "\xa1\xa1\xa1\xa1\xa1",
2419 "\xa1\xa0\xa0\xa0\xa1",
2420 "\xa1\xa0\xa1\xa0\xa1",
2421 "\xa1\xa0\xa0\xa0\xa1",
2422 "\xa1\xa1\xa1\xa1\xa1" 2426 for (
$y=0;
$y < 5;
$y++) {
2449 if (
$w *
$w - 3 == 1) {
2455 $cx = $this->alignmentPattern[
$version][0];
2457 for (
$x=1;
$x < $wo; ++
$x) {
2462 $cy = $this->alignmentPattern[
$version][0];
2463 for (
$y=0;
$y < $wo; ++
$y) {
2464 $cx = $this->alignmentPattern[
$version][0];
2465 for (
$x=0;
$x < $wo; ++
$x) {
2483 return $this->versionPattern[(
$version - 7)];
2511 "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
2512 "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
2513 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
2514 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
2515 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
2516 "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
2517 "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" 2519 for (
$y=0;
$y < 7;
$y++) {
2532 $frameLine = str_repeat (
"\0",
$width);
2540 for (
$y=0;
$y < 7; ++
$y) {
2543 $frame[$yOffset][7] =
"\xc0";
2546 $setPattern = str_repeat(
"\xc0", 8);
2551 $setPattern = str_repeat(
"\x84", 9);
2555 for (
$y=0;
$y < 8; ++
$y,++$yOffset) {
2557 $frame[$yOffset][8] =
"\x84";
2561 for (
$i=1;
$i < $wo; ++
$i) {
2599 if (!isset($this->frames[
$version])) {
2602 if (is_null($this->frames[$version])) {
2614 return ($spec[0] + $spec[3]);
2677 return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]);
2686 return ($spec[0] + $spec[3]) * $spec[2];
2703 protected function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) {
2704 foreach ($this->rsitems as $rs) {
2705 if (($rs[
'pad'] != $pad) OR ($rs[
'nroots'] != $nroots) OR ($rs[
'mm'] != $symsize)
2706 OR ($rs[
'gfpoly'] != $gfpoly) OR ($rs[
'fcr'] != $fcr) OR ($rs[
'prim'] != $prim)) {
2711 $rs = $this->
init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
2712 array_unshift($this->rsitems, $rs);
2727 while (
$x >= $rs[
'nn']) {
2729 $x = (
$x >> $rs[
'mm']) + (
$x & $rs[
'nn']);
2744 protected function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) {
2748 if (($symsize < 0) OR ($symsize > 8)) {
2751 if (($fcr < 0) OR ($fcr >= (1<<$symsize))) {
2754 if (($prim <= 0) OR ($prim >= (1<<$symsize))) {
2757 if (($nroots < 0) OR ($nroots >= (1<<$symsize))) {
2760 if (($pad < 0) OR ($pad >= ((1<<$symsize) -1 - $nroots))) {
2764 $rs[
'mm'] = $symsize;
2765 $rs[
'nn'] = (1 << $symsize) - 1;
2767 $rs[
'alpha_to'] = array_fill(0, ($rs[
'nn'] + 1), 0);
2768 $rs[
'index_of'] = array_fill(0, ($rs[
'nn'] + 1), 0);
2773 $rs[
'index_of'][0] = $A0;
2774 $rs[
'alpha_to'][$A0] = 0;
2776 for (
$i=0;
$i<$rs[
'nn']; ++
$i) {
2777 $rs[
'index_of'][$sr] =
$i;
2778 $rs[
'alpha_to'][
$i] = $sr;
2780 if ($sr & (1 << $symsize)) {
2790 $rs[
'genpoly'] = array_fill(0, ($nroots + 1), 0);
2792 $rs[
'prim'] = $prim;
2793 $rs[
'nroots'] = $nroots;
2794 $rs[
'gfpoly'] = $gfpoly;
2796 for ($iprim=1; ($iprim % $prim) != 0; $iprim += $rs[
'nn']) {
2799 $rs[
'iprim'] = (int)($iprim / $prim);
2800 $rs[
'genpoly'][0] = 1;
2802 $rs[
'genpoly'][
$i+1] = 1;
2804 for ($j =
$i; $j > 0; --$j) {
2805 if ($rs[
'genpoly'][$j] != 0) {
2806 $rs[
'genpoly'][$j] = $rs[
'genpoly'][$j-1] ^ $rs[
'alpha_to'][$this->
modnn($rs, $rs[
'index_of'][$rs[
'genpoly'][$j]] + $root)];
2808 $rs[
'genpoly'][$j] = $rs[
'genpoly'][$j-1];
2812 $rs[
'genpoly'][0] = $rs[
'alpha_to'][$this->
modnn($rs, $rs[
'index_of'][$rs[
'genpoly'][0]] + $root)];
2815 for (
$i = 0;
$i <= $nroots; ++
$i) {
2816 $rs[
'genpoly'][
$i] = $rs[
'index_of'][$rs[
'genpoly'][
$i]];
2831 $ALPHA_TO =& $rs[
'alpha_to'];
2832 $INDEX_OF =& $rs[
'index_of'];
2833 $GENPOLY =& $rs[
'genpoly'];
2834 $NROOTS =& $rs[
'nroots'];
2836 $PRIM =& $rs[
'prim'];
2837 $IPRIM =& $rs[
'iprim'];
2840 $parity = array_fill(0, $NROOTS, 0);
2841 for (
$i=0;
$i < ($NN - $NROOTS - $PAD);
$i++) {
2842 $feedback = $INDEX_OF[
$data[
$i] ^ $parity[0]];
2843 if ($feedback != $A0) {
2847 $feedback = $this->
modnn($rs, $NN - $GENPOLY[$NROOTS] + $feedback);
2848 for ($j=1; $j < $NROOTS; ++$j) {
2849 $parity[$j] ^= $ALPHA_TO[$this->
modnn($rs, $feedback + $GENPOLY[($NROOTS - $j)])];
2853 array_shift($parity);
2854 if ($feedback != $A0) {
2855 array_push($parity, $ALPHA_TO[$this->
modnn($rs, $feedback + $GENPOLY[0])]);
2857 array_push($parity, 0);
encodeModeKanji($inputitem, $version)
encodeModeKanji
maximumWords($mode, $version)
Return the maximum length for the mode and version.
checkModeAn($size, $data)
checkModeAn
getRemainder($version)
Return the numer of remainder bits.
rsDataLength($spec)
Return data length.
putFinderPattern($frame, $ox, $oy)
Put a finder pattern.
newFromBytes($size, $data)
Return new bitstream from bytes.
estimateBitsModeAn($size)
estimateBitsModeAn
getEccSpec($version, $level, $spec)
Return an array of ECC specification.
calcN1N3($length)
calcN1N3
getBarcodeArray()
Returns a barcode array which is readable by TCPDF.
estimateBitsModeKanji($size)
estimateBitsModeKanji
calcParity($items)
calcParity
setFrameAt($at, $val)
Set frame value at specified position.
$rsitems
Reed-Solomon items.
checkModeNum($size, $data)
checkModeNum
encodeMask($mask)
Encode mask.
$level
Levels of error correction.
$formatInfo
Array Format information.
encodeModeAn($inputitem, $version)
encodeModeAn
newFromNum($bits, $num)
Return new bitstream from number.
encodeBitStream($inputitem, $version)
encodeBitStream
rsDataCodes2($spec)
Return data codes 2.
makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly=false)
makeMaskNo
getWidth($version)
Return the width of the symbol for the version.
rsEccCodes1($spec)
Return ecc codes 1.
rsDataCodes1($spec)
Return data codes 1.
getFrameAt($at)
Get frame value at specified position.
rsBlockNum2($spec)
Return block number 2.
putAlignmentMarker($frame, $ox, $oy)
Put an alignment marker.
getBitStream($items)
Returns a stream of bits.
rsBlockNum1($spec)
Return block number 1.
checkModeKanji($size, $data)
checkModeKanji
lengthOfCode($mode, $version, $bits)
lengthOfCode
generateMaskNo($maskNo, $width, $frame)
Return bitmask.
estimateBitStreamSize($items, $version)
estimateBitStreamSize
isdigitat($str, $pos)
Return true if the character at specified position is a number.
createFrame($version)
Return a copy of initialized frame.
__construct($code, $eclevel='L')
This is the class constructor.
$dataStr
Input data string.
newFrame($version)
Set new frame for the specified version.
$capacity
Array Table of the capacity of symbols.
appendNum($bitstream, $bits, $num)
Append one bitstream created from number to another.
estimateBitsMode8($size)
estimateBitsMode8
makeMask($width, $frame, $maskNo, $level)
makeMask
getECCLength($version, $level)
Return maximum error correction code length (bytes) for the version.
$lengthTableBits
Array Length indicator.
estimateVersion($items)
estimateVersion
encode_rs_char($rs, $data, $parity)
Encode a Reed-Solomon codec and returns the parity array.
getVersionPattern($version)
Return BCH encoded version information pattern that is used for the symbol of version 7 or greater...
getDataLength($version, $level)
Return maximum data code length (bytes) for the version.
$anTable
Alphabet-numeric convesion table.
lookAnTable($c)
Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19).
appendBytes($bitstream, $size, $data)
Append one bitstream created from bytes to another.
getCode()
Return Reed-Solomon block code.
init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
Initialize a Reed-Solomon codec and returns an array of values.
$casesensitive
Boolean flag, if true the input string will be converted to uppercase.
convertData($items)
convertData
appendNewInputItem($items, $mode, $size, $data)
Append data to an input object.
rsEccCodes2($spec)
Return ecc codes 2.
check($mode, $size, $data)
Validate the input data.
getNextPosition()
Return the next frame position.
putAlignmentPattern($version, $frame, $width)
Put an alignment pattern.
encodeModeStructure($inputitem)
encodeModeStructure
init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
Initialize a Reed-Solomon codec and add it to existing rsitems.
getByteStream($items)
Pack all bit streams padding bits into a byte array.
rsEccLength($spec)
Return ecc length.
appendBitstream($bitstream, $append)
Append one bitstream to another.
appendPaddingBit($bstream)
Append Padding Bit to bitstream.
binarize($frame)
Convert the frame in binary form.
Class to create QR-code arrays for TCPDF class.
$eccTable
Array Table of the error correction code (Reed-Solomon block).
encodeModeNum($inputitem, $version)
encodeModeNum
isalnumat($str, $pos)
Return true if the character at specified position is an alphanumeric character.
$structured
Structured QR code (not supported yet).
rsBlockNum($spec)
Return block number 0.
bitstreamToByte($bstream)
Convert bitstream to bytes.
encodeMode8($inputitem, $version)
encodeMode8
encodeString($string)
Encode the input string to QR code.
estimateBitsModeNum($size)
estimateBitsModeNum
qrstrset($srctab, $x, $y, $repl, $replLen=false)
Replace a value on the array at the specified position.
identifyMode($pos)
identifyMode
init($spec)
Initialize code.
createBitStream($items)
createBitStream
$ecccode
Error correction code.
lengthIndicator($mode, $version)
Return the size of length indicator for the mode and version.
$barcode_array
Barcode array to be returned which is readable by TCPDF.
mask($width, $frame, $level)
mask
mergeBitStream($items)
mergeBitStream
$rsblocks
Reed-Solomon blocks.
writeFormatInformation($width, &$frame, $mask, $level)
Write Format Information on frame and returns the number of black bits.
newInputItem($mode, $size, $data, $bstream=null)
newInputItem
$versionPattern
Array Version information pattern (BCH coded).
insertStructuredAppendHeader($items, $size, $index, $parity)
insertStructuredAppendHeader
evaluateSymbol($width, $frame)
evaluateSymbol
getFormatInfo($mask, $level)
Return BCH encoded format information pattern.
for($i=6; $i< 13; $i++) for($i=1; $i< 13; $i++) $d
$eccLength
Error correction length.
getMinimumVersion($size, $level)
Return a version number that satisfies the input code length.
$alignmentPattern
Array Positions of alignment patterns.
allocate($setLength)
Return an array with zeros.