com-tecnick-tcpdf
[ class tree: com-tecnick-tcpdf ] [ index: com-tecnick-tcpdf ] [ all elements ]

Source for file qrcode.php

Documentation is available at qrcode.php

  1. <?php
  2. //============================================================+
  3. // File name   : qrcode.php
  4. // Version     : 1.0.006
  5. // Begin       : 2010-03-22
  6. // Last Update : 2010-08-30
  7. // Author      : Nicola Asuni - Tecnick.com S.r.l - Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
  8. // License     : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
  9. // -------------------------------------------------------------------
  10. // Copyright (C) 2010-2010  Nicola Asuni - Tecnick.com S.r.l.
  11. //
  12. // This file is part of TCPDF software library.
  13. //
  14. // TCPDF is free software: you can redistribute it and/or modify it
  15. // under the terms of the GNU Lesser General Public License as
  16. // published by the Free Software Foundation, either version 3 of the
  17. // License, or (at your option) any later version.
  18. //
  19. // TCPDF is distributed in the hope that it will be useful, but
  20. // WITHOUT ANY WARRANTY; without even the implied warranty of
  21. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  22. // See the GNU Lesser General Public License for more details.
  23. //
  24. // You should have received a copy of the GNU Lesser General Public License
  25. // along with TCPDF.  If not, see <http://www.gnu.org/licenses/>.
  26. //
  27. // See LICENSE.TXT file for more information.
  28. // -------------------------------------------------------------------
  29. //
  30. // DESCRIPTION :
  31. //
  32. // Class to create QR-code arrays for TCPDF class.
  33. // QR Code symbol is a 2D barcode that can be scanned by
  34. // handy terminals such as a mobile phone with CCD.
  35. // The capacity of QR Code is up to 7000 digits or 4000
  36. // characters, and has high robustness.
  37. // This class supports QR Code model 2, described in
  38. // JIS (Japanese Industrial Standards) X0510:2004
  39. // or ISO/IEC 18004.
  40. // Currently the following features are not supported:
  41. // ECI and FNC1 mode, Micro QR Code, QR Code model 1,
  42. // Structured mode.
  43. //
  44. // This class is derived from the following projects:
  45. // ---------------------------------------------------------
  46. // "PHP QR Code encoder"
  47. // License: GNU-LGPLv3
  48. // Copyright (C) 2010 by Dominik Dzienia <deltalab at poczta dot fm>
  49. // http://phpqrcode.sourceforge.net/
  50. // https://sourceforge.net/projects/phpqrcode/
  51. //
  52. // The "PHP QR Code encoder" is based on
  53. // "C libqrencode library" (ver. 3.1.1)
  54. // License: GNU-LGPL 2.1
  55. // Copyright (C) 2006-2010 by Kentaro Fukuchi
  56. // http://megaui.net/fukuchi/works/qrencode/index.en.html
  57. //
  58. // Reed-Solomon code encoder is written by Phil Karn, KA9Q.
  59. // Copyright (C) 2002-2006 Phil Karn, KA9Q
  60. //
  61. // QR Code is registered trademark of DENSO WAVE INCORPORATED
  62. // http://www.denso-wave.com/qrcode/index-e.html
  63. // ---------------------------------------------------------
  64. //============================================================+
  65.  
  66. /**
  67.  * Class to create QR-code arrays for TCPDF class.
  68.  * QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD.
  69.  * The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness.
  70.  * This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004.
  71.  * Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode.
  72.  *
  73.  * This class is derived from "PHP QR Code encoder" by Dominik Dzienia (http://phpqrcode.sourceforge.net/) based on "libqrencode C library 3.1.1." by Kentaro Fukuchi (http://megaui.net/fukuchi/works/qrencode/index.en.html), contains Reed-Solomon code written by Phil Karn, KA9Q. QR Code is registered trademark of DENSO WAVE INCORPORATED (http://www.denso-wave.com/qrcode/index-e.html).
  74.  * Please read comments on this class source file for full copyright and license information.
  75.  *
  76.  * @package com.tecnick.tcpdf
  77.  * @abstract Class for generating QR-code array for TCPDF.
  78.  * @author Nicola Asuni
  79.  * @copyright 2010-2010 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
  80.  * @link http://www.tcpdf.org
  81.  * @license http://www.gnu.org/copyleft/lesser.html LGPL
  82.  * @version 1.0.006
  83.  */
  84.  
  85. // definitions
  86. if (!defined('QRCODEDEFS')) {
  87.  
  88.     /**
  89.      * Indicate that definitions for this class are set
  90.      */
  91.     define('QRCODEDEFS', true);
  92.  
  93.     // -----------------------------------------------------
  94.  
  95.     // Encoding modes (characters which can be encoded in QRcode)
  96.  
  97.     /**
  98.      * Encoding mode
  99.      */
  100.     define('QR_MODE_NL', -1);
  101.  
  102.     /**
  103.      * Encoding mode numeric (0-9). 3 characters are encoded to 10bit length. In theory, 7089 characters or less can be stored in a QRcode.
  104.      */
  105.     define('QR_MODE_NM', 0);
  106.  
  107.     /**
  108.      * Encoding mode alphanumeric (0-9A-Z $%*+-./:) 45characters. 2 characters are encoded to 11bit length. In theory, 4296 characters or less can be stored in a QRcode.
  109.      */
  110.     define('QR_MODE_AN', 1);
  111.  
  112.     /**
  113.      * Encoding mode 8bit byte data. In theory, 2953 characters or less can be stored in a QRcode.
  114.      */
  115.     define('QR_MODE_8B', 2);
  116.  
  117.     /**
  118.      * Encoding mode KANJI. A KANJI character (multibyte character) is encoded to 13bit length. In theory, 1817 characters or less can be stored in a QRcode.
  119.      */
  120.     define('QR_MODE_KJ', 3);
  121.  
  122.     /**
  123.      * Encoding mode STRUCTURED (currently unsupported)
  124.      */
  125.     define('QR_MODE_ST', 4);
  126.  
  127.     // -----------------------------------------------------
  128.  
  129.     // Levels of error correction.
  130.     // QRcode has a function of an error correcting for miss reading that white is black.
  131.     // Error correcting is defined in 4 level as below.
  132.  
  133.     /**
  134.      * Error correction level L : About 7% or less errors can be corrected.
  135.      */
  136.     define('QR_ECLEVEL_L', 0);
  137.  
  138.     /**
  139.      * Error correction level M : About 15% or less errors can be corrected.
  140.      */
  141.     define('QR_ECLEVEL_M', 1);
  142.  
  143.     /**
  144.      * Error correction level Q : About 25% or less errors can be corrected.
  145.      */
  146.     define('QR_ECLEVEL_Q', 2);
  147.  
  148.     /**
  149.      * Error correction level H : About 30% or less errors can be corrected.
  150.      */
  151.     define('QR_ECLEVEL_H', 3);
  152.  
  153.     // -----------------------------------------------------
  154.  
  155.     // Version. Size of QRcode is defined as version.
  156.     // Version is from 1 to 40.
  157.     // Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases.
  158.     // So version 40 is 177*177 matrix.
  159.  
  160.     /**
  161.      * Maximum QR Code version.
  162.      */
  163.     define('QRSPEC_VERSION_MAX', 40);
  164.  
  165.     /**
  166.      * Maximum matrix size for maximum version (version 40 is 177*177 matrix).
  167.      */
  168.     define('QRSPEC_WIDTH_MAX', 177);
  169.  
  170.     // -----------------------------------------------------
  171.  
  172.     /**
  173.      * Matrix index to get width from $capacity array.
  174.      */
  175.     define('QRCAP_WIDTH',    0);
  176.  
  177.     /**
  178.      * Matrix index to get number of words from $capacity array.
  179.      */
  180.     define('QRCAP_WORDS',    1);
  181.  
  182.     /**
  183.      * Matrix index to get remainder from $capacity array.
  184.      */
  185.     define('QRCAP_REMINDER', 2);
  186.  
  187.     /**
  188.      * Matrix index to get error correction level from $capacity array.
  189.      */
  190.     define('QRCAP_EC',       3);
  191.  
  192.     // -----------------------------------------------------
  193.  
  194.     // Structure (currently usupported)
  195.  
  196.     /**
  197.      * Number of header bits for structured mode
  198.      */
  199.     define('STRUCTURE_HEADER_BITS',  20);
  200.  
  201.     /**
  202.      * Max number of symbols for structured mode
  203.      */
  204.     define('MAX_STRUCTURED_SYMBOLS', 16);
  205.  
  206.     // -----------------------------------------------------
  207.  
  208.     // Masks
  209.  
  210.     /**
  211.      * Down point base value for case 1 mask pattern (concatenation of same color in a line or a column)
  212.      */
  213.     define('N1',  3);
  214.  
  215.     /**
  216.      * Down point base value for case 2 mask pattern (module block of same color)
  217.      */
  218.     define('N2',  3);
  219.  
  220.     /**
  221.      * Down point base value for case 3 mask pattern (1:1:3:1:1(dark:bright:dark:bright:dark)pattern in a line or a column)
  222.      */
  223.     define('N3', 40);
  224.  
  225.     /**
  226.      * Down point base value for case 4 mask pattern (ration of dark modules in whole)
  227.      */
  228.     define('N4', 10);
  229.  
  230.     // -----------------------------------------------------
  231.  
  232.     // Optimization settings
  233.  
  234.     /**
  235.      * if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
  236.      */
  237.     define('QR_FIND_BEST_MASK', true);
  238.  
  239.     /**
  240.      * if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
  241.      */
  242.     define('QR_FIND_FROM_RANDOM', 2);
  243.  
  244.     /**
  245.      * when QR_FIND_BEST_MASK === false
  246.      */
  247.     define('QR_DEFAULT_MASK', 2);
  248.  
  249.     // -----------------------------------------------------
  250.  
  251. } // end of definitions
  252.  
  253. // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
  254.  
  255. if (!class_exists('QRcode', false)) {
  256.  
  257.     // for compatibility with PHP4
  258.     if (!function_exists('str_split')) {
  259.         /**
  260.          * Convert a string to an array (needed for PHP4 compatibility)
  261.          * @param string $string The input string.
  262.          * @param int $split_length Maximum length of the chunk.
  263.          * @return  If the optional split_length  parameter is specified, the returned array will be broken down into chunks with each being split_length  in length, otherwise each chunk will be one character in length. FALSE is returned if split_length is less than 1. If the split_length length exceeds the length of string , the entire string is returned as the first (and only) array element.
  264.          */
  265.         function str_split($string, $split_length=1) {
  266.             if ((strlen($string) > $split_length) OR (!$split_length)) {
  267.                 do {
  268.                     $c = strlen($string);
  269.                     $parts[] = substr($string, 0, $split_length);
  270.                     $string = substr($string, $split_length);
  271.                 } while ($string !== false);
  272.             } else {
  273.                 $parts = array($string);
  274.             }
  275.             return $parts;
  276.         }
  277.     }
  278.  
  279.     // #####################################################
  280.  
  281.     /**
  282.      * Class to create QR-code arrays for TCPDF class.
  283.      * QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD.
  284.      * The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness.
  285.      * This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004.
  286.      * Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode.
  287.      *
  288.      * This class is derived from "PHP QR Code encoder" by Dominik Dzienia (http://phpqrcode.sourceforge.net/) based on "libqrencode C library 3.1.1." by Kentaro Fukuchi (http://megaui.net/fukuchi/works/qrencode/index.en.html), contains Reed-Solomon code written by Phil Karn, KA9Q. QR Code is registered trademark of DENSO WAVE INCORPORATED (http://www.denso-wave.com/qrcode/index-e.html).
  289.      * Please read comments on this class source file for full copyright and license information.
  290.      *
  291.      * @name QRcode
  292.      * @package com.tecnick.tcpdf
  293.      * @abstract Class for generating QR-code array for TCPDF.
  294.      * @author Nicola Asuni
  295.      * @copyright 2010-2010 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
  296.      * @link http://www.tcpdf.org
  297.      * @license http://www.gnu.org/copyleft/lesser.html LGPL
  298.      * @version 1.0.006
  299.      */
  300.     class QRcode {
  301.  
  302.         /**
  303.          * @var barcode array to be returned which is readable by TCPDF
  304.          * @access protected
  305.          */
  306.         protected $barcode_array = array();
  307.  
  308.         /**
  309.          * @var QR code version. Size of QRcode is defined as version. Version is from 1 to 40. Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases. So version 40 is 177*177 matrix.
  310.          * @access protected
  311.          */
  312.         protected $version = 0;
  313.  
  314.         /**
  315.          * @var Levels of error correction. See definitions for possible values.
  316.          * @access protected
  317.          */
  318.         protected $level = QR_ECLEVEL_L;
  319.  
  320.         /**
  321.          * @var Encoding mode
  322.          * @access protected
  323.          */
  324.         protected $hint = QR_MODE_8B;
  325.  
  326.         /**
  327.          * @var if true the input string will be converted to uppercase
  328.          * @access protected
  329.          */
  330.         protected $casesensitive = true;
  331.  
  332.         /**
  333.          * @var structured QR code (not supported yet)
  334.          * @access protected
  335.          */
  336.         protected $structured = 0;
  337.  
  338.         /**
  339.          * @var mask data
  340.          * @access protected
  341.          */
  342.         protected $data;
  343.  
  344.         // FrameFiller
  345.  
  346.         /**
  347.          * @var width 
  348.          * @access protected
  349.          */
  350.         protected $width;
  351.  
  352.         /**
  353.          * @var frame 
  354.          * @access protected
  355.          */
  356.         protected $frame;
  357.  
  358.         /**
  359.          * @var X position of bit
  360.          * @access protected
  361.          */
  362.         protected $x;
  363.  
  364.         /**
  365.          * @var Y position of bit
  366.          * @access protected
  367.          */
  368.         protected $y;
  369.  
  370.         /**
  371.          * @var direction 
  372.          * @access protected
  373.          */
  374.         protected $dir;
  375.  
  376.         /**
  377.          * @var single bit
  378.          * @access protected
  379.          */
  380.         protected $bit;
  381.  
  382.         // ---- QRrawcode ----
  383.  
  384.         /**
  385.          * @var data code
  386.          * @access protected
  387.          */
  388.         protected $datacode = array();
  389.  
  390.         /**
  391.          * @var error correction code
  392.          * @access protected
  393.          */
  394.         protected $ecccode = array();
  395.  
  396.         /**
  397.          * @var blocks 
  398.          * @access protected
  399.          */
  400.         protected $blocks;
  401.  
  402.         /**
  403.          * @var Reed-Solomon blocks
  404.          * @access protected
  405.          */
  406.         protected $rsblocks = array(); //of RSblock
  407.  
  408.         /**
  409.          * @var counter 
  410.          * @access protected
  411.          */
  412.         protected $count;
  413.  
  414.         /**
  415.          * @var data length
  416.          * @access protected
  417.          */
  418.         protected $dataLength;
  419.  
  420.         /**
  421.          * @var error correction length
  422.          * @access protected
  423.          */
  424.         protected $eccLength;
  425.  
  426.         /**
  427.          * @var b1 
  428.          * @access protected
  429.          */
  430.         protected $b1;
  431.  
  432.         // ---- QRmask ----
  433.  
  434.         /**
  435.          * @var run length
  436.          * @access protected
  437.          */
  438.         protected $runLength = array();
  439.  
  440.         // ---- QRsplit ----
  441.  
  442.         /**
  443.          * @var input data string
  444.          * @access protected
  445.          */
  446.         protected $dataStr = '';
  447.  
  448.         /**
  449.          * @var input items
  450.          * @access protected
  451.          */
  452.         protected $items;
  453.  
  454.         // Reed-Solomon items
  455.  
  456.         /**
  457.          * @var Reed-Solomon items
  458.          * @access protected
  459.          */
  460.         protected $rsitems = array();
  461.  
  462.         /**
  463.          * @var array of frames
  464.          * @access protected
  465.          */
  466.         protected $frames = array();
  467.  
  468.         /**
  469.          * @var alphabet-numeric convesion table
  470.          * @access protected
  471.          */
  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  //
  481.             );
  482.  
  483.         /**
  484.          * @var array Table of the capacity of symbols
  485.          *  See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004.
  486.          * @access protected
  487.          */
  488.         protected $capacity = array(
  489.             array(  0,    0, 0, array(   0,    0,    0,    0)), //
  490.             array( 21,   26, 0, array(   7,   10,   13,   17)), //  1
  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)), //  5
  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)), // 10
  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)), // 15
  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)), // 20
  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)), // 25
  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)), // 30
  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)), // 35
  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))  // 40
  530.         );
  531.  
  532.         /**
  533.          * @var array Length indicator
  534.          * @access protected
  535.          */
  536.         protected $lengthTableBits = array(
  537.             array(10, 12, 14),
  538.             array( 9, 11, 13),
  539.             array( 8, 16, 16),
  540.             array( 8, 10, 12)
  541.         );
  542.  
  543.         /**
  544.          * @var array Table of the error correction code (Reed-Solomon block)
  545.          *  See Table 12-16 (pp.30-36), JIS X0510:2004.
  546.          * @access protected
  547.          */
  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)), //  1
  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)), //  5
  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)), // 10
  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)), // 15
  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)), // 20
  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)), // 25
  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)), // 30
  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)), // 35
  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))  // 40
  590.         );
  591.  
  592.         /**
  593.          * @var array Positions of alignment patterns.
  594.          *  This array includes only the second and the third position of the alignment patterns. Rest of them can be calculated from the distance between them.
  595.          *  See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
  596.          * @access protected
  597.          */
  598.         protected $alignmentPattern = array(
  599.             array( 0,  0),
  600.             array( 0,  0), array(18,  0), array(22,  0), array(26,  0), array(30,  0), //  1- 5
  601.             array(34,  0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), //  6-10
  602.             array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), // 11-15
  603.             array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), // 16-20
  604.             array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), // 21-25
  605.             array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), // 26-30
  606.             array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), // 31-35
  607.             array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58)  // 35-40
  608.         );
  609.  
  610.         /**
  611.          * @var array Version information pattern (BCH coded).
  612.          *  See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
  613.          *  size: [QRSPEC_VERSION_MAX - 6]
  614.          * @access protected
  615.          */
  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, //
  621.             0x27541, 0x28c69
  622.         );
  623.  
  624.         /**
  625.          * @var array Format information
  626.          * @access protected
  627.          */
  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)  //
  633.         );
  634.  
  635.  
  636.         // -------------------------------------------------
  637.         // -------------------------------------------------
  638.  
  639.  
  640.         /**
  641.          * This is the class constructor.
  642.          * Creates a QRcode object
  643.          * @param string $code code to represent using QRcode
  644.          * @param string $eclevel error level: <ul><li>L : About 7% or less errors can be corrected.</li><li>M : About 15% or less errors can be corrected.</li><li>Q : About 25% or less errors can be corrected.</li><li>H : About 30% or less errors can be corrected.</li></ul>
  645.          * @access public
  646.          * @since 1.0.000
  647.          */
  648.         public function __construct($code, $eclevel = 'L') {
  649.             $barcode_array = array();
  650.             if ((is_null($code)) OR ($code == '\0') OR ($code == '')) {
  651.                 return false;
  652.             }
  653.             // set error correction level
  654.             $this->level = array_search($eclevel, array('L', 'M', 'Q', 'H'));
  655.             if ($this->level === false) {
  656.                 $this->level = QR_ECLEVEL_L;
  657.             }
  658.             if (($this->hint != QR_MODE_8B) AND ($this->hint != QR_MODE_KJ)) {
  659.                 return false;
  660.             }
  661.             if (($this->version < 0) OR ($this->version > QRSPEC_VERSION_MAX)) {
  662.                 return false;
  663.             }
  664.             $this->items = array();
  665.             $this->encodeString($code);
  666.             if (is_null($this->data)) {
  667.                 return false;
  668.             }
  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) {
  675.                 $arrAdd = array();
  676.                 foreach (str_split($line) as $char) {
  677.                     $arrAdd[] = ($char=='1')?1:0;
  678.                 }
  679.                 $barcode_array['bcode'][] = $arrAdd;
  680.             }
  681.             $this->barcode_array = $barcode_array;
  682.         }
  683.  
  684.         /**
  685.          * Returns a barcode array which is readable by TCPDF
  686.          * @return array barcode array readable by TCPDF;
  687.          * @access public
  688.          */
  689.         public function getBarcodeArray() {
  690.             return $this->barcode_array;
  691.         }
  692.  
  693.         /**
  694.          * Convert the frame in binary form
  695.          * @param array $frame array to binarize
  696.          * @return array frame in binary form
  697.          */
  698.         protected function binarize($frame) {
  699.             $len = count($frame);
  700.             // the frame is square (width = height)
  701.             foreach ($frame as &$frameLine) {
  702.                 for ($i=0; $i<$len; $i++) {
  703.                     $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
  704.                 }
  705.             }
  706.             return $frame;
  707.         }
  708.  
  709.         /**
  710.          * Encode the input string to QR code
  711.          * @param string $string input string to encode
  712.          */
  713.         protected function encodeString($string) {
  714.             $this->dataStr = $string;
  715.             if (!$this->casesensitive) {
  716.                 $this->toUpper();
  717.             }
  718.             $ret = $this->splitString();
  719.             if ($ret < 0) {
  720.                 return NULL;
  721.             }
  722.             $this->encodeMask(-1);
  723.         }
  724.  
  725.         /**
  726.          * Encode mask
  727.          * @param int $mask masking mode
  728.          */
  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)) {
  733.                 return NULL;
  734.             }
  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);
  742.             if ($ret < 0) {
  743.                 return NULL;
  744.             }
  745.             $this->count = 0;
  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;
  750.             $this->dir = -1;
  751.             $this->bit = -1;
  752.             // inteleaved data and ecc codes
  753.             for ($i=0; $i < ($this->dataLength + $this->eccLength); $i++) {
  754.                 $code = $this->getCode();
  755.                 $bit = 0x80;
  756.                 for ($j=0; $j<8; $j++) {
  757.                     $addr = $this->getNextPosition();
  758.                     $this->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
  759.                     $bit = $bit >> 1;
  760.                 }
  761.             }
  762.             // remainder bits
  763.             $j = $this->getRemainder($this->version);
  764.             for ($i=0; $i<$j; $i++) {
  765.                 $addr = $this->getNextPosition();
  766.                 $this->setFrameAt($addr, 0x02);
  767.             }
  768.             // masking
  769.             $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
  770.             if ($mask < 0) {
  771.                 if (QR_FIND_BEST_MASK) {
  772.                     $masked = $this->mask($this->width, $this->frame, $this->level);
  773.                 } else {
  774.                     $masked = $this->makeMask($this->width, $this->frame, (intval(QR_DEFAULT_MASK) % 8), $this->level);
  775.                 }
  776.             } else {
  777.                 $masked = $this->makeMask($this->width, $this->frame, $mask, $this->level);
  778.             }
  779.             if ($masked == NULL) {
  780.                 return NULL;
  781.             }
  782.             $this->data = $masked;
  783.         }
  784.  
  785.         // - - - - - - - - - - - - - - - - - - - - - - - - -
  786.  
  787.         // FrameFiller
  788.  
  789.         /**
  790.          * Set frame value at specified position
  791.          * @param array $at x,y position
  792.          * @param int $val value of the character to set
  793.          */
  794.         protected function setFrameAt($at, $val) {
  795.             $this->frame[$at['y']][$at['x']] = chr($val);
  796.         }
  797.  
  798.         /**
  799.          * Get frame value at specified position
  800.          * @param array $at x,y position
  801.          * @return value at specified position
  802.          */
  803.         protected function getFrameAt($at) {
  804.             return ord($this->frame[$at['y']][$at['x']]);
  805.         }
  806.  
  807.         /**
  808.          * Return the next frame position
  809.          * @return array of x,y coordinates
  810.          */
  811.         protected function getNextPosition() {
  812.             do {
  813.                 if ($this->bit == -1) {
  814.                     $this->bit = 0;
  815.                     return array('x'=>$this->x, 'y'=>$this->y);
  816.                 }
  817.                 $x = $this->x;
  818.                 $y = $this->y;
  819.                 $w = $this->width;
  820.                 if ($this->bit == 0) {
  821.                     $x--;
  822.                     $this->bit++;
  823.                 } else {
  824.                     $x++;
  825.                     $y += $this->dir;
  826.                     $this->bit--;
  827.                 }
  828.                 if ($this->dir < 0) {
  829.                     if ($y < 0) {
  830.                         $y = 0;
  831.                         $x -= 2;
  832.                         $this->dir = 1;
  833.                         if ($x == 6) {
  834.                             $x--;
  835.                             $y = 9;
  836.                         }
  837.                     }
  838.                 } else {
  839.                     if ($y == $w) {
  840.                         $y = $w - 1;
  841.                         $x -= 2;
  842.                         $this->dir = -1;
  843.                         if ($x == 6) {
  844.                             $x--;
  845.                             $y -= 8;
  846.                         }
  847.                     }
  848.                 }
  849.                 if (($x < 0) OR ($y < 0)) {
  850.                     return NULL;
  851.                 }
  852.                 $this->x = $x;
  853.                 $this->y = $y;
  854.             } while(ord($this->frame[$y][$x]) & 0x80);
  855.             return array('x'=>$x, 'y'=>$y);
  856.         }
  857.  
  858.         // - - - - - - - - - - - - - - - - - - - - - - - - -
  859.  
  860.         // QRrawcode
  861.  
  862.         /**
  863.          * Initialize code.
  864.          * @param array $spec array of ECC specification
  865.          * @return 0 in case of success, -1 in case of error
  866.          */
  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);
  871.             $blockNo = 0;
  872.             $dataPos = 0;
  873.             $eccPos = 0;
  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);
  884.                 $dataPos += $dl;
  885.                 $eccPos += $el;
  886.                 $blockNo++;
  887.             }
  888.             if ($this->rsBlockNum2($spec) == 0) {
  889.                 return 0;
  890.             }
  891.             $dl = $this->rsDataCodes2($spec);
  892.             $el = $this->rsEccCodes2($spec);
  893.             $rs = $this->init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
  894.             if ($rs == NULL) {
  895.                 return -1;
  896.             }
  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);
  907.                 $dataPos += $dl;
  908.                 $eccPos += $el;
  909.                 $blockNo++;
  910.             }
  911.             return 0;
  912.         }
  913.  
  914.         /**
  915.          * Return Reed-Solomon block code.
  916.          * @return array rsblocks
  917.          */
  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']) {
  923.                     $row += $this->b1;
  924.                 }
  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];
  930.             } else {
  931.                 return 0;
  932.             }
  933.             $this->count++;
  934.             return $ret;
  935.         }
  936.  
  937.         // - - - - - - - - - - - - - - - - - - - - - - - - -
  938.  
  939.         // QRmask
  940.  
  941.         /**
  942.          * Write Format Information on frame and returns the number of black bits
  943.          * @param int $width frame width
  944.          * @param array $frame frame
  945.          * @param array $mask masking mode
  946.          * @param int $level error correction level
  947.          * @return int blacks
  948.          */
  949.          protected function writeFormatInformation($width, &$frame, $mask, $level) {
  950.             $blacks = 0;
  951.             $format =  $this->getFormatInfo($mask, $level);
  952.             for ($i=0; $i<8; ++$i) {
  953.                 if ($format & 1) {
  954.                     $blacks += 2;
  955.                     $v = 0x85;
  956.                 } else {
  957.                     $v = 0x84;
  958.                 }
  959.                 $frame[8][$width - 1 - $i] = chr($v);
  960.                 if ($i < 6) {
  961.                     $frame[$i][8] = chr($v);
  962.                 } else {
  963.                     $frame[$i + 1][8] = chr($v);
  964.                 }
  965.                 $format = $format >> 1;
  966.             }
  967.             for ($i=0; $i<7; ++$i) {
  968.             if ($format & 1) {
  969.                 $blacks += 2;
  970.                 $v = 0x85;
  971.             } else {
  972.                 $v = 0x84;
  973.             }
  974.             $frame[$width - 7 + $i][8] = chr($v);
  975.             if ($i == 0) {
  976.                 $frame[8][7] = chr($v);
  977.             } else {
  978.                 $frame[8][6 - $i] = chr($v);
  979.             }
  980.             $format = $format >> 1;
  981.             }
  982.             return $blacks;
  983.         }
  984.  
  985.         /**
  986.          * mask0
  987.          * @param int $x X position
  988.          * @param int $y Y position
  989.          * @return int mask
  990.          */
  991.          protected function mask0($x, $y) {
  992.             return ($x + $y) & 1;
  993.         }
  994.  
  995.         /**
  996.          * mask1
  997.          * @param int $x X position
  998.          * @param int $y Y position
  999.          * @return int mask
  1000.          */
  1001.          protected function mask1($x, $y) {
  1002.             return ($y & 1);
  1003.         }
  1004.  
  1005.         /**
  1006.          * mask2
  1007.          * @param int $x X position
  1008.          * @param int $y Y position
  1009.          * @return int mask
  1010.          */
  1011.          protected function mask2($x, $y) {
  1012.             return ($x % 3);
  1013.         }
  1014.  
  1015.         /**
  1016.          * mask3
  1017.          * @param int $x X position
  1018.          * @param int $y Y position
  1019.          * @return int mask
  1020.          */
  1021.          protected function mask3($x, $y) {
  1022.             return ($x + $y) % 3;
  1023.         }
  1024.  
  1025.         /**
  1026.          * mask4
  1027.          * @param int $x X position
  1028.          * @param int $y Y position
  1029.          * @return int mask
  1030.          */
  1031.          protected function mask4($x, $y) {
  1032.             return (((int)($y / 2)) + ((int)($x / 3))) & 1;
  1033.         }
  1034.  
  1035.         /**
  1036.          * mask5
  1037.          * @param int $x X position
  1038.          * @param int $y Y position
  1039.          * @return int mask
  1040.          */
  1041.          protected function mask5($x, $y) {
  1042.             return (($x * $y) & 1) + ($x * $y) % 3;
  1043.         }
  1044.  
  1045.         /**
  1046.          * mask6
  1047.          * @param int $x X position
  1048.          * @param int $y Y position
  1049.          * @return int mask
  1050.          */
  1051.          protected function mask6($x, $y) {
  1052.             return ((($x * $y) & 1) + ($x * $y) % 3) & 1;
  1053.         }
  1054.  
  1055.         /**
  1056.          * mask7
  1057.          * @param int $x X position
  1058.          * @param int $y Y position
  1059.          * @return int mask
  1060.          */
  1061.          protected function mask7($x, $y) {
  1062.             return ((($x * $y) % 3) + (($x + $y) & 1)) & 1;
  1063.         }
  1064.  
  1065.         /**
  1066.          * Return bitmask
  1067.          * @param int $maskNo mask number
  1068.          * @param int $width width
  1069.          * @param array $frame frame
  1070.          * @return array bitmask
  1071.          */
  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;
  1078.                     } else {
  1079.                         $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y);
  1080.                         $bitMask[$y][$x] = ($maskFunc == 0)?1:0;
  1081.                     }
  1082.                 }
  1083.             }
  1084.             return $bitMask;
  1085.         }
  1086.  
  1087.         /**
  1088.          * makeMaskNo
  1089.          * @param int $maskNo 
  1090.          * @param int $width 
  1091.          * @param int $s 
  1092.          * @param int $d 
  1093.          * @param boolean $maskGenOnly 
  1094.          * @return int b
  1095.          */
  1096.          protected function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly=false) {
  1097.             $b = 0;
  1098.             $bitMask = array();
  1099.             $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
  1100.             if ($maskGenOnly) {
  1101.                 return;
  1102.             }
  1103.             $d = $s;
  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]);
  1108.                     }
  1109.                     $b += (int)(ord($d[$y][$x]) & 1);
  1110.                 }
  1111.             }
  1112.             return $b;
  1113.         }
  1114.  
  1115.         /**
  1116.          * makeMask
  1117.          * @param int $width 
  1118.          * @param array $frame 
  1119.          * @param int $maskNo 
  1120.          * @param int $level 
  1121.          * @return array mask
  1122.          */
  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);
  1127.             return $masked;
  1128.         }
  1129.  
  1130.         /**
  1131.          * calcN1N3
  1132.          * @param int $length 
  1133.          * @return int demerit
  1134.          */
  1135.          protected function calcN1N3($length) {
  1136.             $demerit = 0;
  1137.             for ($i=0; $i<$length; ++$i) {
  1138.                 if ($this->runLength[$i] >= 5) {
  1139.                     $demerit += (N1 + ($this->runLength[$i] - 5));
  1140.                 }
  1141.                 if ($i & 1) {
  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))) {
  1149.                                 $demerit += N3;
  1150.                             } elseif ((($i+3) >= $length) OR ($this->runLength[$i+3] >= (4 * $fact))) {
  1151.                                 $demerit += N3;
  1152.                             }
  1153.                         }
  1154.                     }
  1155.                 }
  1156.             }
  1157.             return $demerit;
  1158.         }
  1159.  
  1160.         /**
  1161.          * evaluateSymbol
  1162.          * @param int $width 
  1163.          * @param array $frame 
  1164.          * @return int demerit
  1165.          */
  1166.          protected function evaluateSymbol($width, $frame) {
  1167.             $head = 0;
  1168.             $demerit = 0;
  1169.             for ($y=0; $y<$width; ++$y) {
  1170.                 $head = 0;
  1171.                 $this->runLength[0] = 1;
  1172.                 $frameY = $frame[$y];
  1173.                 if ($y > 0) {
  1174.                     $frameYM = $frame[$y-1];
  1175.                 }
  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) {
  1181.                             $demerit += N2;
  1182.                         }
  1183.                     }
  1184.                     if (($x == 0) AND (ord($frameY[$x]) & 1)) {
  1185.                         $this->runLength[0] = -1;
  1186.                         $head = 1;
  1187.                         $this->runLength[$head] = 1;
  1188.                     } elseif ($x > 0) {
  1189.                         if ((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
  1190.                             $head++;
  1191.                             $this->runLength[$head] = 1;
  1192.                         } else {
  1193.                             $this->runLength[$head]++;
  1194.                         }
  1195.                     }
  1196.                 }
  1197.                 $demerit += $this->calcN1N3($head+1);
  1198.             }
  1199.             for ($x=0; $x<$width; ++$x) {
  1200.                 $head = 0;
  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;
  1205.                         $head = 1;
  1206.                         $this->runLength[$head] = 1;
  1207.                     } elseif ($y > 0) {
  1208.                         if ((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
  1209.                             $head++;
  1210.                             $this->runLength[$head] = 1;
  1211.                         } else {
  1212.                             $this->runLength[$head]++;
  1213.                         }
  1214.                     }
  1215.                 }
  1216.                 $demerit += $this->calcN1N3($head+1);
  1217.             }
  1218.             return $demerit;
  1219.         }
  1220.  
  1221.         /**
  1222.          * mask
  1223.          * @param int $width 
  1224.          * @param array $frame 
  1225.          * @param int $level 
  1226.          * @return array best mask
  1227.          */
  1228.          protected function mask($width, $frame, $level) {
  1229.             $minDemerit = PHP_INT_MAX;
  1230.             $bestMaskNum = 0;
  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);
  1239.                 }
  1240.             }
  1241.             $bestMask = $frame;
  1242.             foreach ($checked_masks as $i) {
  1243.                 $mask = array_fill(0, $width, str_repeat("\0", $width));
  1244.                 $demerit = 0;
  1245.                 $blacks = 0;
  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;
  1253.                     $bestMask = $mask;
  1254.                     $bestMaskNum = $i;
  1255.                 }
  1256.             }
  1257.             return $bestMask;
  1258.         }
  1259.  
  1260.         // - - - - - - - - - - - - - - - - - - - - - - - - -
  1261.  
  1262.         // QRsplit
  1263.  
  1264.         /**
  1265.          * Return true if the character at specified position is a number
  1266.          * @param string $str string
  1267.          * @param int $pos characted position
  1268.          * @return boolean true of false
  1269.          */
  1270.          protected function isdigitat($str, $pos) {
  1271.             if ($pos >= strlen($str)) {
  1272.                 return false;
  1273.             }
  1274.             return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
  1275.         }
  1276.  
  1277.         /**
  1278.          * Return true if the character at specified position is an alphanumeric character
  1279.          * @param string $str string
  1280.          * @param int $pos characted position
  1281.          * @return boolean true of false
  1282.          */
  1283.          protected function isalnumat($str, $pos) {
  1284.             if ($pos >= strlen($str)) {
  1285.                 return false;
  1286.             }
  1287.             return ($this->lookAnTable(ord($str[$pos])) >= 0);
  1288.         }
  1289.  
  1290.         /**
  1291.          * identifyMode
  1292.          * @param int $pos 
  1293.          * @return int mode
  1294.          */
  1295.          protected function identifyMode($pos) {
  1296.             if ($pos >= strlen($this->dataStr)) {
  1297.                 return QR_MODE_NL;
  1298.             }
  1299.             $c = $this->dataStr[$pos];
  1300.             if ($this->isdigitat($this->dataStr, $pos)) {
  1301.                 return QR_MODE_NM;
  1302.             } elseif ($this->isalnumat($this->dataStr, $pos)) {
  1303.                 return QR_MODE_AN;
  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)) {
  1309.                         return QR_MODE_KJ;
  1310.                     }
  1311.                 }
  1312.             }
  1313.             return QR_MODE_8B;
  1314.         }
  1315.  
  1316.         /**
  1317.          * eatNum
  1318.          * @return int run
  1319.          */
  1320.          protected function eatNum() {
  1321.             $ln = $this->lengthIndicator(QR_MODE_NM, $this->version);
  1322.             $p = 0;
  1323.             while($this->isdigitat($this->dataStr, $p)) {
  1324.                 $p++;
  1325.             }
  1326.             $run = $p;
  1327.             $mode = $this->identifyMode($p);
  1328.             if ($mode == QR_MODE_8B) {
  1329.                 $dif = $this->estimateBitsModeNum($run) + 4 + $ln
  1330.                 + $this->estimateBitsMode8(1)         // + 4 + l8
  1331.                 - $this->estimateBitsMode8($run + 1); // - 4 - l8
  1332.                 if ($dif > 0) {
  1333.                     return $this->eat8();
  1334.                 }
  1335.             }
  1336.             if ($mode == QR_MODE_AN) {
  1337.                 $dif = $this->estimateBitsModeNum($run) + 4 + $ln
  1338.                 + $this->estimateBitsModeAn(1)        // + 4 + la
  1339.                 - $this->estimateBitsModeAn($run + 1);// - 4 - la
  1340.                 if ($dif > 0) {
  1341.                     return $this->eatAn();
  1342.                 }
  1343.             }
  1344.             $this->items = $this->appendNewInputItem($this->items, QR_MODE_NM, $run, str_split($this->dataStr));
  1345.             return $run;
  1346.         }
  1347.  
  1348.         /**
  1349.          * eatAn
  1350.          * @return int run
  1351.          */
  1352.          protected function eatAn() {
  1353.             $la = $this->lengthIndicator(QR_MODE_AN,  $this->version);
  1354.             $ln = $this->lengthIndicator(QR_MODE_NM, $this->version);
  1355.             $p = 0;
  1356.             while($this->isalnumat($this->dataStr, $p)) {
  1357.                 if ($this->isdigitat($this->dataStr, $p)) {
  1358.                     $q = $p;
  1359.                     while($this->isdigitat($this->dataStr, $q)) {
  1360.                         $q++;
  1361.                     }
  1362.                     $dif = $this->estimateBitsModeAn($p) // + 4 + la
  1363.                     + $this->estimateBitsModeNum($q - $p) + 4 + $ln
  1364.                     - $this->estimateBitsModeAn($q); // - 4 - la
  1365.                     if ($dif < 0) {
  1366.                         break;
  1367.                     } else {
  1368.                         $p = $q;
  1369.                     }
  1370.                 } else {
  1371.                     $p++;
  1372.                 }
  1373.             }
  1374.             $run = $p;
  1375.             if (!$this->isalnumat($this->dataStr, $p)) {
  1376.                 $dif = $this->estimateBitsModeAn($run) + 4 + $la
  1377.                 + $this->estimateBitsMode8(1) // + 4 + l8
  1378.                 - $this->estimateBitsMode8($run + 1); // - 4 - l8
  1379.                 if ($dif > 0) {
  1380.                     return $this->eat8();
  1381.                 }
  1382.             }
  1383.             $this->items = $this->appendNewInputItem($this->items, QR_MODE_AN, $run, str_split($this->dataStr));
  1384.             return $run;
  1385.         }
  1386.  
  1387.         /**
  1388.          * eatKanji
  1389.          * @return int run
  1390.          */
  1391.          protected function eatKanji() {
  1392.             $p = 0;
  1393.             while($this->identifyMode($p) == QR_MODE_KJ) {
  1394.                 $p += 2;
  1395.             }
  1396.             $this->items = $this->appendNewInputItem($this->items, QR_MODE_KJ, $p, str_split($this->dataStr));
  1397.             return $run;
  1398.         }
  1399.  
  1400.         /**
  1401.          * eat8
  1402.          * @return int run
  1403.          */
  1404.          protected function eat8() {
  1405.             $la = $this->lengthIndicator(QR_MODE_AN, $this->version);
  1406.             $ln = $this->lengthIndicator(QR_MODE_NM, $this->version);
  1407.             $p = 1;
  1408.             $dataStrLen = strlen($this->dataStr);
  1409.             while($p < $dataStrLen) {
  1410.                 $mode = $this->identifyMode($p);
  1411.                 if ($mode == QR_MODE_KJ) {
  1412.                     break;
  1413.                 }
  1414.                 if ($mode == QR_MODE_NM) {
  1415.                     $q = $p;
  1416.                     while($this->isdigitat($this->dataStr, $q)) {
  1417.                         $q++;
  1418.                     }
  1419.                     $dif = $this->estimateBitsMode8($p) // + 4 + l8
  1420.                     + $this->estimateBitsModeNum($q - $p) + 4 + $ln
  1421.                     - $this->estimateBitsMode8($q); // - 4 - l8
  1422.                     if ($dif < 0) {
  1423.                         break;
  1424.                     } else {
  1425.                         $p = $q;
  1426.                     }
  1427.                 } elseif ($mode == QR_MODE_AN) {
  1428.                     $q = $p;
  1429.                     while($this->isalnumat($this->dataStr, $q)) {
  1430.                         $q++;
  1431.                     }
  1432.                     $dif = $this->estimateBitsMode8($p)  // + 4 + l8
  1433.                     + $this->estimateBitsModeAn($q - $p) + 4 + $la
  1434.                     - $this->estimateBitsMode8($q); // - 4 - l8
  1435.                     if ($dif < 0) {
  1436.                         break;
  1437.                     } else {
  1438.                         $p = $q;
  1439.                     }
  1440.                 } else {
  1441.                     $p++;
  1442.                 }
  1443.             }
  1444.             $run = $p;
  1445.             $this->items = $this->appendNewInputItem($this->items, QR_MODE_8B, $run, str_split($this->dataStr));
  1446.             return $run;
  1447.         }
  1448.  
  1449.         /**
  1450.          * splitString
  1451.          */
  1452.          protected function splitString() {
  1453.             while (strlen($this->dataStr) > 0) {
  1454.                 if ($this->dataStr == '') {
  1455.                     return 0;
  1456.                 }
  1457.                 $mode = $this->identifyMode(0);
  1458.                 switch ($mode) {
  1459.                     case QR_MODE_NM: {
  1460.                         $length = $this->eatNum();
  1461.                         break;
  1462.                     }
  1463.                     case QR_MODE_AN: {
  1464.                         $length = $this->eatAn();
  1465.                         break;
  1466.                     }
  1467.                     case QR_MODE_KJ: {
  1468.                         if ($hint == QR_MODE_KJ) {
  1469.                             $length = $this->eatKanji();
  1470.                         } else {
  1471.                             $length = $this->eat8();
  1472.                         }
  1473.                         break;
  1474.                     }
  1475.                     default: {
  1476.                         $length = $this->eat8();
  1477.                         break;
  1478.                     }
  1479.                 }
  1480.                 if ($length == 0) {
  1481.                     return 0;
  1482.                 }
  1483.                 if ($length < 0) {
  1484.                     return -1;
  1485.                 }
  1486.                 $this->dataStr = substr($this->dataStr, $length);
  1487.             }
  1488.         }
  1489.  
  1490.         /**
  1491.          * toUpper
  1492.          */
  1493.          protected function toUpper() {
  1494.             $stringLen = strlen($this->dataStr);
  1495.             $p = 0;
  1496.             while ($p < $stringLen) {
  1497.                 $mode = $this->identifyMode(substr($this->dataStr, $p), $this->hint);
  1498.                 if ($mode == QR_MODE_KJ) {
  1499.                     $p += 2;
  1500.                 } else {
  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);
  1503.                     }
  1504.                     $p++;
  1505.                 }
  1506.             }
  1507.             return $this->dataStr;
  1508.         }
  1509.  
  1510.         // - - - - - - - - - - - - - - - - - - - - - - - - -
  1511.  
  1512.         // QRinputItem
  1513.  
  1514.         /**
  1515.          * newInputItem
  1516.          * @param int $mode 
  1517.          * @param int $size 
  1518.          * @param array $data 
  1519.          * @param array $bstream 
  1520.          * @return array input item
  1521.          */
  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));
  1526.             }
  1527.             if (!$this->check($mode, $size, $setData)) {
  1528.                 return NULL;
  1529.             }
  1530.             $inputitem = array();
  1531.             $inputitem['mode'] = $mode;
  1532.             $inputitem['size'] = $size;
  1533.             $inputitem['data'] = $setData;
  1534.             $inputitem['bstream'] = $bstream;
  1535.             return $inputitem;
  1536.         }
  1537.  
  1538.         /**
  1539.          * encodeModeNum
  1540.          * @param array $inputitem 
  1541.          * @param int $version 
  1542.          * @return array input item
  1543.          */
  1544.          protected function encodeModeNum($inputitem, $version) {
  1545.             $words = (int)($inputitem['size'] / 3);
  1546.             $inputitem['bstream'] = array();
  1547.             $val = 0x1;
  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);
  1555.             }
  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);
  1563.             }
  1564.             return $inputitem;
  1565.         }
  1566.  
  1567.         /**
  1568.          * encodeModeAn
  1569.          * @param array $inputitem 
  1570.          * @param int $version 
  1571.          * @return array input item
  1572.          */
  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);
  1582.             }
  1583.             if ($inputitem['size'] & 1) {
  1584.                 $val = $this->lookAnTable(ord($inputitem['data'][($words * 2)]));
  1585.                 $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 6, $val);
  1586.             }
  1587.             return $inputitem;
  1588.         }
  1589.  
  1590.         /**
  1591.          * encodeMode8
  1592.          * @param array $inputitem 
  1593.          * @param int $version 
  1594.          * @return array input item
  1595.          */
  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]));
  1602.             }
  1603.             return $inputitem;
  1604.         }
  1605.  
  1606.         /**
  1607.          * encodeModeKanji
  1608.          * @param array $inputitem 
  1609.          * @param int $version 
  1610.          * @return array input item
  1611.          */
  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) {
  1619.                     $val -= 0x8140;
  1620.                 } else {
  1621.                     $val -= 0xc140;
  1622.                 }
  1623.                 $h = ($val >> 8) * 0xc0;
  1624.                 $val = ($val & 0xff) + $h;
  1625.                 $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 13, $val);
  1626.             }
  1627.             return $inputitem;
  1628.         }
  1629.  
  1630.         /**
  1631.          * encodeModeStructure
  1632.          * @param array $inputitem 
  1633.          * @return array input item
  1634.          */
  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]));
  1641.             return $inputitem;
  1642.         }
  1643.  
  1644.         /**
  1645.          * encodeBitStream
  1646.          * @param array $inputitem 
  1647.          * @param int $version 
  1648.          * @return array input item
  1649.          */
  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']);
  1661.             } else {
  1662.                 switch($inputitem['mode']) {
  1663.                     case QR_MODE_NM: {
  1664.                         $inputitem = $this->encodeModeNum($inputitem, $version);
  1665.                         break;
  1666.                     }
  1667.                     case QR_MODE_AN: {
  1668.                         $inputitem = $this->encodeModeAn($inputitem, $version);
  1669.                         break;
  1670.                     }
  1671.                     case QR_MODE_8B: {
  1672.                         $inputitem = $this->encodeMode8($inputitem, $version);
  1673.                         break;
  1674.                     }
  1675.                     case QR_MODE_KJ: {
  1676.                         $inputitem = $this->encodeModeKanji($inputitem, $version);
  1677.                         break;
  1678.                     }
  1679.                     case QR_MODE_ST: {
  1680.                         $inputitem = $this->encodeModeStructure($inputitem);
  1681.                         break;
  1682.                     }
  1683.                     default: {
  1684.                         break;
  1685.                     }
  1686.                 }
  1687.             }
  1688.             return $inputitem;
  1689.         }
  1690.  
  1691.         // - - - - - - - - - - - - - - - - - - - - - - - - -
  1692.  
  1693.         // QRinput
  1694.  
  1695.         /**
  1696.          * Append data to an input object.
  1697.          * The data is copied and appended to the input object.
  1698.          * @param array items input items
  1699.          * @param int $mode encoding mode.
  1700.          * @param int $size size of data (byte).
  1701.          * @param array $data array of input data.
  1702.          * @return items 
  1703.          *
  1704.          */
  1705.         protected function appendNewInputItem($items, $mode, $size, $data) {
  1706.             $items[] = $this->newInputItem($mode, $size, $data);
  1707.             return $items;
  1708.         }
  1709.  
  1710.         /**
  1711.          * insertStructuredAppendHeader
  1712.          * @param array $items 
  1713.          * @param int $size 
  1714.          * @param int $index 
  1715.          * @param int $parity 
  1716.          * @return array items
  1717.          */
  1718.          protected function insertStructuredAppendHeader($items, $size, $index, $parity) {
  1719.             if ($size > MAX_STRUCTURED_SYMBOLS) {
  1720.                 return -1;
  1721.             }
  1722.             if (($index <= 0) OR ($index > MAX_STRUCTURED_SYMBOLS)) {
  1723.                 return -1;
  1724.             }
  1725.             $buf = array($size, $index, $parity);
  1726.             $entry = $this->newInputItem(QR_MODE_ST, 3, buf);
  1727.             array_unshift($items, $entry);
  1728.             return $items;
  1729.         }
  1730.  
  1731.         /**
  1732.          * calcParity
  1733.          * @param array $items 
  1734.          * @return int parity
  1735.          */
  1736.          protected function calcParity($items) {
  1737.             $parity = 0;
  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];
  1742.                     }
  1743.                 }
  1744.             }
  1745.             return $parity;
  1746.         }
  1747.  
  1748.         /**
  1749.          * checkModeNum
  1750.          * @param int $size 
  1751.          * @param array $data 
  1752.          * @return boolean true or false
  1753.          */
  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'))){
  1757.                     return false;
  1758.                 }
  1759.             }
  1760.             return true;
  1761.         }
  1762.  
  1763.         /**
  1764.          * estimateBitsModeNum
  1765.          * @param int $size 
  1766.          * @return int number of bits
  1767.          */
  1768.          protected function estimateBitsModeNum($size) {
  1769.             $w = (int)$size / 3;
  1770.             $bits = $w * 10;
  1771.             switch($size - $w * 3) {
  1772.                 case 1: {
  1773.                     $bits += 4;
  1774.                     break;
  1775.                 }
  1776.                 case 2: {
  1777.                     $bits += 7;
  1778.                     break;
  1779.                 }
  1780.                 default: {
  1781.                     break;
  1782.                 }
  1783.             }
  1784.             return $bits;
  1785.         }
  1786.  
  1787.         /**
  1788.          * Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19).
  1789.          * @param int $c character value
  1790.          * @return value 
  1791.          */
  1792.         protected function lookAnTable($c) {
  1793.             return (($c > 127)?-1:$this->anTable[$c]);
  1794.         }
  1795.  
  1796.         /**
  1797.          * checkModeAn
  1798.          * @param int $size 
  1799.          * @param array $data 
  1800.          * @return boolean true or false
  1801.          */
  1802.          protected function checkModeAn($size, $data) {
  1803.             for ($i=0; $i<$size; ++$i) {
  1804.                 if ($this->lookAnTable(ord($data[$i])) == -1) {
  1805.                     return false;
  1806.                 }
  1807.             }
  1808.             return true;
  1809.         }
  1810.  
  1811.         /**
  1812.          * estimateBitsModeAn
  1813.          * @param int $size 
  1814.          * @return int number of bits
  1815.          */
  1816.          protected function estimateBitsModeAn($size) {
  1817.             $w = (int)($size / 2);
  1818.             $bits = $w * 11;
  1819.             if ($size & 1) {
  1820.                 $bits += 6;
  1821.             }
  1822.             return $bits;
  1823.         }
  1824.  
  1825.         /**
  1826.          * estimateBitsMode8
  1827.          * @param int $size 
  1828.          * @return int number of bits
  1829.          */
  1830.          protected function estimateBitsMode8($size) {
  1831.             return $size * 8;
  1832.         }
  1833.  
  1834.         /**
  1835.          * estimateBitsModeKanji
  1836.          * @param int $size 
  1837.          * @return int number of bits
  1838.          */
  1839.          protected function estimateBitsModeKanji($size) {
  1840.             return (int)(($size / 2) * 13);
  1841.         }
  1842.  
  1843.         /**
  1844.          * checkModeKanji
  1845.          * @param int $size 
  1846.          * @param array $data 
  1847.          * @return boolean true or false
  1848.          */
  1849.          protected function checkModeKanji($size, $data) {
  1850.             if ($size & 1) {
  1851.                 return false;
  1852.             }
  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)) {
  1856.                     return false;
  1857.                 }
  1858.             }
  1859.             return true;
  1860.         }
  1861.  
  1862.         /**
  1863.          * Validate the input data.
  1864.          * @param int $mode encoding mode.
  1865.          * @param int $size size of data (byte).
  1866.          * @param array data data to validate
  1867.          * @return boolean true in case of valid data, false otherwise
  1868.          */
  1869.         protected function check($mode, $size, $data) {
  1870.             if ($size <= 0) {
  1871.                 return false;
  1872.             }
  1873.             switch($mode) {
  1874.                 case QR_MODE_NM: {
  1875.                     return $this->checkModeNum($size, $data);
  1876.                 }
  1877.                 case QR_MODE_AN: {
  1878.                     return $this->checkModeAn($size, $data);
  1879.                 }
  1880.                 case QR_MODE_KJ: {
  1881.                     return $this->checkModeKanji($size, $data);
  1882.                 }
  1883.                 case QR_MODE_8B: {
  1884.                     return true;
  1885.                 }
  1886.                 case QR_MODE_ST: {
  1887.                     return true;
  1888.                 }
  1889.                 default: {
  1890.                     break;
  1891.                 }
  1892.             }
  1893.             return false;
  1894.         }
  1895.  
  1896.         /**
  1897.          * estimateBitStreamSize
  1898.          * @param array $items 
  1899.          * @param int $version 
  1900.          * @return int bits
  1901.          */
  1902.          protected function estimateBitStreamSize($items, $version) {
  1903.             $bits = 0;
  1904.             if ($version == 0) {
  1905.                 $version = 1;
  1906.             }
  1907.             foreach ($items as $item) {
  1908.                 switch($item['mode']) {
  1909.                     case QR_MODE_NM: {
  1910.                         $bits = $this->estimateBitsModeNum($item['size']);
  1911.                         break;
  1912.                     }
  1913.                     case QR_MODE_AN: {
  1914.                         $bits = $this->estimateBitsModeAn($item['size']);
  1915.                         break;
  1916.                     }
  1917.                     case QR_MODE_8B: {
  1918.                         $bits = $this->estimateBitsMode8($item['size']);
  1919.                         break;
  1920.                     }
  1921.                     case QR_MODE_KJ: {
  1922.                         $bits = $this->estimateBitsModeKanji($item['size']);
  1923.                         break;
  1924.                     }
  1925.                     case QR_MODE_ST: {
  1926.                         return STRUCTURE_HEADER_BITS;
  1927.                     }
  1928.                     default: {
  1929.                         return 0;
  1930.                     }
  1931.                 }
  1932.                 $l = $this->lengthIndicator($item['mode'], $version);
  1933.                 $m = 1 << $l;
  1934.                 $num = (int)(($item['size'] + $m - 1) / $m);
  1935.                 $bits += $num * (4 + $l);
  1936.             }
  1937.             return $bits;
  1938.         }
  1939.  
  1940.         /**
  1941.          * estimateVersion
  1942.          * @param array $items 
  1943.          * @return int version
  1944.          */
  1945.          protected function estimateVersion($items) {
  1946.             $version = 0;
  1947.             $prev = 0;
  1948.             do {
  1949.                 $prev = $version;
  1950.                 $bits = $this->estimateBitStreamSize($items, $prev);
  1951.                 $version = $this->getMinimumVersion((int)(($bits + 7) / 8), $this->level);
  1952.                 if ($version < 0) {
  1953.                     return -1;
  1954.                 }
  1955.             } while ($version > $prev);
  1956.             return $version;
  1957.         }
  1958.  
  1959.         /**
  1960.          * lengthOfCode
  1961.          * @param int $mode 
  1962.          * @param int $version 
  1963.          * @param int $bits 
  1964.          * @return int size
  1965.          */
  1966.          protected function lengthOfCode($mode, $version, $bits) {
  1967.             $payload = $bits - 4 - $this->lengthIndicator($mode, $version);
  1968.             switch($mode) {
  1969.                 case QR_MODE_NM: {
  1970.                     $chunks = (int)($payload / 10);
  1971.                     $remain = $payload - $chunks * 10;
  1972.                     $size = $chunks * 3;
  1973.                     if ($remain >= 7) {
  1974.                         $size += 2;
  1975.                     } elseif ($remain >= 4) {
  1976.                         $size += 1;
  1977.                     }
  1978.                     break;
  1979.                 }
  1980.                 case QR_MODE_AN: {
  1981.                     $chunks = (int)($payload / 11);
  1982.                     $remain = $payload - $chunks * 11;
  1983.                     $size = $chunks * 2;
  1984.                     if ($remain >= 6) {
  1985.                         ++$size;
  1986.                     }
  1987.                     break;
  1988.                 }
  1989.                 case QR_MODE_8B: {
  1990.                     $size = (int)($payload / 8);
  1991.                     break;
  1992.                 }
  1993.                 case QR_MODE_KJ: {
  1994.                     $size = (int)(($payload / 13) * 2);
  1995.                     break;
  1996.                 }
  1997.                 case QR_MODE_ST: {
  1998.                     $size = (int)($payload / 8);
  1999.                     break;
  2000.                 }
  2001.                 default: {
  2002.                     $size = 0;
  2003.                     break;
  2004.                 }
  2005.             }
  2006.             $maxsize = $this->maximumWords($mode, $version);
  2007.             if ($size < 0) {
  2008.                 $size = 0;
  2009.             }
  2010.             if ($size > $maxsize) {
  2011.                 $size = $maxsize;
  2012.             }
  2013.             return $size;
  2014.         }
  2015.  
  2016.         /**
  2017.          * createBitStream
  2018.          * @param array $items 
  2019.          * @return array of items and total bits
  2020.          */
  2021.          protected function createBitStream($items) {
  2022.             $total = 0;
  2023.             foreach ($items as $key => $item) {
  2024.                 $items[$key] = $this->encodeBitStream($item, $this->version);
  2025.                 $bits = count($items[$key]['bstream']);
  2026.                 $total += $bits;
  2027.             }
  2028.             return array($items, $total);
  2029.         }
  2030.  
  2031.         /**
  2032.          * convertData
  2033.          * @param array $items 
  2034.          * @return array items
  2035.          */
  2036.          protected function convertData($items) {
  2037.             $ver = $this->estimateVersion($items);
  2038.             if ($ver > $this->version) {
  2039.                 $this->version = $ver;
  2040.             }
  2041.             for (;;) {
  2042.                 $cbs = $this->createBitStream($items);
  2043.                 $items = $cbs[0];
  2044.                 $bits = $cbs[1];
  2045.                 if ($bits < 0) {
  2046.                     return -1;
  2047.                 }
  2048.                 $ver = $this->getMinimumVersion((int)(($bits + 7) / 8), $this->level);
  2049.                 if ($ver < 0) {
  2050.                     return -1;
  2051.                 } elseif ($ver > $this->version) {
  2052.                     $this->version = $ver;
  2053.                 } else {
  2054.                     break;
  2055.                 }
  2056.             }
  2057.             return $items;
  2058.         }
  2059.  
  2060.         /**
  2061.          * Append Padding Bit to bitstream
  2062.          * @param array $bstream 
  2063.          * @return array bitstream
  2064.          */
  2065.          protected function appendPaddingBit($bstream) {
  2066.              if (is_null($bstream)) {
  2067.                  return null;
  2068.              }
  2069.             $bits = count($bstream);
  2070.             $maxwords = $this->getDataLength($this->version, $this->level);
  2071.             $maxbits = $maxwords * 8;
  2072.             if ($maxbits == $bits) {
  2073.                 return 0;
  2074.             }
  2075.             if ($maxbits - $bits < 5) {
  2076.                 return $this->appendNum($bstream, $maxbits - $bits, 0);
  2077.             }
  2078.             $bits += 4;
  2079.             $words = (int)(($bits + 7) / 8);
  2080.             $padding = array();
  2081.             $padding = $this->appendNum($padding, $words * 8 - $bits + 4, 0);
  2082.             $padlen = $maxwords - $words;
  2083.             if ($padlen > 0) {
  2084.                 $padbuf = array();
  2085.                 for ($i=0; $i<$padlen; ++$i) {
  2086.                     $padbuf[$i] = ($i&1)?0x11:0xec;
  2087.                 }
  2088.                 $padding = $this->appendBytes($padding, $padlen, $padbuf);
  2089.             }
  2090.             return $this->appendBitstream($bstream, $padding);
  2091.         }
  2092.  
  2093.         /**
  2094.          * mergeBitStream
  2095.          * @param array $bstream 
  2096.          * @return array bitstream
  2097.          */
  2098.          protected function mergeBitStream($items) {
  2099.             $items = $this->convertData($items);
  2100.             if (!is_array($items)) {
  2101.                 return null;
  2102.             }
  2103.             $bstream = array();
  2104.             foreach ($items as $item) {
  2105.                 $bstream = $this->appendBitstream($bstream, $item['bstream']);
  2106.             }
  2107.             return $bstream;
  2108.         }
  2109.  
  2110.         /**
  2111.          * Returns a stream of bits.
  2112.          * @param int $items 
  2113.          * @return array padded merged byte stream
  2114.          */
  2115.         protected function getBitStream($items) {
  2116.             $bstream = $this->mergeBitStream($items);
  2117.             return $this->appendPaddingBit($bstream);
  2118.         }
  2119.  
  2120.         /**
  2121.          * Pack all bit streams padding bits into a byte array.
  2122.          * @param int $items 
  2123.          * @return array padded merged byte stream
  2124.          */
  2125.         protected function getByteStream($items) {
  2126.             $bstream = $this->getBitStream($items);
  2127.             return $this->bitstreamToByte($bstream);
  2128.         }
  2129.  
  2130.         // - - - - - - - - - - - - - - - - - - - - - - - - -
  2131.  
  2132.         // QRbitstream
  2133.  
  2134.         /**
  2135.          * Return an array with zeros
  2136.          * @param int $setLength array size
  2137.          * @return array 
  2138.          */
  2139.          protected function allocate($setLength) {
  2140.             return array_fill(0, $setLength, 0);
  2141.         }
  2142.  
  2143.         /**
  2144.          * Return new bitstream from number
  2145.          * @param int $bits number of bits
  2146.          * @param int $num number
  2147.          * @return array bitstream
  2148.          */
  2149.          protected function newFromNum($bits, $num) {
  2150.             $bstream = $this->allocate($bits);
  2151.             $mask = 1 << ($bits - 1);
  2152.             for ($i=0; $i<$bits; ++$i) {
  2153.                 if ($num & $mask) {
  2154.                     $bstream[$i] = 1;
  2155.                 } else {
  2156.                     $bstream[$i] = 0;
  2157.                 }
  2158.                 $mask = $mask >> 1;
  2159.             }
  2160.             return $bstream;
  2161.         }
  2162.  
  2163.         /**
  2164.          * Return new bitstream from bytes
  2165.          * @param int $size size
  2166.          * @param array $data bytes
  2167.          * @return array bitstream
  2168.          */
  2169.          protected function newFromBytes($size, $data) {
  2170.             $bstream = $this->allocate($size * 8);
  2171.             $p=0;
  2172.             for ($i=0; $i<$size; ++$i) {
  2173.                 $mask = 0x80;
  2174.                 for ($j=0; $j<8; ++$j) {
  2175.                     if ($data[$i] & $mask) {
  2176.                         $bstream[$p] = 1;
  2177.                     } else {
  2178.                         $bstream[$p] = 0;
  2179.                     }
  2180.                     $p++;
  2181.                     $mask = $mask >> 1;
  2182.                 }
  2183.             }
  2184.             return $bstream;
  2185.         }
  2186.  
  2187.         /**
  2188.          * Append one bitstream to another
  2189.          * @param array $bitstream original bitstream
  2190.          * @param array $append bitstream to append
  2191.          * @return array bitstream
  2192.          */
  2193.          protected function appendBitstream($bitstream, $append) {
  2194.             if ((!is_array($append)) OR (count($append) == 0)) {
  2195.                 return $bitstream;
  2196.             }
  2197.             if (count($bitstream) == 0) {
  2198.                 return $append;
  2199.             }
  2200.             return array_values(array_merge($bitstream, $append));
  2201.         }
  2202.  
  2203.         /**
  2204.          * Append one bitstream created from number to another
  2205.          * @param array $bitstream original bitstream
  2206.          * @param int $bits number of bits
  2207.          * @param int $num number
  2208.          * @return array bitstream
  2209.          */
  2210.          protected function appendNum($bitstream, $bits, $num) {
  2211.             if ($bits == 0) {
  2212.                 return 0;
  2213.             }
  2214.             $b = $this->newFromNum($bits, $num);
  2215.             return $this->appendBitstream($bitstream, $b);
  2216.         }
  2217.  
  2218.         /**
  2219.          * Append one bitstream created from bytes to another
  2220.          * @param array $bitstream original bitstream
  2221.          * @param int $size size
  2222.          * @param array $data bytes
  2223.          * @return array bitstream
  2224.          */
  2225.          protected function appendBytes($bitstream, $size, $data) {
  2226.             if ($size == 0) {
  2227.                 return 0;
  2228.             }
  2229.             $b = $this->newFromBytes($size, $data);
  2230.             return $this->appendBitstream($bitstream, $b);
  2231.         }
  2232.  
  2233.         /**
  2234.          * Convert bitstream to bytes
  2235.          * @param array $bitstream original bitstream
  2236.          * @return array of bytes
  2237.          */
  2238.          protected function bitstreamToByte($bstream) {
  2239.             if (is_null($bstream)) {
  2240.                  return null;
  2241.              }
  2242.             $size = count($bstream);
  2243.             if ($size == 0) {
  2244.                 return array();
  2245.             }
  2246.             $data = array_fill(0, (int)(($size + 7) / 8), 0);
  2247.             $bytes = (int)($size / 8);
  2248.             $p = 0;
  2249.             for ($i=0; $i<$bytes; $i++) {
  2250.                 $v = 0;
  2251.                 for ($j=0; $j<8; $j++) {
  2252.                     $v = $v << 1;
  2253.                     $v |= $bstream[$p];
  2254.                     $p++;
  2255.                 }
  2256.                 $data[$i] = $v;
  2257.             }
  2258.             if ($size & 7) {
  2259.                 $v = 0;
  2260.                 for ($j=0; $j<($size & 7); $j++) {
  2261.                     $v = $v << 1;
  2262.                     $v |= $bstream[$p];
  2263.                     $p++;
  2264.                 }
  2265.                 $data[$bytes] = $v;
  2266.             }
  2267.             return $data;
  2268.         }
  2269.  
  2270.         // - - - - - - - - - - - - - - - - - - - - - - - - -
  2271.  
  2272.         // QRspec
  2273.  
  2274.         /**
  2275.          * Replace a value on the array at the specified position
  2276.          * @param array $srctab 
  2277.          * @param int $x X position
  2278.          * @param int $y Y position
  2279.          * @param string $repl value to replace
  2280.          * @param int $replLen length of the repl string
  2281.          * @return array srctab
  2282.          */
  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));
  2285.             return $srctab;
  2286.         }
  2287.  
  2288.         /**
  2289.          * Return maximum data code length (bytes) for the version.
  2290.          * @param int $version version
  2291.          * @param int $level error correction level
  2292.          * @return int maximum size (bytes)
  2293.          */
  2294.         protected function getDataLength($version, $level) {
  2295.             return $this->capacity[$version][QRCAP_WORDS] - $this->capacity[$version][QRCAP_EC][$level];
  2296.         }
  2297.  
  2298.         /**
  2299.          * Return maximum error correction code length (bytes) for the version.
  2300.          * @param int $version version
  2301.          * @param int $level error correction level
  2302.          * @return int ECC size (bytes)
  2303.          */
  2304.         protected function getECCLength($version, $level){
  2305.             return $this->capacity[$version][QRCAP_EC][$level];
  2306.         }
  2307.  
  2308.         /**
  2309.          * Return the width of the symbol for the version.
  2310.          * @param int $version version
  2311.          * @return int width
  2312.          */
  2313.         protected function getWidth($version) {
  2314.             return $this->capacity[$version][QRCAP_WIDTH];
  2315.         }
  2316.  
  2317.         /**
  2318.          * Return the numer of remainder bits.
  2319.          * @param int $version version
  2320.          * @return int number of remainder bits
  2321.          */
  2322.         protected function getRemainder($version) {
  2323.             return $this->capacity[$version][QRCAP_REMINDER];
  2324.         }
  2325.  
  2326.         /**
  2327.          * Return a version number that satisfies the input code length.
  2328.          * @param int $size input code length (byte)
  2329.          * @param int $level error correction level
  2330.          * @return int version number
  2331.          */
  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) {
  2336.                     return $i;
  2337.                 }
  2338.             }
  2339.             return -1;
  2340.         }
  2341.  
  2342.         /**
  2343.          * Return the size of length indicator for the mode and version.
  2344.          * @param int $mode encoding mode
  2345.          * @param int $version version
  2346.          * @return int the size of the appropriate length indicator (bits).
  2347.          */
  2348.         protected function lengthIndicator($mode, $version) {
  2349.             if ($mode == QR_MODE_ST) {
  2350.                 return 0;
  2351.             }
  2352.             if ($version <= 9) {
  2353.                 $l = 0;
  2354.             } elseif ($version <= 26) {
  2355.                 $l = 1;
  2356.             } else {
  2357.                 $l = 2;
  2358.             }
  2359.             return $this->lengthTableBits[$mode][$l];
  2360.         }
  2361.  
  2362.         /**
  2363.          * Return the maximum length for the mode and version.
  2364.          * @param int $mode encoding mode
  2365.          * @param int $version version
  2366.          * @return int the maximum length (bytes)
  2367.          */
  2368.         protected function maximumWords($mode, $version) {
  2369.             if ($mode == QR_MODE_ST) {
  2370.                 return 3;
  2371.             }
  2372.             if ($version <= 9) {
  2373.                 $l = 0;
  2374.             } else if ($version <= 26) {
  2375.                 $l = 1;
  2376.             } else {
  2377.                 $l = 2;
  2378.             }
  2379.             $bits = $this->lengthTableBits[$mode][$l];
  2380.             $words = (1 << $bits) - 1;
  2381.             if ($mode == QR_MODE_KJ) {
  2382.                 $words *= 2; // the number of bytes is required
  2383.             }
  2384.             return $words;
  2385.         }
  2386.  
  2387.         /**
  2388.          * Return an array of ECC specification.
  2389.          * @param int $version version
  2390.          * @param int $level error correction level
  2391.          * @param array $spec an array of ECC specification contains as following: {# of type1 blocks, # of data code, # of ecc code, # of type2 blocks, # of data code}
  2392.          * @return array spec
  2393.          */
  2394.         protected function getEccSpec($version, $level, $spec) {
  2395.             if (count($spec) < 5) {
  2396.                 $spec = array(0, 0, 0, 0, 0);
  2397.             }
  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);
  2402.             if ($b2 == 0) {
  2403.                 $spec[0] = $b1;
  2404.                 $spec[1] = (int)($data / $b1);
  2405.                 $spec[2] = (int)($ecc / $b1);
  2406.                 $spec[3] = 0;
  2407.                 $spec[4] = 0;
  2408.             } else {
  2409.                 $spec[0] = $b1;
  2410.                 $spec[1] = (int)($data / ($b1 + $b2));
  2411.                 $spec[2] = (int)($ecc  / ($b1 + $b2));
  2412.                 $spec[3] = $b2;
  2413.                 $spec[4] = $spec[1] + 1;
  2414.             }
  2415.             return $spec;
  2416.         }
  2417.  
  2418.         /**
  2419.          * Put an alignment marker.
  2420.          * @param array $frame frame
  2421.          * @param int $width width
  2422.          * @param int $ox X center coordinate of the pattern
  2423.          * @param int $oy Y center coordinate of the pattern
  2424.          * @return array frame
  2425.          */
  2426.         protected function putAlignmentMarker($frame, $ox, $oy) {
  2427.             $finder = array(
  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"
  2433.                 );
  2434.             $yStart = $oy - 2;
  2435.             $xStart = $ox - 2;
  2436.             for ($y=0; $y < 5; $y++) {
  2437.                 $frame = $this->qrstrset($frame, $xStart, $yStart+$y, $finder[$y]);
  2438.             }
  2439.             return $frame;
  2440.         }
  2441.  
  2442.         /**
  2443.          * Put an alignment pattern.
  2444.          * @param int $version version
  2445.          * @param array $fram frame
  2446.          * @param int $width width
  2447.          * @return array frame
  2448.          */
  2449.          protected function putAlignmentPattern($version, $frame, $width) {
  2450.             if ($version < 2) {
  2451.                 return $frame;
  2452.             }
  2453.             $d = $this->alignmentPattern[$version][1] - $this->alignmentPattern[$version][0];
  2454.             if ($d < 0) {
  2455.                 $w = 2;
  2456.             } else {
  2457.                 $w = (int)(($width - $this->alignmentPattern[$version][0]) / $d + 2);
  2458.             }
  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);
  2463.                 return $frame;
  2464.             }
  2465.             $cx = $this->alignmentPattern[$version][0];
  2466.             $wo = $w - 1;
  2467.             for ($x=1; $x < $wo; ++$x) {
  2468.                 $frame = $this->putAlignmentMarker($frame, 6, $cx);
  2469.                 $frame = $this->putAlignmentMarker($frame, $cx,  6);
  2470.                 $cx += $d;
  2471.             }
  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);
  2477.                     $cx += $d;
  2478.                 }
  2479.                 $cy += $d;
  2480.             }
  2481.             return $frame;
  2482.         }
  2483.  
  2484.         /**
  2485.          * Return BCH encoded version information pattern that is used for the symbol of version 7 or greater. Use lower 18 bits.
  2486.          * @param int $version version
  2487.          * @return BCH encoded version information pattern
  2488.          */
  2489.         protected function getVersionPattern($version) {
  2490.             if (($version < 7) OR ($version > QRSPEC_VERSION_MAX)) {
  2491.                 return 0;
  2492.             }
  2493.             return $this->versionPattern[($version - 7)];
  2494.         }
  2495.  
  2496.         /**
  2497.          * Return BCH encoded format information pattern.
  2498.          * @param array $mask 
  2499.          * @param int $level error correction level
  2500.          * @return BCH encoded format information pattern
  2501.          */
  2502.         protected function getFormatInfo($mask, $level) {
  2503.             if (($mask < 0) OR ($mask > 7)) {
  2504.                 return 0;
  2505.             }
  2506.             if (($level < 0) OR ($level > 3)) {
  2507.                 return 0;
  2508.             }
  2509.             return $this->formatInfo[$level][$mask];
  2510.         }
  2511.  
  2512.         /**
  2513.          * Put a finder pattern.
  2514.          * @param array $frame frame
  2515.          * @param int $width width
  2516.          * @param int $ox X center coordinate of the pattern
  2517.          * @param int $oy Y center coordinate of the pattern
  2518.          * @return array frame
  2519.          */
  2520.         protected function putFinderPattern($frame, $ox, $oy) {
  2521.             $finder = array(
  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"
  2529.             );
  2530.             for ($y=0; $y < 7; $y++) {
  2531.                 $frame = $this->qrstrset($frame, $ox, ($oy + $y), $finder[$y]);
  2532.             }
  2533.             return $frame;
  2534.         }
  2535.  
  2536.         /**
  2537.          * Return a copy of initialized frame.
  2538.          * @param int $version version
  2539.          * @return Array of unsigned char.
  2540.          */
  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);
  2545.             // Finder pattern
  2546.             $frame = $this->putFinderPattern($frame, 0, 0);
  2547.             $frame = $this->putFinderPattern($frame, $width - 7, 0);
  2548.             $frame = $this->putFinderPattern($frame, 0, $width - 7);
  2549.             // Separator
  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";
  2555.                 ++$yOffset;
  2556.             }
  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);
  2561.             // Format info
  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";
  2569.             }
  2570.             // Timing pattern
  2571.             $wo = $width - 15;
  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));
  2575.             }
  2576.             // Alignment pattern
  2577.             $frame = $this->putAlignmentPattern($version, $frame, $width);
  2578.             // Version information
  2579.             if ($version >= 7) {
  2580.                 $vinf = $this->getVersionPattern($version);
  2581.                 $v = $vinf;
  2582.                 for ($x=0; $x<6; ++$x) {
  2583.                     for ($y=0; $y<3; ++$y) {
  2584.                         $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1));
  2585.                         $v = $v >> 1;
  2586.                     }
  2587.                 }
  2588.                 $v = $vinf;
  2589.                 for ($y=0; $y<6; ++$y) {
  2590.                     for ($x=0; $x<3; ++$x) {
  2591.                         $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1));
  2592.                         $v = $v >> 1;
  2593.                     }
  2594.                 }
  2595.             }
  2596.             // and a little bit...
  2597.             $frame[$width - 8][8] = "\x81";
  2598.             return $frame;
  2599.         }
  2600.  
  2601.         /**
  2602.          * Set new frame for the specified version.
  2603.          * @param int $version version
  2604.          * @return Array of unsigned char.
  2605.          */
  2606.         protected function newFrame($version) {
  2607.             if (($version < 1) OR ($version > QRSPEC_VERSION_MAX)) {
  2608.                 return NULL;
  2609.             }
  2610.             if (!isset($this->frames[$version])) {
  2611.                 $this->frames[$version] = $this->createFrame($version);
  2612.             }
  2613.             if (is_null($this->frames[$version])) {
  2614.                 return NULL;
  2615.             }
  2616.             return $this->frames[$version];
  2617.         }
  2618.  
  2619.         /**
  2620.          * Return block number 0
  2621.          * @param array $spec 
  2622.          * @return int value
  2623.          */
  2624.          protected function rsBlockNum($spec) {
  2625.             return ($spec[0] + $spec[3]);
  2626.         }
  2627.  
  2628.         /**
  2629.         * Return block number 1
  2630.          * @param array $spec 
  2631.          * @return int value
  2632.          */
  2633.          protected function rsBlockNum1($spec) {
  2634.             return $spec[0];
  2635.         }
  2636.  
  2637.         /**
  2638.          * Return data codes 1
  2639.          * @param array $spec 
  2640.          * @return int value
  2641.          */
  2642.          protected function rsDataCodes1($spec) {
  2643.             return $spec[1];
  2644.         }
  2645.  
  2646.         /**
  2647.          * Return ecc codes 1
  2648.          * @param array $spec 
  2649.          * @return int value
  2650.          */
  2651.          protected function rsEccCodes1($spec) {
  2652.             return $spec[2];
  2653.         }
  2654.  
  2655.         /**
  2656.          * Return block number 2
  2657.          * @param array $spec 
  2658.          * @return int value
  2659.          */
  2660.          protected function rsBlockNum2($spec) {
  2661.             return $spec[3];
  2662.         }
  2663.  
  2664.         /**
  2665.          * Return data codes 2
  2666.          * @param array $spec 
  2667.          * @return int value
  2668.          */
  2669.          protected function rsDataCodes2($spec) {
  2670.             return $spec[4];
  2671.         }
  2672.  
  2673.         /**
  2674.          * Return ecc codes 2
  2675.          * @param array $spec 
  2676.          * @return int value
  2677.          */
  2678.          protected function rsEccCodes2($spec) {
  2679.             return $spec[2];
  2680.         }
  2681.  
  2682.         /**
  2683.          * Return data length
  2684.          * @param array $spec 
  2685.          * @return int value
  2686.          */
  2687.          protected function rsDataLength($spec) {
  2688.             return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]);
  2689.         }
  2690.  
  2691.         /**
  2692.          * Return ecc length
  2693.          * @param array $spec 
  2694.          * @return int value
  2695.          */
  2696.          protected function rsEccLength($spec) {
  2697.             return ($spec[0] + $spec[3]) * $spec[2];
  2698.         }
  2699.  
  2700.         // - - - - - - - - - - - - - - - - - - - - - - - - -
  2701.  
  2702.         // QRrs
  2703.  
  2704.         /**
  2705.          * Initialize a Reed-Solomon codec and add it to existing rsitems
  2706.          * @param int $symsize symbol size, bits
  2707.          * @param int $gfpoly  Field generator polynomial coefficients
  2708.          * @param int $fcr  first root of RS code generator polynomial, index form
  2709.          * @param int $prim  primitive element to generate polynomial roots
  2710.          * @param int $nroots RS code generator polynomial degree (number of roots)
  2711.          * @param int $pad  padding bytes at front of shortened block
  2712.          * @return array Array of RS values:<ul><li>mm = Bits per symbol;</li><li>nn = Symbols per block;</li><li>alpha_to = log lookup table array;</li><li>index_of = Antilog lookup table array;</li><li>genpoly = Generator polynomial array;</li><li>nroots = Number of generator;</li><li>roots = number of parity symbols;</li><li>fcr = First consecutive root, index form;</li><li>prim = Primitive element, index form;</li><li>iprim = prim-th root of 1, index form;</li><li>pad = Padding bytes in shortened block;</li><li>gfpoly</ul>.
  2713.          */
  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)) {
  2718.                     continue;
  2719.                 }
  2720.                 return $rs;
  2721.             }
  2722.             $rs = $this->init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
  2723.             array_unshift($this->rsitems, $rs);
  2724.             return $rs;
  2725.         }
  2726.  
  2727.         // - - - - - - - - - - - - - - - - - - - - - - - - -
  2728.  
  2729.         // QRrsItem
  2730.  
  2731.         /**
  2732.          * modnn
  2733.          * @param array RS values
  2734.          * @param int $x X position
  2735.          * @return int X osition
  2736.          */
  2737.          protected function modnn($rs, $x) {
  2738.             while ($x >= $rs['nn']) {
  2739.                 $x -= $rs['nn'];
  2740.                 $x = ($x >> $rs['mm']) + ($x & $rs['nn']);
  2741.             }
  2742.             return $x;
  2743.         }
  2744.  
  2745.         /**
  2746.          * Initialize a Reed-Solomon codec and returns an array of values.
  2747.          * @param int $symsize symbol size, bits
  2748.          * @param int $gfpoly  Field generator polynomial coefficients
  2749.          * @param int $fcr  first root of RS code generator polynomial, index form
  2750.          * @param int $prim  primitive element to generate polynomial roots
  2751.          * @param int $nroots RS code generator polynomial degree (number of roots)
  2752.          * @param int $pad  padding bytes at front of shortened block
  2753.          * @return array Array of RS values:<ul><li>mm = Bits per symbol;</li><li>nn = Symbols per block;</li><li>alpha_to = log lookup table array;</li><li>index_of = Antilog lookup table array;</li><li>genpoly = Generator polynomial array;</li><li>nroots = Number of generator;</li><li>roots = number of parity symbols;</li><li>fcr = First consecutive root, index form;</li><li>prim = Primitive element, index form;</li><li>iprim = prim-th root of 1, index form;</li><li>pad = Padding bytes in shortened block;</li><li>gfpoly</ul>.
  2754.          */
  2755.         protected function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) {
  2756.             // Based on Reed solomon encoder by Phil Karn, KA9Q (GNU-LGPLv2)
  2757.             $rs = null;
  2758.             // Check parameter ranges
  2759.             if (($symsize < 0) OR ($symsize > 8)) {
  2760.                 return $rs;
  2761.             }
  2762.             if (($fcr < 0) OR ($fcr >= (1<<$symsize))) {
  2763.                 return $rs;
  2764.             }
  2765.             if (($prim <= 0) OR ($prim >= (1<<$symsize))) {
  2766.                 return $rs;
  2767.             }
  2768.             if (($nroots < 0) OR ($nroots >= (1<<$symsize))) {
  2769.                 return $rs;
  2770.             }
  2771.             if (($pad < 0) OR ($pad >= ((1<<$symsize) -1 - $nroots))) {
  2772.                 return $rs;
  2773.             }
  2774.             $rs = array();
  2775.             $rs['mm'] = $symsize;
  2776.             $rs['nn'] = (1 << $symsize) - 1;
  2777.             $rs['pad'] = $pad;
  2778.             $rs['alpha_to'] = array_fill(0, ($rs['nn'] + 1), 0);
  2779.             $rs['index_of'] = array_fill(0, ($rs['nn'] + 1), 0);
  2780.             // PHP style macro replacement ;)
  2781.             $NN =& $rs['nn'];
  2782.             $A0 =& $NN;
  2783.             // Generate Galois field lookup tables
  2784.             $rs['index_of'][0] = $A0; // log(zero) = -inf
  2785.             $rs['alpha_to'][$A0] = 0; // alpha**-inf = 0
  2786.             $sr = 1;
  2787.             for ($i=0; $i<$rs['nn']; ++$i) {
  2788.                 $rs['index_of'][$sr] = $i;
  2789.                 $rs['alpha_to'][$i] = $sr;
  2790.                 $sr <<= 1;
  2791.                 if ($sr & (1 << $symsize)) {
  2792.                     $sr ^= $gfpoly;
  2793.                 }
  2794.                 $sr &= $rs['nn'];
  2795.             }
  2796.             if ($sr != 1) {
  2797.                 // field generator polynomial is not primitive!
  2798.                 return NULL;
  2799.             }
  2800.             // Form RS code generator polynomial from its roots
  2801.             $rs['genpoly'] = array_fill(0, ($nroots + 1), 0);
  2802.             $rs['fcr'] = $fcr;
  2803.             $rs['prim'] = $prim;
  2804.             $rs['nroots'] = $nroots;
  2805.             $rs['gfpoly'] = $gfpoly;
  2806.             // Find prim-th root of 1, used in decoding
  2807.             for ($iprim=1; ($iprim % $prim) != 0; $iprim += $rs['nn']) {
  2808.                 ; // intentional empty-body loop!
  2809.             }
  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;
  2814.                 // Multiply rs->genpoly[] by  @**(root + x)
  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)];
  2818.                     } else {
  2819.                         $rs['genpoly'][$j] = $rs['genpoly'][$j-1];
  2820.                     }
  2821.                 }
  2822.                 // rs->genpoly[0] can never be zero
  2823.                 $rs['genpoly'][0] = $rs['alpha_to'][$this->modnn($rs, $rs['index_of'][$rs['genpoly'][0]] + $root)];
  2824.             }
  2825.             // convert rs->genpoly[] to index form for quicker encoding
  2826.             for ($i = 0; $i <= $nroots; ++$i) {
  2827.                 $rs['genpoly'][$i] = $rs['index_of'][$rs['genpoly'][$i]];
  2828.             }
  2829.             return $rs;
  2830.         }
  2831.  
  2832.         /**
  2833.          * Encode a Reed-Solomon codec and returns the parity array
  2834.          * @param array $rs RS values
  2835.          * @param array $data data
  2836.          * @param array $parity parity
  2837.          * @return parity array
  2838.          */
  2839.          protected function encode_rs_char($rs, $data, $parity) {
  2840.             $MM       =& $rs['mm']; // bits per symbol
  2841.             $NN       =& $rs['nn']; // the total number of symbols in a RS block
  2842.             $ALPHA_TO =& $rs['alpha_to']; // the address of an array of NN elements to convert Galois field elements in index (log) form to polynomial form
  2843.             $INDEX_OF =& $rs['index_of']; // the address of an array of NN elements to convert Galois field elements in polynomial form to index (log) form
  2844.             $GENPOLY  =& $rs['genpoly']; // an array of NROOTS+1 elements containing the generator polynomial in index form
  2845.             $NROOTS   =& $rs['nroots']; // the number of roots in the RS code generator polynomial, which is the same as the number of parity symbols in a block
  2846.             $FCR      =& $rs['fcr']; // first consecutive root, index form
  2847.             $PRIM     =& $rs['prim']; // primitive element, index form
  2848.             $IPRIM    =& $rs['iprim']; // prim-th root of 1, index form
  2849.             $PAD      =& $rs['pad']; // the number of pad symbols in a block
  2850.             $A0       =& $NN;
  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) {
  2855.                     // feedback term is non-zero
  2856.                     // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
  2857.                     // always be for the polynomials constructed by init_rs()
  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)])];
  2861.                     }
  2862.                 }
  2863.                 // Shift
  2864.                 array_shift($parity);
  2865.                 if ($feedback != $A0) {
  2866.                     array_push($parity, $ALPHA_TO[$this->modnn($rs, $feedback + $GENPOLY[0])]);
  2867.                 } else {
  2868.                     array_push($parity, 0);
  2869.                 }
  2870.             }
  2871.             return $parity;
  2872.         }
  2873.  
  2874.     } // end QRcode class
  2875.  
  2876. } // END OF "class_exists QRcode"
  2877. //============================================================+
  2878. // END OF FILE
  2879. //============================================================+

Documentation generated on Sun, 27 Feb 2011 16:33:37 -0800 by phpDocumentor 1.4.3