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)
641 if ((is_null($code)) OR ($code ==
'\0') OR ($code ==
'')) {
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)) {
660 $qrTab = $this->
binarize($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);
723 if (is_null($this->datacode)) {
726 $spec = $this->
getEccSpec($this->version, $this->level, $spec);
730 $this->ecccode = array_fill(0, $this->eccLength, 0);
737 $this->width = $this->
getWidth($this->version);
738 $this->frame = $this->
newFrame($this->version);
739 $this->x = $this->width - 1;
740 $this->y = $this->width - 1;
747 for ($j=0; $j<8; $j++) {
755 for ($i=0; $i<$j; $i++) {
760 $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
762 if (QR_FIND_BEST_MASK) {
763 $masked = $this->
mask($this->width, $this->frame, $this->level);
765 $masked = $this->
makeMask($this->width, $this->frame, (intval(QR_DEFAULT_MASK) % 8), $this->level);
768 $masked = $this->
makeMask($this->width, $this->frame, $mask, $this->level);
770 if ($masked == NULL) {
773 $this->data = $masked;
786 $this->frame[$at[
'y']][$at[
'x']] = chr($val);
795 return ord($this->frame[$at[
'y']][$at[
'x']]);
804 if ($this->bit == -1) {
806 return array(
'x'=>$this->x,
'y'=>$this->y);
811 if ($this->bit == 0) {
819 if ($this->dir < 0) {
840 if ((
$x < 0) OR (
$y < 0)) {
845 }
while(ord($this->frame[
$y][
$x]) & 0x80);
846 return array(
'x'=>$x,
'y'=>
$y);
858 protected function init($spec) {
861 $rs = $this->
init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
866 for ($i=0; $i < $endfor; ++$i) {
867 $ecc = array_slice($this->ecccode, $eccPos);
868 $this->rsblocks[$blockNo] = array();
869 $this->rsblocks[$blockNo][
'dataLength'] = $dl;
870 $this->rsblocks[$blockNo][
'data'] = array_slice($this->datacode, $dataPos);
871 $this->rsblocks[$blockNo][
'eccLength'] = $el;
872 $ecc = $this->
encode_rs_char($rs, $this->rsblocks[$blockNo][
'data'], $ecc);
873 $this->rsblocks[$blockNo][
'ecc'] = $ecc;
874 $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
884 $rs = $this->
init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
889 for ($i=0; $i < $endfor; ++$i) {
890 $ecc = array_slice($this->ecccode, $eccPos);
891 $this->rsblocks[$blockNo] = array();
892 $this->rsblocks[$blockNo][
'dataLength'] = $dl;
893 $this->rsblocks[$blockNo][
'data'] = array_slice($this->datacode, $dataPos);
894 $this->rsblocks[$blockNo][
'eccLength'] = $el;
895 $ecc = $this->
encode_rs_char($rs, $this->rsblocks[$blockNo][
'data'], $ecc);
896 $this->rsblocks[$blockNo][
'ecc'] = $ecc;
897 $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc);
910 if ($this->count < $this->dataLength) {
913 if ($col >= $this->rsblocks[0][
'dataLength']) {
916 $ret = $this->rsblocks[
$row][
'data'][$col];
917 } elseif ($this->count < $this->dataLength + $this->eccLength) {
920 $ret = $this->rsblocks[
$row][
'ecc'][$col];
943 for ($i=0; $i<8; ++$i) {
954 $frame[$i + 1][8] = chr($v);
956 $format = $format >> 1;
958 for ($i=0; $i<7; ++$i) {
969 $frame[8][6 - $i] = chr($v);
971 $format = $format >> 1;
983 return (
$x +
$y) & 1;
1013 return (
$x +
$y) % 3;
1023 return (((
int)(
$y / 2)) + ((
int)(
$x / 3))) & 1;
1033 return ((
$x *
$y) & 1) + (
$x *
$y) % 3;
1043 return (((
$x *
$y) & 1) + (
$x * $y) % 3) & 1;
1053 return (((
$x *
$y) % 3) + ((
$x + $y) & 1)) & 1;
1064 $bitMask = array_fill(0,
$width, array_fill(0,
$width, 0));
1068 $bitMask[
$y][
$x] = 0;
1070 $maskFunc = call_user_func(array($this,
'mask'.$maskNo), $x,
$y);
1071 $bitMask[
$y][
$x] = ($maskFunc == 0)?1:0;
1097 if ($bitMask[
$y][
$x] == 1) {
1098 $d[
$y][
$x] = chr(ord($s[
$y][
$x]) ^ ((
int)($bitMask[
$y][$x])));
1100 $b += (int)(ord(
$d[
$y][
$x]) & 1);
1115 $masked = array_fill(0,
$width, str_repeat(
"\0",
$width));
1128 for ($i=0; $i<$length; ++$i) {
1129 if ($this->runLength[$i] >= 5) {
1130 $demerit += (N1 + ($this->runLength[$i] - 5));
1133 if (($i >= 3) AND ($i < ($length-2)) AND ($this->runLength[$i] % 3 == 0)) {
1134 $fact = (int)($this->runLength[$i] / 3);
1135 if (($this->runLength[$i-2] == $fact)
1136 AND ($this->runLength[$i-1] == $fact)
1137 AND ($this->runLength[$i+1] == $fact)
1138 AND ($this->runLength[$i+2] == $fact)) {
1139 if (($this->runLength[$i-3] < 0) OR ($this->runLength[$i-3] >= (4 * $fact))) {
1141 } elseif ((($i+3) >= $length) OR ($this->runLength[$i+3] >= (4 * $fact))) {
1162 $this->runLength[0] = 1;
1168 if ((
$x > 0) AND (
$y > 0)) {
1169 $b22 = ord($frameY[
$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
1170 $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
1171 if (($b22 | ($w22 ^ 1)) & 1) {
1175 if ((
$x == 0) AND (ord($frameY[
$x]) & 1)) {
1176 $this->runLength[0] = -1;
1178 $this->runLength[$head] = 1;
1180 if ((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
1182 $this->runLength[$head] = 1;
1184 $this->runLength[$head]++;
1188 $demerit += $this->
calcN1N3($head+1);
1192 $this->runLength[0] = 1;
1195 $this->runLength[0] = -1;
1197 $this->runLength[$head] = 1;
1201 $this->runLength[$head] = 1;
1203 $this->runLength[$head]++;
1207 $demerit += $this->
calcN1N3($head+1);
1220 $minDemerit = PHP_INT_MAX;
1222 $bestMask = array();
1223 $checked_masks = array(0, 1, 2, 3, 4, 5, 6, 7);
1224 if (QR_FIND_FROM_RANDOM !==
false) {
1225 $howManuOut = 8 - (QR_FIND_FROM_RANDOM % 9);
1226 for ($i = 0; $i < $howManuOut; ++$i) {
1227 $remPos = rand (0, count($checked_masks)-1);
1228 unset($checked_masks[$remPos]);
1229 $checked_masks = array_values($checked_masks);
1233 foreach ($checked_masks as $i) {
1234 $mask = array_fill(0,
$width, str_repeat(
"\0",
$width));
1240 $demerit = (int)((
int)(abs($blacks - 50) / 5) * N4);
1242 if ($demerit < $minDemerit) {
1243 $minDemerit = $demerit;
1262 if ($pos >= strlen($str)) {
1265 return ((ord($str[$pos]) >= ord(
'0'))&&(ord($str[$pos]) <= ord(
'9')));
1275 if ($pos >= strlen($str)) {
1278 return ($this->
lookAnTable(ord($str[$pos])) >= 0);
1287 if ($pos >= strlen($this->dataStr)) {
1290 $c = $this->dataStr[$pos];
1291 if ($this->
isdigitat($this->dataStr, $pos)) {
1293 } elseif ($this->
isalnumat($this->dataStr, $pos)) {
1295 } elseif ($this->hint == QR_MODE_KJ) {
1296 if ($pos+1 < strlen($this->dataStr)) {
1297 $d = $this->dataStr[$pos+1];
1298 $word = (ord($c) << 8) | ord(
$d);
1299 if (($word >= 0x8140 && $word <= 0x9ffc) OR ($word >= 0xe040 && $word <= 0xebbf)) {
1314 while($this->
isdigitat($this->dataStr, $p)) {
1319 if ($mode == QR_MODE_8B) {
1324 return $this->
eat8();
1327 if ($mode == QR_MODE_AN) {
1332 return $this->
eatAn();
1335 $this->items = $this->
appendNewInputItem($this->items, QR_MODE_NM, $run, str_split($this->dataStr));
1347 while($this->
isalnumat($this->dataStr, $p)) {
1348 if ($this->
isdigitat($this->dataStr, $p)) {
1350 while($this->
isdigitat($this->dataStr, $q)) {
1366 if (!$this->
isalnumat($this->dataStr, $p)) {
1371 return $this->
eat8();
1374 $this->items = $this->
appendNewInputItem($this->items, QR_MODE_AN, $run, str_split($this->dataStr));
1387 $this->items = $this->
appendNewInputItem($this->items, QR_MODE_KJ, $p, str_split($this->dataStr));
1399 $dataStrLen = strlen($this->dataStr);
1400 while($p < $dataStrLen) {
1402 if ($mode == QR_MODE_KJ) {
1405 if ($mode == QR_MODE_NM) {
1407 while($this->
isdigitat($this->dataStr, $q)) {
1418 } elseif ($mode == QR_MODE_AN) {
1420 while($this->
isalnumat($this->dataStr, $q)) {
1436 $this->items = $this->
appendNewInputItem($this->items, QR_MODE_8B, $run, str_split($this->dataStr));
1445 while (strlen($this->dataStr) > 0) {
1449 $length = $this->
eatNum();
1453 $length = $this->
eatAn();
1457 if (
$hint == QR_MODE_KJ) {
1460 $length = $this->
eat8();
1465 $length = $this->
eat8();
1475 $this->dataStr = substr($this->dataStr, $length);
1484 $stringLen = strlen($this->dataStr);
1486 while ($p < $stringLen) {
1487 $mode = $this->
identifyMode(substr($this->dataStr, $p), $this->hint);
1488 if ($mode == QR_MODE_KJ) {
1491 if ((ord($this->dataStr[$p]) >= ord(
'a')) AND (ord($this->dataStr[$p]) <= ord(
'z'))) {
1492 $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
1514 if (count($setData) <
$size) {
1515 $setData = array_merge($setData, array_fill(0, (
$size - count($setData)), 0));
1520 $inputitem = array();
1521 $inputitem[
'mode'] = $mode;
1522 $inputitem[
'size'] =
$size;
1523 $inputitem[
'data'] = $setData;
1524 $inputitem[
'bstream'] = $bstream;
1535 $words = (int)($inputitem[
'size'] / 3);
1536 $inputitem[
'bstream'] = array();
1538 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, $val);
1540 for ($i=0; $i < $words; ++$i) {
1541 $val = (ord($inputitem[
'data'][$i*3 ]) - ord(
'0')) * 100;
1542 $val += (ord($inputitem[
'data'][$i*3+1]) - ord(
'0')) * 10;
1543 $val += (ord($inputitem[
'data'][$i*3+2]) - ord(
'0'));
1544 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 10, $val);
1546 if ($inputitem[
'size'] - $words * 3 == 1) {
1547 $val = ord($inputitem[
'data'][$words*3]) - ord(
'0');
1548 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, $val);
1549 } elseif (($inputitem[
'size'] - ($words * 3)) == 2) {
1550 $val = (ord($inputitem[
'data'][$words*3 ]) - ord(
'0')) * 10;
1551 $val += (ord($inputitem[
'data'][$words*3+1]) - ord(
'0'));
1552 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 7, $val);
1564 $words = (int)($inputitem[
'size'] / 2);
1565 $inputitem[
'bstream'] = array();
1566 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, 0x02);
1568 for ($i=0; $i < $words; ++$i) {
1569 $val = (int)($this->
lookAnTable(ord($inputitem[
'data'][$i*2])) * 45);
1570 $val += (int)($this->
lookAnTable(ord($inputitem[
'data'][($i*2)+1])));
1571 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 11, $val);
1573 if ($inputitem[
'size'] & 1) {
1574 $val = $this->
lookAnTable(ord($inputitem[
'data'][($words * 2)]));
1575 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 6, $val);
1587 $inputitem[
'bstream'] = array();
1588 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, 0x4);
1590 for ($i=0; $i < $inputitem[
'size']; ++$i) {
1591 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 8, ord($inputitem[
'data'][$i]));
1603 $inputitem[
'bstream'] = array();
1604 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, 0x8);
1606 for ($i=0; $i<$inputitem[
'size']; $i+=2) {
1607 $val = (ord($inputitem[
'data'][$i]) << 8) | ord($inputitem[
'data'][$i+1]);
1608 if ($val <= 0x9ffc) {
1613 $h = ($val >> 8) * 0xc0;
1614 $val = ($val & 0xff) + $h;
1615 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 13, $val);
1626 $inputitem[
'bstream'] = array();
1627 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, 0x03);
1628 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, ord($inputitem[
'data'][1]) - 1);
1629 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 4, ord($inputitem[
'data'][0]) - 1);
1630 $inputitem[
'bstream'] = $this->
appendNum($inputitem[
'bstream'], 8, ord($inputitem[
'data'][2]));
1641 $inputitem[
'bstream'] = array();
1643 if ($inputitem[
'size'] > $words) {
1644 $st1 = $this->
newInputItem($inputitem[
'mode'], $words, $inputitem[
'data']);
1645 $st2 = $this->
newInputItem($inputitem[
'mode'], $inputitem[
'size'] - $words, array_slice($inputitem[
'data'], $words));
1648 $inputitem[
'bstream'] = array();
1649 $inputitem[
'bstream'] = $this->
appendBitstream($inputitem[
'bstream'], $st1[
'bstream']);
1650 $inputitem[
'bstream'] = $this->
appendBitstream($inputitem[
'bstream'], $st2[
'bstream']);
1652 switch($inputitem[
'mode']) {
1697 if (!empty($newitem)) {
1712 if (
$size > MAX_STRUCTURED_SYMBOLS) {
1715 if (($index <= 0) OR ($index > MAX_STRUCTURED_SYMBOLS)) {
1718 $buf = array(
$size, $index, $parity);
1720 array_unshift(
$items, $entry);
1731 foreach (
$items as $item) {
1732 if ($item[
'mode'] != QR_MODE_ST) {
1733 for ($i=$item[
'size']-1; $i>=0; --$i) {
1734 $parity ^= $item[
'data'][$i];
1748 for ($i=0; $i<
$size; ++$i) {
1749 if ((ord(
$data[$i]) < ord(
'0')) OR (ord(
$data[$i]) > ord(
'9'))){
1762 return (($c > 127)?-1:$this->anTable[$c]);
1772 for ($i=0; $i<
$size; ++$i) {
1786 $w = (int)(
$size / 3);
1788 switch(
$size - ($w * 3)) {
1807 $bits = (int)(
$size * 5.5);
1820 return (
int)(
$size * 8);
1829 return (
int)(
$size * 6.5);
1842 for ($i=0; $i<
$size; $i+=2) {
1843 $val = (ord(
$data[$i]) << 8) | ord(
$data[$i+1]);
1844 if (($val < 0x8140) OR (($val > 0x9ffc) AND ($val < 0xe040)) OR ($val > 0xebbf)) {
1896 foreach (
$items as $item) {
1897 switch($item[
'mode']) {
1915 return STRUCTURE_HEADER_BITS;
1923 $num = (int)(($item[
'size'] + $m - 1) / $m);
1924 $bits += $num * (4 + $l);
1959 $chunks = (int)($payload / 10);
1960 $remain = $payload - $chunks * 10;
1961 $size = $chunks * 3;
1964 } elseif ($remain >= 4) {
1970 $chunks = (int)($payload / 11);
1971 $remain = $payload - $chunks * 11;
1972 $size = $chunks * 2;
1979 $size = (int)($payload / 8);
1983 $size = (int)(($payload / 13) * 2);
1987 $size = (int)($payload / 8);
1999 if (
$size > $maxsize) {
2012 foreach (
$items as $key => $item) {
2014 $bits = count(
$items[$key][
'bstream']);
2027 if ($ver > $this->version) {
2028 $this->version = $ver;
2040 } elseif ($ver > $this->version) {
2041 $this->version = $ver;
2055 if (is_null($bstream)) {
2058 $bits = count($bstream);
2059 $maxwords = $this->
getDataLength($this->version, $this->level);
2060 $maxbits = $maxwords * 8;
2061 if ($maxbits == $bits) {
2064 if ($maxbits - $bits < 5) {
2065 return $this->
appendNum($bstream, $maxbits - $bits, 0);
2068 $words = (int)(($bits + 7) / 8);
2070 $padding = $this->
appendNum($padding, $words * 8 - $bits + 4, 0);
2071 $padlen = $maxwords - $words;
2074 for ($i=0; $i<$padlen; ++$i) {
2075 $padbuf[$i] = ($i&1)?0x11:0xec;
2077 $padding = $this->
appendBytes($padding, $padlen, $padbuf);
2093 foreach (
$items as $item) {
2129 return array_fill(0, $setLength, 0);
2140 $mask = 1 << ($bits - 1);
2141 for ($i=0; $i<$bits; ++$i) {
2161 for ($i=0; $i<
$size; ++$i) {
2163 for ($j=0; $j<8; ++$j) {
2164 if (
$data[$i] & $mask) {
2183 if ((!is_array($append)) OR (count($append) == 0)) {
2186 if (count($bitstream) == 0) {
2189 return array_values(array_merge($bitstream, $append));
2228 if (is_null($bstream)) {
2231 $size = count($bstream);
2235 $data = array_fill(0, (
int)((
$size + 7) / 8), 0);
2236 $bytes = (int)(
$size / 8);
2238 for ($i=0; $i<$bytes; $i++) {
2240 for ($j=0; $j<8; $j++) {
2249 for ($j=0; $j<(
$size & 7); $j++) {
2273 $srctab[
$y] = substr_replace($srctab[
$y], ($replLen !==
false)?substr($repl,0,$replLen):$repl,
$x, ($replLen !==
false)?$replLen:strlen($repl));
2303 return $this->capacity[
$version][QRCAP_WIDTH];
2312 return $this->capacity[
$version][QRCAP_REMINDER];
2322 for ($i = 1; $i <= QRSPEC_VERSION_MAX; ++$i) {
2323 $words = ($this->capacity[$i][QRCAP_WORDS] - $this->capacity[$i][QRCAP_EC][
$level]);
2324 if ($words >=
$size) {
2339 if ($mode == QR_MODE_ST) {
2349 return $this->lengthTableBits[$mode][$l];
2359 if ($mode == QR_MODE_ST) {
2369 $bits = $this->lengthTableBits[$mode][$l];
2370 $words = (1 << $bits) - 1;
2371 if ($mode == QR_MODE_KJ) {
2385 if (count($spec) < 5) {
2386 $spec = array(0, 0, 0, 0, 0);
2395 $spec[2] = (int)($ecc /
$b1);
2400 $spec[1] = (int)(
$data / (
$b1 + $b2));
2401 $spec[2] = (int)($ecc / (
$b1 + $b2));
2403 $spec[4] = $spec[1] + 1;
2417 "\xa1\xa1\xa1\xa1\xa1",
2418 "\xa1\xa0\xa0\xa0\xa1",
2419 "\xa1\xa0\xa1\xa0\xa1",
2420 "\xa1\xa0\xa0\xa0\xa1",
2421 "\xa1\xa1\xa1\xa1\xa1" 2425 for (
$y=0;
$y < 5;
$y++) {
2448 if ($w * $w - 3 == 1) {
2454 $cx = $this->alignmentPattern[
$version][0];
2456 for (
$x=1;
$x < $wo; ++
$x) {
2461 $cy = $this->alignmentPattern[
$version][0];
2462 for (
$y=0;
$y < $wo; ++
$y) {
2463 $cx = $this->alignmentPattern[
$version][0];
2464 for (
$x=0;
$x < $wo; ++
$x) {
2482 return $this->versionPattern[(
$version - 7)];
2492 if (($mask < 0) OR ($mask > 7)) {
2498 return $this->formatInfo[
$level][$mask];
2510 "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
2511 "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
2512 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
2513 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
2514 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
2515 "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
2516 "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" 2518 for (
$y=0;
$y < 7;
$y++) {
2531 $frameLine = str_repeat (
"\0",
$width);
2539 for (
$y=0;
$y < 7; ++
$y) {
2542 $frame[$yOffset][7] =
"\xc0";
2545 $setPattern = str_repeat(
"\xc0", 8);
2550 $setPattern = str_repeat(
"\x84", 9);
2554 for (
$y=0;
$y < 8; ++
$y,++$yOffset) {
2556 $frame[$yOffset][8] =
"\x84";
2560 for ($i=1; $i < $wo; ++$i) {
2561 $frame[6][7+$i] = chr(0x90 | ($i & 1));
2562 $frame[7+$i][6] = chr(0x90 | ($i & 1));
2598 if (!isset($this->frames[
$version])) {
2601 if (is_null($this->frames[$version])) {
2613 return ($spec[0] + $spec[3]);
2676 return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]);
2685 return ($spec[0] + $spec[3]) * $spec[2];
2702 protected function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) {
2703 foreach ($this->rsitems as $rs) {
2704 if (($rs[
'pad'] != $pad) OR ($rs[
'nroots'] != $nroots) OR ($rs[
'mm'] != $symsize)
2705 OR ($rs[
'gfpoly'] != $gfpoly) OR ($rs[
'fcr'] != $fcr) OR ($rs[
'prim'] != $prim)) {
2710 $rs = $this->
init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
2711 array_unshift($this->rsitems, $rs);
2726 while (
$x >= $rs[
'nn']) {
2728 $x = (
$x >> $rs[
'mm']) + (
$x & $rs[
'nn']);
2743 protected function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) {
2747 if (($symsize < 0) OR ($symsize > 8)) {
2750 if (($fcr < 0) OR ($fcr >= (1<<$symsize))) {
2753 if (($prim <= 0) OR ($prim >= (1<<$symsize))) {
2756 if (($nroots < 0) OR ($nroots >= (1<<$symsize))) {
2759 if (($pad < 0) OR ($pad >= ((1<<$symsize) -1 - $nroots))) {
2763 $rs[
'mm'] = $symsize;
2764 $rs[
'nn'] = (1 << $symsize) - 1;
2766 $rs[
'alpha_to'] = array_fill(0, ($rs[
'nn'] + 1), 0);
2767 $rs[
'index_of'] = array_fill(0, ($rs[
'nn'] + 1), 0);
2772 $rs[
'index_of'][0] = $A0;
2773 $rs[
'alpha_to'][$A0] = 0;
2775 for ($i=0; $i<$rs[
'nn']; ++$i) {
2776 $rs[
'index_of'][$sr] = $i;
2777 $rs[
'alpha_to'][$i] = $sr;
2779 if ($sr & (1 << $symsize)) {
2789 $rs[
'genpoly'] = array_fill(0, ($nroots + 1), 0);
2791 $rs[
'prim'] = $prim;
2792 $rs[
'nroots'] = $nroots;
2793 $rs[
'gfpoly'] = $gfpoly;
2795 for ($iprim=1; ($iprim % $prim) != 0; $iprim += $rs[
'nn']) {
2798 $rs[
'iprim'] = (int)($iprim / $prim);
2799 $rs[
'genpoly'][0] = 1;
2800 for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
2801 $rs[
'genpoly'][$i+1] = 1;
2803 for ($j = $i; $j > 0; --$j) {
2804 if ($rs[
'genpoly'][$j] != 0) {
2805 $rs[
'genpoly'][$j] = $rs[
'genpoly'][$j-1] ^ $rs[
'alpha_to'][$this->
modnn($rs, $rs[
'index_of'][$rs[
'genpoly'][$j]] + $root)];
2807 $rs[
'genpoly'][$j] = $rs[
'genpoly'][$j-1];
2811 $rs[
'genpoly'][0] = $rs[
'alpha_to'][$this->
modnn($rs, $rs[
'index_of'][$rs[
'genpoly'][0]] + $root)];
2814 for ($i = 0; $i <= $nroots; ++$i) {
2815 $rs[
'genpoly'][$i] = $rs[
'index_of'][$rs[
'genpoly'][$i]];
2830 $ALPHA_TO =& $rs[
'alpha_to'];
2831 $INDEX_OF =& $rs[
'index_of'];
2832 $GENPOLY =& $rs[
'genpoly'];
2833 $NROOTS =& $rs[
'nroots'];
2835 $PRIM =& $rs[
'prim'];
2836 $IPRIM =& $rs[
'iprim'];
2839 $parity = array_fill(0, $NROOTS, 0);
2840 for ($i=0; $i < ($NN - $NROOTS - $PAD); $i++) {
2841 $feedback = $INDEX_OF[
$data[$i] ^ $parity[0]];
2842 if ($feedback != $A0) {
2846 $feedback = $this->
modnn($rs, $NN - $GENPOLY[$NROOTS] + $feedback);
2847 for ($j=1; $j < $NROOTS; ++$j) {
2848 $parity[$j] ^= $ALPHA_TO[$this->
modnn($rs, $feedback + $GENPOLY[($NROOTS - $j)])];
2852 array_shift($parity);
2853 if ($feedback != $A0) {
2854 array_push($parity, $ALPHA_TO[$this->
modnn($rs, $feedback + $GENPOLY[0])]);
2856 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.
$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.