86 if (!defined(
'QRCODEDEFS')) {
91 define(
'QRCODEDEFS',
true);
100 define(
'QR_MODE_NL', -1);
105 define(
'QR_MODE_NM', 0);
110 define(
'QR_MODE_AN', 1);
115 define(
'QR_MODE_8B', 2);
120 define(
'QR_MODE_KJ', 3);
125 define(
'QR_MODE_ST', 4);
136 define(
'QR_ECLEVEL_L', 0);
141 define(
'QR_ECLEVEL_M', 1);
146 define(
'QR_ECLEVEL_Q', 2);
151 define(
'QR_ECLEVEL_H', 3);
163 define(
'QRSPEC_VERSION_MAX', 40);
168 define(
'QRSPEC_WIDTH_MAX', 177);
175 define(
'QRCAP_WIDTH', 0);
180 define(
'QRCAP_WORDS', 1);
185 define(
'QRCAP_REMINDER', 2);
190 define(
'QRCAP_EC', 3);
199 define(
'STRUCTURE_HEADER_BITS', 20);
204 define(
'MAX_STRUCTURED_SYMBOLS', 16);
237 define(
'QR_FIND_BEST_MASK',
true);
242 define(
'QR_FIND_FROM_RANDOM', 2);
247 define(
'QR_DEFAULT_MASK', 2);
255 if (!class_exists(
'QRcode',
false)) {
258 if (!function_exists(
'str_split')) {
265 function str_split($string, $split_length=1) {
266 if ((strlen($string) > $split_length) OR (!$split_length)) {
268 $c = strlen($string);
269 $parts[] = substr($string, 0, $split_length);
270 $string = substr($string, $split_length);
271 }
while ($string !==
false);
273 $parts = array($string);
306 protected $barcode_array = array();
312 protected $version = 0;
318 protected $level = QR_ECLEVEL_L;
324 protected $hint = QR_MODE_8B;
330 protected $casesensitive =
true;
336 protected $structured = 0;
388 protected $datacode = array();
394 protected $ecccode = array();
406 protected $rsblocks = array();
418 protected $dataLength;
424 protected $eccLength;
438 protected $runLength = array();
446 protected $dataStr =
'';
460 protected $rsitems = array();
466 protected $frames = array();
472 protected $anTable = array(
473 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
474 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
475 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
476 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,
477 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
478 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
479 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
480 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
488 protected $capacity = array(
489 array( 0, 0, 0, array( 0, 0, 0, 0)),
490 array( 21, 26, 0, array( 7, 10, 13, 17)),
491 array( 25, 44, 7, array( 10, 16, 22, 28)),
492 array( 29, 70, 7, array( 15, 26, 36, 44)),
493 array( 33, 100, 7, array( 20, 36, 52, 64)),
494 array( 37, 134, 7, array( 26, 48, 72, 88)),
495 array( 41, 172, 7, array( 36, 64, 96, 112)),
496 array( 45, 196, 0, array( 40, 72, 108, 130)),
497 array( 49, 242, 0, array( 48, 88, 132, 156)),
498 array( 53, 292, 0, array( 60, 110, 160, 192)),
499 array( 57, 346, 0, array( 72, 130, 192, 224)),
500 array( 61, 404, 0, array( 80, 150, 224, 264)),
501 array( 65, 466, 0, array( 96, 176, 260, 308)),
502 array( 69, 532, 0, array( 104, 198, 288, 352)),
503 array( 73, 581, 3, array( 120, 216, 320, 384)),
504 array( 77, 655, 3, array( 132, 240, 360, 432)),
505 array( 81, 733, 3, array( 144, 280, 408, 480)),
506 array( 85, 815, 3, array( 168, 308, 448, 532)),
507 array( 89, 901, 3, array( 180, 338, 504, 588)),
508 array( 93, 991, 3, array( 196, 364, 546, 650)),
509 array( 97, 1085, 3, array( 224, 416, 600, 700)),
510 array(101, 1156, 4, array( 224, 442, 644, 750)),
511 array(105, 1258, 4, array( 252, 476, 690, 816)),
512 array(109, 1364, 4, array( 270, 504, 750, 900)),
513 array(113, 1474, 4, array( 300, 560, 810, 960)),
514 array(117, 1588, 4, array( 312, 588, 870, 1050)),
515 array(121, 1706, 4, array( 336, 644, 952, 1110)),
516 array(125, 1828, 4, array( 360, 700, 1020, 1200)),
517 array(129, 1921, 3, array( 390, 728, 1050, 1260)),
518 array(133, 2051, 3, array( 420, 784, 1140, 1350)),
519 array(137, 2185, 3, array( 450, 812, 1200, 1440)),
520 array(141, 2323, 3, array( 480, 868, 1290, 1530)),
521 array(145, 2465, 3, array( 510, 924, 1350, 1620)),
522 array(149, 2611, 3, array( 540, 980, 1440, 1710)),
523 array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
524 array(157, 2876, 0, array( 570, 1064, 1590, 1890)),
525 array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
526 array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
527 array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
528 array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
529 array(177, 3706, 0, array( 750, 1372, 2040, 2430))
536 protected $lengthTableBits = array(
548 protected $eccTable = array(
549 array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)),
550 array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)),
551 array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)),
552 array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)),
553 array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)),
554 array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)),
555 array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)),
556 array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)),
557 array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)),
558 array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)),
559 array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)),
560 array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)),
561 array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)),
562 array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)),
563 array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)),
564 array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)),
565 array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)),
566 array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)),
567 array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)),
568 array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)),
569 array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)),
570 array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)),
571 array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)),
572 array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)),
573 array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)),
574 array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)),
575 array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)),
576 array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)),
577 array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)),
578 array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)),
579 array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)),
580 array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)),
581 array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)),
582 array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)),
583 array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)),
584 array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)),
585 array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
586 array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)),
587 array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)),
588 array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)),
589 array(array(19, 6), array(18, 31), array(34, 34), array(20, 61))
598 protected $alignmentPattern = array(
600 array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0),
601 array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50),
602 array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48),
603 array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62),
604 array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58),
605 array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52),
606 array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54),
607 array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58)
616 protected $versionPattern = array(
617 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
618 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
619 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
620 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
628 protected $formatInfo = array(
629 array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
630 array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
631 array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed),
632 array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b)
648 public function __construct($code, $eclevel =
'L') {
649 $barcode_array = array();
650 if ((is_null($code)) OR ($code ==
'\0') OR ($code ==
'')) {
654 $this->level = array_search($eclevel, array(
'L',
'M',
'Q',
'H'));
655 if ($this->level ===
false) {
656 $this->level = QR_ECLEVEL_L;
658 if (($this->hint != QR_MODE_8B) AND ($this->hint != QR_MODE_KJ)) {
661 if (($this->version < 0) OR ($this->version > QRSPEC_VERSION_MAX)) {
664 $this->items = array();
665 $this->encodeString($code);
666 if (is_null($this->data)) {
669 $qrTab = $this->binarize($this->data);
670 $size = count($qrTab);
671 $barcode_array[
'num_rows'] = $size;
672 $barcode_array[
'num_cols'] = $size;
673 $barcode_array[
'bcode'] = array();
674 foreach ($qrTab as $line) {
676 foreach (str_split($line) as $char) {
677 $arrAdd[] = ($char==
'1')?1:0;
679 $barcode_array[
'bcode'][] = $arrAdd;
681 $this->barcode_array = $barcode_array;
689 public function getBarcodeArray() {
690 return $this->barcode_array;
698 protected function binarize($frame) {
699 $len = count($frame);
701 foreach ($frame as &$frameLine) {
702 for ($i=0; $i<$len; $i++) {
703 $frameLine[$i] = (ord($frameLine[$i])&1)?
'1':
'0';
713 protected function encodeString($string) {
714 $this->dataStr = $string;
715 if (!$this->casesensitive) {
718 $ret = $this->splitString();
722 $this->encodeMask(-1);
729 protected function encodeMask($mask) {
730 $spec = array(0, 0, 0, 0, 0);
731 $this->datacode = $this->getByteStream($this->items);
732 if (is_null($this->datacode)) {
735 $spec = $this->getEccSpec($this->version, $this->level, $spec);
736 $this->b1 = $this->rsBlockNum1($spec);
737 $this->dataLength = $this->rsDataLength($spec);
738 $this->eccLength = $this->rsEccLength($spec);
739 $this->ecccode = array_fill(0, $this->eccLength, 0);
740 $this->blocks = $this->rsBlockNum($spec);
741 $ret = $this->init($spec);
746 $this->width = $this->getWidth($this->version);
747 $this->frame = $this->newFrame($this->version);
748 $this->x = $this->width - 1;
749 $this->y = $this->width - 1;
753 for ($i=0; $i < ($this->dataLength + $this->eccLength); $i++) {
754 $code = $this->getCode();
756 for ($j=0; $j<8; $j++) {
757 $addr = $this->getNextPosition();
758 $this->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
763 $j = $this->getRemainder($this->version);
764 for ($i=0; $i<$j; $i++) {
765 $addr = $this->getNextPosition();
766 $this->setFrameAt($addr, 0x02);
769 $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
771 if (QR_FIND_BEST_MASK) {
772 $masked = $this->mask($this->width, $this->frame, $this->level);
774 $masked = $this->makeMask($this->width, $this->frame, (intval(QR_DEFAULT_MASK) % 8), $this->level);
777 $masked = $this->makeMask($this->width, $this->frame, $mask, $this->level);
779 if ($masked == NULL) {
782 $this->data = $masked;
794 protected function setFrameAt($at, $val) {
795 $this->frame[$at[
'y']][$at[
'x']] = chr($val);
803 protected function getFrameAt($at) {
804 return ord($this->frame[$at[
'y']][$at[
'x']]);
811 protected function getNextPosition() {
813 if ($this->bit == -1) {
815 return array(
'x'=>$this->x,
'y'=>$this->y);
820 if ($this->bit == 0) {
828 if ($this->dir < 0) {
849 if ((
$x < 0) OR (
$y < 0)) {
854 }
while(ord($this->frame[
$y][
$x]) & 0x80);
855 return array(
'x'=>$x,
'y'=>
$y);
867 protected function init($spec) {
868 $dl = $this->rsDataCodes1($spec);
869 $el = $this->rsEccCodes1($spec);
870 $rs = $this->init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
874 $endfor = $this->rsBlockNum1($spec);
875 for ($i=0; $i < $endfor; ++$i) {
876 $ecc = array_slice($this->ecccode, $eccPos);
877 $this->rsblocks[$blockNo] = array();
878 $this->rsblocks[$blockNo][
'dataLength'] = $dl;
879 $this->rsblocks[$blockNo][
'data'] = array_slice($this->datacode, $dataPos);
880 $this->rsblocks[$blockNo][
'eccLength'] = $el;
881 $ecc = $this->encode_rs_char($rs, $this->rsblocks[$blockNo][
'data'], $ecc);
882 $this->rsblocks[$blockNo][
'ecc'] = $ecc;
883 $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
888 if ($this->rsBlockNum2($spec) == 0) {
891 $dl = $this->rsDataCodes2($spec);
892 $el = $this->rsEccCodes2($spec);
893 $rs = $this->init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
897 $endfor = $this->rsBlockNum2($spec);
898 for ($i=0; $i < $endfor; ++$i) {
899 $ecc = array_slice($this->ecccode, $eccPos);
900 $this->rsblocks[$blockNo] = array();
901 $this->rsblocks[$blockNo][
'dataLength'] = $dl;
902 $this->rsblocks[$blockNo][
'data'] = array_slice($this->datacode, $dataPos);
903 $this->rsblocks[$blockNo][
'eccLength'] = $el;
904 $ecc = $this->encode_rs_char($rs, $this->rsblocks[$blockNo][
'data'], $ecc);
905 $this->rsblocks[$blockNo][
'ecc'] = $ecc;
906 $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc);
918 protected function getCode() {
919 if ($this->count < $this->dataLength) {
920 $row = $this->count % $this->blocks;
921 $col = $this->count / $this->blocks;
922 if ($col >= $this->rsblocks[0][
'dataLength']) {
925 $ret = $this->rsblocks[
$row][
'data'][$col];
926 } elseif ($this->count < $this->dataLength + $this->eccLength) {
927 $row = ($this->count - $this->dataLength) % $this->blocks;
928 $col = ($this->count - $this->dataLength) / $this->blocks;
929 $ret = $this->rsblocks[
$row][
'ecc'][$col];
949 protected function writeFormatInformation($width, &$frame, $mask, $level) {
951 $format = $this->getFormatInfo($mask, $level);
952 for ($i=0; $i<8; ++$i) {
959 $frame[8][$width - 1 - $i] = chr($v);
961 $frame[$i][8] = chr($v);
963 $frame[$i + 1][8] = chr($v);
965 $format = $format >> 1;
967 for ($i=0; $i<7; ++$i) {
974 $frame[$width - 7 + $i][8] = chr($v);
976 $frame[8][7] = chr($v);
978 $frame[8][6 - $i] = chr($v);
980 $format = $format >> 1;
991 protected function mask0(
$x,
$y) {
992 return (
$x +
$y) & 1;
1001 protected function mask1(
$x,
$y) {
1011 protected function mask2(
$x,
$y) {
1021 protected function mask3(
$x,
$y) {
1022 return (
$x +
$y) % 3;
1031 protected function mask4(
$x,
$y) {
1032 return (((
int)(
$y / 2)) + ((
int)(
$x / 3))) & 1;
1041 protected function mask5(
$x,
$y) {
1042 return ((
$x *
$y) & 1) + (
$x *
$y) % 3;
1051 protected function mask6(
$x,
$y) {
1052 return (((
$x *
$y) & 1) + (
$x * $y) % 3) & 1;
1061 protected function mask7(
$x, $y) {
1062 return (((
$x * $y) % 3) + ((
$x + $y) & 1)) & 1;
1072 protected function generateMaskNo($maskNo, $width, $frame) {
1073 $bitMask = array_fill(0, $width, array_fill(0, $width, 0));
1074 for ($y=0; $y<$width; ++
$y) {
1075 for (
$x=0;
$x<$width; ++
$x) {
1076 if (ord($frame[$y][
$x]) & 0x80) {
1077 $bitMask[
$y][
$x] = 0;
1079 $maskFunc = call_user_func(array($this,
'mask'.$maskNo), $x, $y);
1080 $bitMask[
$y][
$x] = ($maskFunc == 0)?1:0;
1096 protected function makeMaskNo($maskNo, $width, $s, &
$d, $maskGenOnly=
false) {
1099 $bitMask = $this->generateMaskNo($maskNo, $width, $s,
$d);
1104 for ($y=0; $y<$width; ++
$y) {
1105 for (
$x=0;
$x<$width; ++
$x) {
1106 if ($bitMask[$y][
$x] == 1) {
1107 $d[
$y][
$x] = chr(ord($s[$y][
$x]) ^ (
int)$bitMask[$y][$x]);
1109 $b += (int)(ord(
$d[$y][
$x]) & 1);
1123 protected function makeMask($width, $frame, $maskNo, $level) {
1124 $masked = array_fill(0, $width, str_repeat(
"\0", $width));
1125 $this->makeMaskNo($maskNo, $width, $frame, $masked);
1126 $this->writeFormatInformation($width, $masked, $maskNo, $level);
1135 protected function calcN1N3($length) {
1137 for ($i=0; $i<$length; ++$i) {
1138 if ($this->runLength[$i] >= 5) {
1139 $demerit += (N1 + ($this->runLength[$i] - 5));
1142 if (($i >= 3) AND ($i < ($length-2)) AND ($this->runLength[$i] % 3 == 0)) {
1143 $fact = (int)($this->runLength[$i] / 3);
1144 if (($this->runLength[$i-2] == $fact)
1145 AND ($this->runLength[$i-1] == $fact)
1146 AND ($this->runLength[$i+1] == $fact)
1147 AND ($this->runLength[$i+2] == $fact)) {
1148 if (($this->runLength[$i-3] < 0) OR ($this->runLength[$i-3] >= (4 * $fact))) {
1150 } elseif ((($i+3) >= $length) OR ($this->runLength[$i+3] >= (4 * $fact))) {
1166 protected function evaluateSymbol($width, $frame) {
1169 for ($y=0; $y<$width; ++
$y) {
1171 $this->runLength[0] = 1;
1172 $frameY = $frame[
$y];
1174 $frameYM = $frame[$y-1];
1176 for (
$x=0;
$x<$width; ++
$x) {
1177 if ((
$x > 0) AND ($y > 0)) {
1178 $b22 = ord($frameY[
$x]) & ord($frameY[
$x-1]) & ord($frameYM[
$x]) & ord($frameYM[
$x-1]);
1179 $w22 = ord($frameY[
$x]) | ord($frameY[
$x-1]) | ord($frameYM[
$x]) | ord($frameYM[
$x-1]);
1180 if (($b22 | ($w22 ^ 1)) & 1) {
1184 if ((
$x == 0) AND (ord($frameY[
$x]) & 1)) {
1185 $this->runLength[0] = -1;
1187 $this->runLength[$head] = 1;
1189 if ((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
1191 $this->runLength[$head] = 1;
1193 $this->runLength[$head]++;
1197 $demerit += $this->calcN1N3($head+1);
1199 for ($x=0; $x<$width; ++
$x) {
1201 $this->runLength[0] = 1;
1202 for ($y=0; $y<$width; ++
$y) {
1203 if (($y == 0) AND (ord($frame[$y][$x]) & 1)) {
1204 $this->runLength[0] = -1;
1206 $this->runLength[$head] = 1;
1208 if ((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
1210 $this->runLength[$head] = 1;
1212 $this->runLength[$head]++;
1216 $demerit += $this->calcN1N3($head+1);
1228 protected function mask($width, $frame, $level) {
1229 $minDemerit = PHP_INT_MAX;
1231 $bestMask = array();
1232 $checked_masks = array(0, 1, 2, 3, 4, 5, 6, 7);
1233 if (QR_FIND_FROM_RANDOM !==
false) {
1234 $howManuOut = 8 - (QR_FIND_FROM_RANDOM % 9);
1235 for ($i = 0; $i < $howManuOut; ++$i) {
1236 $remPos = rand (0, count($checked_masks)-1);
1237 unset($checked_masks[$remPos]);
1238 $checked_masks = array_values($checked_masks);
1242 foreach ($checked_masks as $i) {
1243 $mask = array_fill(0, $width, str_repeat(
"\0", $width));
1246 $blacks = $this->makeMaskNo($i, $width, $frame, $mask);
1247 $blacks += $this->writeFormatInformation($width, $mask, $i, $level);
1248 $blacks = (int)(100 * $blacks / ($width * $width));
1249 $demerit = (int)((
int)(abs($blacks - 50) / 5) * N4);
1250 $demerit += $this->evaluateSymbol($width, $mask);
1251 if ($demerit < $minDemerit) {
1252 $minDemerit = $demerit;
1270 protected function isdigitat($str,
$pos) {
1271 if (
$pos >= strlen($str)) {
1274 return ((ord($str[
$pos]) >= ord(
'0'))&&(ord($str[$pos]) <= ord(
'9')));
1283 protected function isalnumat($str, $pos) {
1284 if ($pos >= strlen($str)) {
1287 return ($this->lookAnTable(ord($str[$pos])) >= 0);
1295 protected function identifyMode($pos) {
1296 if ($pos >= strlen($this->dataStr)) {
1299 $c = $this->dataStr[
$pos];
1300 if ($this->isdigitat($this->dataStr, $pos)) {
1302 } elseif ($this->isalnumat($this->dataStr, $pos)) {
1304 } elseif ($this->hint == QR_MODE_KJ) {
1305 if ($pos+1 < strlen($this->dataStr)) {
1306 $d = $this->dataStr[$pos+1];
1307 $word = (ord($c) << 8) | ord(
$d);
1308 if (($word >= 0x8140 && $word <= 0x9ffc) OR ($word >= 0xe040 && $word <= 0xebbf)) {
1320 protected function eatNum() {
1321 $ln = $this->lengthIndicator(QR_MODE_NM, $this->version);
1323 while($this->isdigitat($this->dataStr, $p)) {
1327 $mode = $this->identifyMode($p);
1328 if ($mode == QR_MODE_8B) {
1329 $dif = $this->estimateBitsModeNum($run) + 4 + $ln
1330 + $this->estimateBitsMode8(1)
1331 - $this->estimateBitsMode8($run + 1);
1333 return $this->eat8();
1336 if ($mode == QR_MODE_AN) {
1337 $dif = $this->estimateBitsModeNum($run) + 4 + $ln
1338 + $this->estimateBitsModeAn(1)
1339 - $this->estimateBitsModeAn($run + 1);
1341 return $this->eatAn();
1344 $this->items = $this->appendNewInputItem($this->items, QR_MODE_NM, $run, str_split($this->dataStr));
1352 protected function eatAn() {
1353 $la = $this->lengthIndicator(QR_MODE_AN, $this->version);
1354 $ln = $this->lengthIndicator(QR_MODE_NM, $this->version);
1356 while($this->isalnumat($this->dataStr, $p)) {
1357 if ($this->isdigitat($this->dataStr, $p)) {
1359 while($this->isdigitat($this->dataStr, $q)) {
1362 $dif = $this->estimateBitsModeAn($p)
1363 + $this->estimateBitsModeNum($q - $p) + 4 + $ln
1364 - $this->estimateBitsModeAn($q);
1375 if (!$this->isalnumat($this->dataStr, $p)) {
1376 $dif = $this->estimateBitsModeAn($run) + 4 + $la
1377 + $this->estimateBitsMode8(1)
1378 - $this->estimateBitsMode8($run + 1);
1380 return $this->eat8();
1383 $this->items = $this->appendNewInputItem($this->items, QR_MODE_AN, $run, str_split($this->dataStr));
1391 protected function eatKanji() {
1393 while($this->identifyMode($p) == QR_MODE_KJ) {
1396 $this->items = $this->appendNewInputItem($this->items, QR_MODE_KJ, $p, str_split($this->dataStr));
1404 protected function eat8() {
1405 $la = $this->lengthIndicator(QR_MODE_AN, $this->version);
1406 $ln = $this->lengthIndicator(QR_MODE_NM, $this->version);
1408 $dataStrLen = strlen($this->dataStr);
1409 while($p < $dataStrLen) {
1410 $mode = $this->identifyMode($p);
1411 if ($mode == QR_MODE_KJ) {
1414 if ($mode == QR_MODE_NM) {
1416 while($this->isdigitat($this->dataStr, $q)) {
1419 $dif = $this->estimateBitsMode8($p)
1420 + $this->estimateBitsModeNum($q - $p) + 4 + $ln
1421 - $this->estimateBitsMode8($q);
1427 } elseif ($mode == QR_MODE_AN) {
1429 while($this->isalnumat($this->dataStr, $q)) {
1432 $dif = $this->estimateBitsMode8($p)
1433 + $this->estimateBitsModeAn($q - $p) + 4 + $la
1434 - $this->estimateBitsMode8($q);
1445 $this->items = $this->appendNewInputItem($this->items, QR_MODE_8B, $run, str_split($this->dataStr));
1452 protected function splitString() {
1453 while (strlen($this->dataStr) > 0) {
1454 if ($this->dataStr ==
'') {
1457 $mode = $this->identifyMode(0);
1460 $length = $this->eatNum();
1464 $length = $this->eatAn();
1468 if ($hint == QR_MODE_KJ) {
1469 $length = $this->eatKanji();
1471 $length = $this->eat8();
1476 $length = $this->eat8();
1486 $this->dataStr = substr($this->dataStr, $length);
1493 protected function toUpper() {
1494 $stringLen = strlen($this->dataStr);
1496 while ($p < $stringLen) {
1497 $mode = $this->identifyMode(substr($this->dataStr, $p), $this->hint);
1498 if ($mode == QR_MODE_KJ) {
1501 if ((ord($this->dataStr[$p]) >= ord(
'a')) AND (ord($this->dataStr[$p]) <= ord(
'z'))) {
1502 $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
1507 return $this->dataStr;
1522 protected function newInputItem($mode, $size,
$data, $bstream=null) {
1523 $setData = array_slice(
$data, 0, $size);
1524 if (count($setData) < $size) {
1525 $setData = array_merge($setData, array_fill(0, ($size - count($setData)), 0));
1527 if (!$this->check($mode, $size, $setData)) {
1530 $inputitem = array();
1531 $inputitem[
'mode'] = $mode;
1532 $inputitem[
'size'] = $size;
1533 $inputitem[
'data'] = $setData;
1534 $inputitem[
'bstream'] = $bstream;
1544 protected function encodeModeNum($inputitem, $version) {
1545 $words = (int)($inputitem[
'size'] / 3);
1546 $inputitem[
'bstream'] = array();
1548 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 4, $val);
1549 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], $this->lengthIndicator(QR_MODE_NM, $version), $inputitem[
'size']);
1550 for ($i=0; $i < $words; ++$i) {
1551 $val = (ord($inputitem[
'data'][$i*3 ]) - ord(
'0')) * 100;
1552 $val += (ord($inputitem[
'data'][$i*3+1]) - ord(
'0')) * 10;
1553 $val += (ord($inputitem[
'data'][$i*3+2]) - ord(
'0'));
1554 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 10, $val);
1556 if ($inputitem[
'size'] - $words * 3 == 1) {
1557 $val = ord($inputitem[
'data'][$words*3]) - ord(
'0');
1558 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 4, $val);
1559 } elseif (($inputitem[
'size'] - ($words * 3)) == 2) {
1560 $val = (ord($inputitem[
'data'][$words*3 ]) - ord(
'0')) * 10;
1561 $val += (ord($inputitem[
'data'][$words*3+1]) - ord(
'0'));
1562 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 7, $val);
1573 protected function encodeModeAn($inputitem, $version) {
1574 $words = (int)($inputitem[
'size'] / 2);
1575 $inputitem[
'bstream'] = array();
1576 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 4, 0x02);
1577 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], $this->lengthIndicator(QR_MODE_AN, $version), $inputitem[
'size']);
1578 for ($i=0; $i < $words; ++$i) {
1579 $val = (int)$this->lookAnTable(ord($inputitem[
'data'][$i*2 ])) * 45;
1580 $val += (int)$this->lookAnTable(ord($inputitem[
'data'][$i*2+1]));
1581 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 11, $val);
1583 if ($inputitem[
'size'] & 1) {
1584 $val = $this->lookAnTable(ord($inputitem[
'data'][($words * 2)]));
1585 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 6, $val);
1596 protected function encodeMode8($inputitem, $version) {
1597 $inputitem[
'bstream'] = array();
1598 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 4, 0x4);
1599 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], $this->lengthIndicator(QR_MODE_8B, $version), $inputitem[
'size']);
1600 for ($i=0; $i < $inputitem[
'size']; ++$i) {
1601 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 8, ord($inputitem[
'data'][$i]));
1612 protected function encodeModeKanji($inputitem, $version) {
1613 $inputitem[
'bstream'] = array();
1614 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 4, 0x8);
1615 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], $this->lengthIndicator(QR_MODE_KJ, $version), (
int)($inputitem[
'size'] / 2));
1616 for ($i=0; $i<$inputitem[
'size']; $i+=2) {
1617 $val = (ord($inputitem[
'data'][$i]) << 8) | ord($inputitem[
'data'][$i+1]);
1618 if ($val <= 0x9ffc) {
1623 $h = ($val >> 8) * 0xc0;
1624 $val = ($val & 0xff) + $h;
1625 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 13, $val);
1635 protected function encodeModeStructure($inputitem) {
1636 $inputitem[
'bstream'] = array();
1637 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 4, 0x03);
1638 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 4, ord($inputitem[
'data'][1]) - 1);
1639 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 4, ord($inputitem[
'data'][0]) - 1);
1640 $inputitem[
'bstream'] = $this->appendNum($inputitem[
'bstream'], 8, ord($inputitem[
'data'][2]));
1650 protected function encodeBitStream($inputitem, $version) {
1651 $inputitem[
'bstream'] = array();
1652 $words = $this->maximumWords($inputitem[
'mode'], $version);
1653 if ($inputitem[
'size'] > $words) {
1654 $st1 = $this->newInputItem($inputitem[
'mode'], $words, $inputitem[
'data']);
1655 $st2 = $this->newInputItem($inputitem[
'mode'], $inputitem[
'size'] - $words, array_slice($inputitem[
'data'], $words));
1656 $st1 = $this->encodeBitStream($st1, $version);
1657 $st2 = $this->encodeBitStream($st2, $version);
1658 $inputitem[
'bstream'] = array();
1659 $inputitem[
'bstream'] = $this->appendBitstream($inputitem[
'bstream'], $st1[
'bstream']);
1660 $inputitem[
'bstream'] = $this->appendBitstream($inputitem[
'bstream'], $st2[
'bstream']);
1662 switch($inputitem[
'mode']) {
1664 $inputitem = $this->encodeModeNum($inputitem, $version);
1668 $inputitem = $this->encodeModeAn($inputitem, $version);
1672 $inputitem = $this->encodeMode8($inputitem, $version);
1676 $inputitem = $this->encodeModeKanji($inputitem, $version);
1680 $inputitem = $this->encodeModeStructure($inputitem);
1705 protected function appendNewInputItem($items, $mode, $size,
$data) {
1706 $items[] = $this->newInputItem($mode, $size,
$data);
1718 protected function insertStructuredAppendHeader($items, $size, $index, $parity) {
1719 if ($size > MAX_STRUCTURED_SYMBOLS) {
1722 if (($index <= 0) OR ($index > MAX_STRUCTURED_SYMBOLS)) {
1725 $buf = array($size, $index, $parity);
1726 $entry = $this->newInputItem(QR_MODE_ST, 3, buf);
1727 array_unshift($items, $entry);
1736 protected function calcParity($items) {
1738 foreach ($items as $item) {
1739 if ($item[
'mode'] != QR_MODE_ST) {
1740 for ($i=$item[
'size']-1; $i>=0; --$i) {
1741 $parity ^= $item[
'data'][$i];
1754 protected function checkModeNum($size,
$data) {
1755 for ($i=0; $i<$size; ++$i) {
1756 if ((ord(
$data[$i]) < ord(
'0')) OR (ord(
$data[$i]) > ord(
'9'))){
1768 protected function estimateBitsModeNum($size) {
1769 $w = (int)$size / 3;
1771 switch($size - $w * 3) {
1792 protected function lookAnTable($c) {
1793 return (($c > 127)?-1:$this->anTable[$c]);
1802 protected function checkModeAn($size,
$data) {
1803 for ($i=0; $i<$size; ++$i) {
1804 if ($this->lookAnTable(ord(
$data[$i])) == -1) {
1816 protected function estimateBitsModeAn($size) {
1817 $w = (int)($size / 2);
1830 protected function estimateBitsMode8($size) {
1839 protected function estimateBitsModeKanji($size) {
1840 return (
int)(($size / 2) * 13);
1849 protected function checkModeKanji($size,
$data) {
1853 for ($i=0; $i<$size; $i+=2) {
1854 $val = (ord(
$data[$i]) << 8) | ord(
$data[$i+1]);
1855 if (($val < 0x8140) OR (($val > 0x9ffc) AND ($val < 0xe040)) OR ($val > 0xebbf)) {
1869 protected function check($mode, $size,
$data) {
1875 return $this->checkModeNum($size,
$data);
1878 return $this->checkModeAn($size,
$data);
1881 return $this->checkModeKanji($size,
$data);
1902 protected function estimateBitStreamSize($items, $version) {
1904 if ($version == 0) {
1907 foreach ($items as $item) {
1908 switch($item[
'mode']) {
1910 $bits = $this->estimateBitsModeNum($item[
'size']);
1914 $bits = $this->estimateBitsModeAn($item[
'size']);
1918 $bits = $this->estimateBitsMode8($item[
'size']);
1922 $bits = $this->estimateBitsModeKanji($item[
'size']);
1926 return STRUCTURE_HEADER_BITS;
1932 $l = $this->lengthIndicator($item[
'mode'], $version);
1934 $num = (int)(($item[
'size'] + $m - 1) / $m);
1935 $bits += $num * (4 +
$l);
1945 protected function estimateVersion($items) {
1950 $bits = $this->estimateBitStreamSize($items, $prev);
1951 $version = $this->getMinimumVersion((
int)(($bits + 7) / 8), $this->level);
1955 }
while ($version > $prev);
1966 protected function lengthOfCode($mode, $version, $bits) {
1967 $payload = $bits - 4 - $this->lengthIndicator($mode, $version);
1970 $chunks = (int)($payload / 10);
1971 $remain = $payload - $chunks * 10;
1972 $size = $chunks * 3;
1975 } elseif ($remain >= 4) {
1981 $chunks = (int)($payload / 11);
1982 $remain = $payload - $chunks * 11;
1983 $size = $chunks * 2;
1990 $size = (int)($payload / 8);
1994 $size = (int)(($payload / 13) * 2);
1998 $size = (int)($payload / 8);
2006 $maxsize = $this->maximumWords($mode, $version);
2010 if ($size > $maxsize) {
2021 protected function createBitStream($items) {
2023 foreach ($items as $key => $item) {
2024 $items[$key] = $this->encodeBitStream($item, $this->version);
2025 $bits = count($items[$key][
'bstream']);
2028 return array($items,
$total);
2036 protected function convertData($items) {
2037 $ver = $this->estimateVersion($items);
2038 if ($ver > $this->version) {
2039 $this->version = $ver;
2042 $cbs = $this->createBitStream($items);
2048 $ver = $this->getMinimumVersion((
int)(($bits + 7) / 8), $this->level);
2051 } elseif ($ver > $this->version) {
2052 $this->version = $ver;
2065 protected function appendPaddingBit($bstream) {
2066 if (is_null($bstream)) {
2069 $bits = count($bstream);
2070 $maxwords = $this->getDataLength($this->version, $this->level);
2071 $maxbits = $maxwords * 8;
2072 if ($maxbits == $bits) {
2075 if ($maxbits - $bits < 5) {
2076 return $this->appendNum($bstream, $maxbits - $bits, 0);
2079 $words = (int)(($bits + 7) / 8);
2081 $padding = $this->appendNum($padding, $words * 8 - $bits + 4, 0);
2082 $padlen = $maxwords - $words;
2085 for ($i=0; $i<$padlen; ++$i) {
2086 $padbuf[$i] = ($i&1)?0x11:0xec;
2088 $padding = $this->appendBytes($padding, $padlen, $padbuf);
2090 return $this->appendBitstream($bstream, $padding);
2098 protected function mergeBitStream($items) {
2099 $items = $this->convertData($items);
2100 if (!is_array($items)) {
2104 foreach ($items as $item) {
2105 $bstream = $this->appendBitstream($bstream, $item[
'bstream']);
2115 protected function getBitStream($items) {
2116 $bstream = $this->mergeBitStream($items);
2117 return $this->appendPaddingBit($bstream);
2125 protected function getByteStream($items) {
2126 $bstream = $this->getBitStream($items);
2127 return $this->bitstreamToByte($bstream);
2139 protected function allocate($setLength) {
2140 return array_fill(0, $setLength, 0);
2149 protected function newFromNum($bits, $num) {
2150 $bstream = $this->allocate($bits);
2151 $mask = 1 << ($bits - 1);
2152 for ($i=0; $i<$bits; ++$i) {
2169 protected function newFromBytes($size,
$data) {
2170 $bstream = $this->allocate($size * 8);
2172 for ($i=0; $i<$size; ++$i) {
2174 for ($j=0; $j<8; ++$j) {
2175 if (
$data[$i] & $mask) {
2193 protected function appendBitstream($bitstream, $append) {
2194 if ((!is_array($append)) OR (count($append) == 0)) {
2197 if (count($bitstream) == 0) {
2200 return array_values(array_merge($bitstream, $append));
2210 protected function appendNum($bitstream, $bits, $num) {
2214 $b = $this->newFromNum($bits, $num);
2215 return $this->appendBitstream($bitstream, $b);
2225 protected function appendBytes($bitstream, $size,
$data) {
2229 $b = $this->newFromBytes($size,
$data);
2230 return $this->appendBitstream($bitstream, $b);
2238 protected function bitstreamToByte($bstream) {
2239 if (is_null($bstream)) {
2242 $size = count($bstream);
2246 $data = array_fill(0, (
int)(($size + 7) / 8), 0);
2247 $bytes = (int)($size / 8);
2249 for ($i=0; $i<$bytes; $i++) {
2251 for ($j=0; $j<8; $j++) {
2260 for ($j=0; $j<($size & 7); $j++) {
2283 protected function qrstrset($srctab, $x, $y, $repl, $replLen=
false) {
2284 $srctab[
$y] = substr_replace($srctab[$y], ($replLen !==
false)?substr($repl,0,$replLen):$repl, $x, ($replLen !==
false)?$replLen:strlen($repl));
2294 protected function getDataLength($version, $level) {
2295 return $this->capacity[$version][QRCAP_WORDS] - $this->capacity[$version][QRCAP_EC][$level];
2304 protected function getECCLength($version, $level){
2305 return $this->capacity[$version][QRCAP_EC][$level];
2313 protected function getWidth($version) {
2314 return $this->capacity[$version][QRCAP_WIDTH];
2322 protected function getRemainder($version) {
2323 return $this->capacity[$version][QRCAP_REMINDER];
2332 protected function getMinimumVersion($size, $level) {
2333 for ($i=1; $i <= QRSPEC_VERSION_MAX; ++$i) {
2334 $words = $this->capacity[$i][QRCAP_WORDS] - $this->capacity[$i][QRCAP_EC][$level];
2335 if ($words >= $size) {
2348 protected function lengthIndicator($mode, $version) {
2349 if ($mode == QR_MODE_ST) {
2352 if ($version <= 9) {
2354 } elseif ($version <= 26) {
2359 return $this->lengthTableBits[$mode][
$l];
2368 protected function maximumWords($mode, $version) {
2369 if ($mode == QR_MODE_ST) {
2372 if ($version <= 9) {
2374 }
else if ($version <= 26) {
2379 $bits = $this->lengthTableBits[$mode][
$l];
2380 $words = (1 << $bits) - 1;
2381 if ($mode == QR_MODE_KJ) {
2394 protected function getEccSpec($version, $level, $spec) {
2395 if (count($spec) < 5) {
2396 $spec = array(0, 0, 0, 0, 0);
2398 $b1 = $this->eccTable[$version][$level][0];
2399 $b2 = $this->eccTable[$version][$level][1];
2400 $data = $this->getDataLength($version, $level);
2401 $ecc = $this->getECCLength($version, $level);
2404 $spec[1] = (int)(
$data / $b1);
2405 $spec[2] = (int)($ecc / $b1);
2410 $spec[1] = (int)(
$data / ($b1 + $b2));
2411 $spec[2] = (int)($ecc / ($b1 + $b2));
2413 $spec[4] = $spec[1] + 1;
2426 protected function putAlignmentMarker($frame, $ox, $oy) {
2428 "\xa1\xa1\xa1\xa1\xa1",
2429 "\xa1\xa0\xa0\xa0\xa1",
2430 "\xa1\xa0\xa1\xa0\xa1",
2431 "\xa1\xa0\xa0\xa0\xa1",
2432 "\xa1\xa1\xa1\xa1\xa1"
2436 for ($y=0; $y < 5; $y++) {
2437 $frame = $this->qrstrset($frame, $xStart, $yStart+$y, $finder[$y]);
2449 protected function putAlignmentPattern($version, $frame, $width) {
2453 $d = $this->alignmentPattern[$version][1] - $this->alignmentPattern[$version][0];
2457 $w = (int)(($width - $this->alignmentPattern[$version][0]) /
$d + 2);
2459 if ($w * $w - 3 == 1) {
2460 $x = $this->alignmentPattern[$version][0];
2461 $y = $this->alignmentPattern[$version][0];
2462 $frame = $this->putAlignmentMarker($frame, $x, $y);
2465 $cx = $this->alignmentPattern[$version][0];
2467 for ($x=1; $x < $wo; ++
$x) {
2468 $frame = $this->putAlignmentMarker($frame, 6, $cx);
2469 $frame = $this->putAlignmentMarker($frame, $cx, 6);
2472 $cy = $this->alignmentPattern[$version][0];
2473 for ($y=0; $y < $wo; ++
$y) {
2474 $cx = $this->alignmentPattern[$version][0];
2475 for ($x=0; $x < $wo; ++
$x) {
2476 $frame = $this->putAlignmentMarker($frame, $cx, $cy);
2489 protected function getVersionPattern($version) {
2490 if (($version < 7) OR ($version > QRSPEC_VERSION_MAX)) {
2493 return $this->versionPattern[($version - 7)];
2502 protected function getFormatInfo($mask, $level) {
2503 if (($mask < 0) OR ($mask > 7)) {
2506 if (($level < 0) OR ($level > 3)) {
2509 return $this->formatInfo[$level][$mask];
2520 protected function putFinderPattern($frame, $ox, $oy) {
2522 "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
2523 "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
2524 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
2525 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
2526 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
2527 "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
2528 "\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
2530 for ($y=0; $y < 7; $y++) {
2531 $frame = $this->qrstrset($frame, $ox, ($oy + $y), $finder[$y]);
2541 protected function createFrame($version) {
2542 $width = $this->capacity[$version][QRCAP_WIDTH];
2543 $frameLine = str_repeat (
"\0", $width);
2544 $frame = array_fill(0, $width, $frameLine);
2546 $frame = $this->putFinderPattern($frame, 0, 0);
2547 $frame = $this->putFinderPattern($frame, $width - 7, 0);
2548 $frame = $this->putFinderPattern($frame, 0, $width - 7);
2550 $yOffset = $width - 7;
2551 for ($y=0; $y < 7; ++
$y) {
2552 $frame[
$y][7] =
"\xc0";
2553 $frame[
$y][$width - 8] =
"\xc0";
2554 $frame[$yOffset][7] =
"\xc0";
2557 $setPattern = str_repeat(
"\xc0", 8);
2558 $frame = $this->qrstrset($frame, 0, 7, $setPattern);
2559 $frame = $this->qrstrset($frame, $width-8, 7, $setPattern);
2560 $frame = $this->qrstrset($frame, 0, $width - 8, $setPattern);
2562 $setPattern = str_repeat(
"\x84", 9);
2563 $frame = $this->qrstrset($frame, 0, 8, $setPattern);
2564 $frame = $this->qrstrset($frame, $width - 8, 8, $setPattern, 8);
2565 $yOffset = $width - 8;
2566 for ($y=0; $y < 8; ++
$y,++$yOffset) {
2567 $frame[
$y][8] =
"\x84";
2568 $frame[$yOffset][8] =
"\x84";
2572 for ($i=1; $i < $wo; ++$i) {
2573 $frame[6][7+$i] = chr(0x90 | ($i & 1));
2574 $frame[7+$i][6] = chr(0x90 | ($i & 1));
2577 $frame = $this->putAlignmentPattern($version, $frame, $width);
2579 if ($version >= 7) {
2580 $vinf = $this->getVersionPattern($version);
2582 for ($x=0; $x<6; ++
$x) {
2583 for ($y=0; $y<3; ++
$y) {
2584 $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1));
2589 for ($y=0; $y<6; ++
$y) {
2590 for ($x=0; $x<3; ++
$x) {
2591 $frame[
$y][$x+($width - 11)] = chr(0x88 | ($v & 1));
2597 $frame[$width - 8][8] =
"\x81";
2606 protected function newFrame($version) {
2607 if (($version < 1) OR ($version > QRSPEC_VERSION_MAX)) {
2610 if (!isset($this->frames[$version])) {
2611 $this->frames[$version] = $this->createFrame($version);
2613 if (is_null($this->frames[$version])) {
2616 return $this->frames[$version];
2624 protected function rsBlockNum($spec) {
2625 return ($spec[0] + $spec[3]);
2633 protected function rsBlockNum1($spec) {
2642 protected function rsDataCodes1($spec) {
2651 protected function rsEccCodes1($spec) {
2660 protected function rsBlockNum2($spec) {
2669 protected function rsDataCodes2($spec) {
2678 protected function rsEccCodes2($spec) {
2687 protected function rsDataLength($spec) {
2688 return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]);
2696 protected function rsEccLength($spec) {
2697 return ($spec[0] + $spec[3]) * $spec[2];
2714 protected function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) {
2715 foreach ($this->rsitems as $rs) {
2716 if (($rs[
'pad'] != $pad) OR ($rs[
'nroots'] != $nroots) OR ($rs[
'mm'] != $symsize)
2717 OR ($rs[
'gfpoly'] != $gfpoly) OR ($rs[
'fcr'] != $fcr) OR ($rs[
'prim'] != $prim)) {
2722 $rs = $this->init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
2723 array_unshift($this->rsitems, $rs);
2737 protected function modnn($rs, $x) {
2738 while ($x >= $rs[
'nn']) {
2740 $x = ($x >> $rs[
'mm']) + ($x & $rs[
'nn']);
2755 protected function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) {
2759 if (($symsize < 0) OR ($symsize > 8)) {
2762 if (($fcr < 0) OR ($fcr >= (1<<$symsize))) {
2765 if (($prim <= 0) OR ($prim >= (1<<$symsize))) {
2768 if (($nroots < 0) OR ($nroots >= (1<<$symsize))) {
2771 if (($pad < 0) OR ($pad >= ((1<<$symsize) -1 - $nroots))) {
2775 $rs[
'mm'] = $symsize;
2776 $rs[
'nn'] = (1 << $symsize) - 1;
2778 $rs[
'alpha_to'] = array_fill(0, ($rs[
'nn'] + 1), 0);
2779 $rs[
'index_of'] = array_fill(0, ($rs[
'nn'] + 1), 0);
2784 $rs[
'index_of'][0] = $A0;
2785 $rs[
'alpha_to'][$A0] = 0;
2787 for ($i=0; $i<$rs[
'nn']; ++$i) {
2788 $rs[
'index_of'][$sr] = $i;
2789 $rs[
'alpha_to'][$i] = $sr;
2791 if ($sr & (1 << $symsize)) {
2801 $rs[
'genpoly'] = array_fill(0, ($nroots + 1), 0);
2803 $rs[
'prim'] = $prim;
2804 $rs[
'nroots'] = $nroots;
2805 $rs[
'gfpoly'] = $gfpoly;
2807 for ($iprim=1; ($iprim % $prim) != 0; $iprim += $rs[
'nn']) {
2810 $rs[
'iprim'] = (int)($iprim / $prim);
2811 $rs[
'genpoly'][0] = 1;
2812 for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
2813 $rs[
'genpoly'][$i+1] = 1;
2815 for ($j = $i; $j > 0; --$j) {
2816 if ($rs[
'genpoly'][$j] != 0) {
2817 $rs[
'genpoly'][$j] = $rs[
'genpoly'][$j-1] ^ $rs[
'alpha_to'][$this->modnn($rs, $rs[
'index_of'][$rs[
'genpoly'][$j]] + $root)];
2819 $rs[
'genpoly'][$j] = $rs[
'genpoly'][$j-1];
2823 $rs[
'genpoly'][0] = $rs[
'alpha_to'][$this->modnn($rs, $rs[
'index_of'][$rs[
'genpoly'][0]] + $root)];
2826 for ($i = 0; $i <= $nroots; ++$i) {
2827 $rs[
'genpoly'][$i] = $rs[
'index_of'][$rs[
'genpoly'][$i]];
2839 protected function encode_rs_char($rs,
$data, $parity) {
2842 $ALPHA_TO =& $rs[
'alpha_to'];
2843 $INDEX_OF =& $rs[
'index_of'];
2844 $GENPOLY =& $rs[
'genpoly'];
2845 $NROOTS =& $rs[
'nroots'];
2847 $PRIM =& $rs[
'prim'];
2848 $IPRIM =& $rs[
'iprim'];
2851 $parity = array_fill(0, $NROOTS, 0);
2852 for ($i=0; $i < ($NN - $NROOTS - $PAD); $i++) {
2853 $feedback = $INDEX_OF[
$data[$i] ^ $parity[0]];
2854 if ($feedback != $A0) {
2858 $feedback = $this->modnn($rs, $NN - $GENPOLY[$NROOTS] + $feedback);
2859 for ($j=1; $j < $NROOTS; ++$j) {
2860 $parity[$j] ^= $ALPHA_TO[$this->modnn($rs, $feedback + $GENPOLY[($NROOTS - $j)])];
2864 array_shift($parity);
2865 if ($feedback != $A0) {
2866 array_push($parity, $ALPHA_TO[$this->modnn($rs, $feedback + $GENPOLY[0])]);
2868 array_push($parity, 0);