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_lengthOR (!$split_length)) {
  267.                 do {
  268.                     $c strlen($string);
  269.                     $parts[substr($string0$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 position of bit
  360.          * @access protected
  361.          */
  362.         protected $x;
  363.  
  364.         /**
  365.          * @var 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-13738-1-1-1-13940-1414243//
  476.              0,  1,  2,  3,  4,  5,  6,  7,  8,  944-1-1-1-1-1//
  477.             -1101112131415161718192021222324//
  478.             2526272829303132333435-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,    00array(   0,    0,    0,    0))//
  490.             array21,   260array(   7,   10,   13,   17))//  1
  491.             array25,   447array(  10,   16,   22,   28))//
  492.             array29,   707array(  15,   26,   36,   44))//
  493.             array33,  1007array(  20,   36,   52,   64))//
  494.             array37,  1347array(  26,   48,   72,   88))//  5
  495.             array41,  1727array(  36,   64,   96,  112))//
  496.             array45,  1960array(  40,   72,  108,  130))//
  497.             array49,  2420array(  48,   88,  132,  156))//
  498.             array53,  2920array(  60,  110,  160,  192))//
  499.             array57,  3460array(  72,  130,  192,  224))// 10
  500.             array61,  4040array(  80,  150,  224,  264))//
  501.             array65,  4660array(  96,  176,  260,  308))//
  502.             array69,  5320array104,  198,  288,  352))//
  503.             array73,  5813array120,  216,  320,  384))//
  504.             array77,  6553array132,  240,  360,  432))// 15
  505.             array81,  7333array144,  280,  408,  480))//
  506.             array85,  8153array168,  308,  448,  532))//
  507.             array89,  9013array180,  338,  504,  588))//
  508.             array93,  9913array196,  364,  546,  650))//
  509.             array9710853array224,  416,  600,  700))// 20
  510.             array(10111564array224,  442,  644,  750))//
  511.             array(10512584array252,  476,  690,  816))//
  512.             array(10913644array270,  504,  750,  900))//
  513.             array(11314744array300,  560,  810,  960))//
  514.             array(11715884array312,  588,  8701050))// 25
  515.             array(12117064array336,  644,  9521110))//
  516.             array(12518284array360,  70010201200))//
  517.             array(12919213array390,  72810501260))//
  518.             array(13320513array420,  78411401350))//
  519.             array(13721853array450,  81212001440))// 30
  520.             array(14123233array480,  86812901530))//
  521.             array(14524653array510,  92413501620))//
  522.             array(14926113array540,  98014401710))//
  523.             array(15327613array570103615301800))//
  524.             array(15728760array570106415901890))// 35
  525.             array(16130340array600112016801980))//
  526.             array(16531960array630120417702100))//
  527.             array(16933620array660126018602220))//
  528.             array(17335320array720131619502310))//
  529.             array(17737060array750137220402430))  // 40
  530.         );
  531.  
  532.         /**
  533.          * @var array Length indicator
  534.          * @access protected
  535.          */
  536.         protected $lengthTableBits = array(
  537.             array(101214),
  538.             array91113),
  539.             array81616),
  540.             array81012)
  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(array0,  0)array0,  0)array0,  0)array0,  0))//
  550.             array(array1,  0)array1,  0)array1,  0)array1,  0))//  1
  551.             array(array1,  0)array1,  0)array1,  0)array1,  0))//
  552.             array(array1,  0)array1,  0)array2,  0)array2,  0))//
  553.             array(array1,  0)array2,  0)array2,  0)array4,  0))//
  554.             array(array1,  0)array2,  0)array2,  2)array2,  2))//  5
  555.             array(array2,  0)array4,  0)array4,  0)array4,  0))//
  556.             array(array2,  0)array4,  0)array2,  4)array4,  1))//
  557.             array(array2,  0)array2,  2)array4,  2)array4,  2))//
  558.             array(array2,  0)array3,  2)array4,  4)array4,  4))//
  559.             array(array2,  2)array4,  1)array6,  2)array6,  2))// 10
  560.             array(array4,  0)array1,  4)array4,  4)array3,  8))//
  561.             array(array2,  2)array6,  2)array4,  6)array7,  4))//
  562.             array(array4,  0)array8,  1)array8,  4)array(12,  4))//
  563.             array(array3,  1)array4,  5)array(11,  5)array(11,  5))//
  564.             array(array5,  1)array5,  5)array5,  7)array(11,  7))// 15
  565.             array(array5,  1)array7,  3)array(15,  2)array313))//
  566.             array(array1,  5)array(10,  1)array115)array217))//
  567.             array(array5,  1)array9,  4)array(17,  1)array219))//
  568.             array(array3,  4)array311)array(17,  4)array916))//
  569.             array(array3,  5)array313)array(15,  5)array(1510))// 20
  570.             array(array4,  4)array(17,  0)array(17,  6)array(19,  6))//
  571.             array(array2,  7)array(17,  0)array716)array(34,  0))//
  572.             array(array4,  5)array414)array(1114)array(1614))//
  573.             array(array6,  4)array614)array(1116)array(30,  2))//
  574.             array(array8,  4)array813)array722)array(2213))// 25
  575.             array(array(10,  2)array(19,  4)array(28,  6)array(33,  4))//
  576.             array(array8,  4)array(22,  3)array826)array(1228))//
  577.             array(array310)array323)array431)array(1131))//
  578.             array(array7,  7)array(21,  7)array137)array(1926))//
  579.             array(array510)array(1910)array(1525)array(2325))// 30
  580.             array(array(13,  3)array229)array(42,  1)array(2328))//
  581.             array(array(17,  0)array(1023)array(1035)array(1935))//
  582.             array(array(17,  1)array(1421)array(2919)array(1146))//
  583.             array(array(13,  6)array(1423)array(44,  7)array(59,  1))//
  584.             array(array(12,  7)array(1226)array(3914)array(2241))// 35
  585.             array(array614)array634)array(4610)array264))//
  586.             array(array(17,  4)array(2914)array(4910)array(2446))//
  587.             array(array418)array(1332)array(4814)array(4232))//
  588.             array(array(20,  4)array(40,  7)array(4322)array(1067))//
  589.             array(array(19,  6)array(1831)array(3434)array(2061))  // 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.             array0,  0),
  600.             array0,  0)array(18,  0)array(22,  0)array(26,  0)array(30,  0)//  1- 5
  601.             array(34,  0)array(2238)array(2442)array(2646)array(2850)//  6-10
  602.             array(3054)array(3258)array(3462)array(2646)array(2648)// 11-15
  603.             array(2650)array(3054)array(3056)array(3058)array(3462)// 16-20
  604.             array(2850)array(2650)array(3054)array(2854)array(3258)// 21-25
  605.             array(3058)array(3462)array(2650)array(3054)array(2652)// 26-30
  606.             array(3056)array(3460)array(3058)array(3462)array(3054)// 31-35
  607.             array(2450)array(2854)array(3258)array(2654)array(3058)  // 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.             0x07c940x085bc0x09a990x0a4d30x0bbf60x0c7620x0d8470x0e60d//
  618.             0x0f9280x10b780x1145d0x12a170x135320x149a60x156830x168c9//
  619.             0x177ec0x18ec40x191e10x1afab0x1b08e0x1cc1a0x1d33f0x1ed75//
  620.             0x1f2500x209d50x216f00x228ba0x2379f0x24b0b0x2542e0x26a64//
  621.             0x275410x28c69
  622.         );
  623.  
  624.         /**
  625.          * @var array Format information
  626.          * @access protected
  627.          */
  628.         protected $formatInfo = array(
  629.             array(0x77c40x72f30x7daa0x789d0x662f0x63180x6c410x6976)//
  630.             array(0x54120x51250x5e7c0x5b4b0x45f90x40ce0x4f970x4aa0)//
  631.             array(0x355f0x30680x3f310x3a060x24b40x21830x2eda0x2bed)//
  632.             array(0x16890x13be0x1ce70x19d00x07620x02550x0d0c0x083b)  //
  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($eclevelarray('L''M''Q''H'));
  655.             if ($this->level === false{
  656.                 $this->level = QR_ECLEVEL_L;
  657.             }
  658.             if (($this->hint != QR_MODE_8BAND ($this->hint != QR_MODE_KJ)) {
  659.                 return false;
  660.             }
  661.             if (($this->version < 0OR ($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($lineas $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(00000);
  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->eccLength0);
  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($addr0x02 (($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($addr0x02);
  767.             }
  768.             // masking
  769.             $this->runLength = array_fill(0QRSPEC_WIDTH_MAX 10);
  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_MASK8)$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 0OR ($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 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(80x11d01$el255 $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[$blockNoarray();
  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(80x11d01$el255 $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[$blockNoarray();
  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->ecccode0$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 $ichr($v);
  960.                 if ($i 6{
  961.                     $frame[$i][8chr($v);
  962.                 else {
  963.                     $frame[$i 1][8chr($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 $i][8chr($v);
  975.             if ($i == 0{
  976.                 $frame[8][7chr($v);
  977.             else {
  978.                 $frame[8][$ichr($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 $y1;
  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 $y3;
  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 $y1($x $y3;
  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 $y1($x $y31;
  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 $y3(($x $y1)) 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$widtharray_fill(0$width0));
  1074.             for ($y=0$y<$width++$y{
  1075.                 for ($x=0$x<$width++$x{
  1076.                     if (ord($frame[$y][$x]0x80{
  1077.                         $bitMask[$y][$x0;
  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][$xchr(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$widthstr_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[$i5));
  1140.                 }
  1141.                 if ($i 1{
  1142.                     if (($i >= 3AND ($i ($length-2)) AND ($this->runLength[$i== 0)) {
  1143.                         $fact = (int)($this->runLength[$i3);
  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-30OR ($this->runLength[$i-3>= ($fact))) {
  1149.                                 $demerit += N3;
  1150.                             elseif ((($i+3>= $lengthOR ($this->runLength[$i+3>= ($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[01;
  1172.                 $frameY $frame[$y];
  1173.                 if ($y 0{
  1174.                     $frameYM $frame[$y-1];
  1175.                 }
  1176.                 for ($x=0$x<$width++$x{
  1177.                     if (($x 0AND ($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 == 0AND (ord($frameY[$x]1)) {
  1185.                         $this->runLength[0= -1;
  1186.                         $head 1;
  1187.                         $this->runLength[$head1;
  1188.                     elseif ($x 0{
  1189.                         if ((ord($frameY[$x]ord($frameY[$x-1])) 1{
  1190.                             $head++;
  1191.                             $this->runLength[$head1;
  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[01;
  1202.                 for ($y=0$y<$width++$y{
  1203.                     if (($y == 0AND (ord($frame[$y][$x]1)) {
  1204.                         $this->runLength[0= -1;
  1205.                         $head 1;
  1206.                         $this->runLength[$head1;
  1207.                     elseif ($y 0{
  1208.                         if ((ord($frame[$y][$x]ord($frame[$y-1][$x])) 1{
  1209.                             $head++;
  1210.                             $this->runLength[$head1;
  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(01234567);
  1233.             if (QR_FIND_FROM_RANDOM !== false{
  1234.                 $howManuOut (QR_FIND_FROM_RANDOM 9);
  1235.                 for ($i 0$i <  $howManuOut++$i{
  1236.                     $remPos rand (0count($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$widthstr_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 505N4);
  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+strlen($this->dataStr)) {
  1306.                     $d $this->dataStr[$pos+1];
  1307.                     $word (ord($c<< 8ord($d);
  1308.                     if (($word >= 0x8140 && $word <= 0x9ffcOR ($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$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$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->itemsQR_MODE_NM$runstr_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$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$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->itemsQR_MODE_AN$runstr_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->itemsQR_MODE_KJ$pstr_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$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$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->itemsQR_MODE_8B$runstr_split($this->dataStr));
  1446.             return $run;
  1447.         }
  1448.  
  1449.         /**
  1450.          * splitString
  1451.          */
  1452.          protected function splitString({
  1453.             while (strlen($this->dataStr0{
  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[$pchr(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($data0$size);
  1524.             if (count($setData$size{
  1525.                 $setData array_merge($setDataarray_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 == 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']40x02);
  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']40x4);
  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']8ord($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']40x8);
  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]<< 8ord($inputitem['data'][$i+1]);
  1618.                 if ($val <= 0x9ffc{
  1619.                     $val -= 0x8140;
  1620.                 else {
  1621.                     $val -= 0xc140;
  1622.                 }
  1623.                 $h ($val >> 80xc0;
  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']40x03);
  1638.             $inputitem['bstream'$this->appendNum($inputitem['bstream']4ord($inputitem['data'][1]1);
  1639.             $inputitem['bstream'$this->appendNum($inputitem['bstream']4ord($inputitem['data'][0]1);
  1640.             $inputitem['bstream'$this->appendNum($inputitem['bstream']8ord($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'$wordsarray_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 <= 0OR ($index MAX_STRUCTURED_SYMBOLS)) {
  1723.                 return -1;
  1724.             }
  1725.             $buf array($size$index$parity);
  1726.             $entry $this->newInputItem(QR_MODE_ST3buf);
  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 213);
  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]<< 8ord($data[$i+1]);
  1855.                 if (($val 0x8140OR (($val 0x9ffcAND ($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 << $l;
  1934.                 $num = (int)(($item['size'$m 1$m);
  1935.                 $bits += $num ($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 78)$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 $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 132);
  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 78)$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 $bits0);
  2077.             }
  2078.             $bits += 4;
  2079.             $words = (int)(($bits 78);
  2080.             $padding array();
  2081.             $padding $this->appendNum($padding$words $bits 40);
  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$setLength0);
  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 << ($bits 1);
  2152.             for ($i=0$i<$bits++$i{
  2153.                 if ($num $mask{
  2154.                     $bstream[$i1;
  2155.                 else {
  2156.                     $bstream[$i0;
  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[$p1;
  2177.                     else {
  2178.                         $bstream[$p0;
  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 78)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[$ysubstr_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 (<< $bits1;
  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($spec5{
  2396.                 $spec array(00000);
  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[30;
  2407.                 $spec[40;
  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[11;
  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 == 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($frame6$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 7OR ($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 0OR ($mask 7)) {
  2504.                 return 0;
  2505.             }
  2506.             if (($level 0OR ($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($frame00);
  2547.             $frame $this->putFinderPattern($frame$width 70);
  2548.             $frame $this->putFinderPattern($frame0$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($frame07$setPattern);
  2559.             $frame $this->qrstrset($frame$width-87$setPattern);
  2560.             $frame $this->qrstrset($frame0$width 8$setPattern);
  2561.             // Format info
  2562.             $setPattern str_repeat("\x84"9);
  2563.             $frame $this->qrstrset($frame08$setPattern);
  2564.             $frame $this->qrstrset($frame$width 88$setPattern8);
  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+$ichr(0x90 ($i 1));
  2574.                 $frame[7+$i][6chr(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][$xchr(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 1OR ($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'!= $padOR ($rs['nroots'!= $nrootsOR ($rs['mm'!= $symsize)
  2717.                     OR ($rs['gfpoly'!= $gfpolyOR ($rs['fcr'!= $fcrOR ($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 0OR ($symsize 8)) {
  2760.                 return $rs;
  2761.             }
  2762.             if (($fcr 0OR ($fcr >= (1<<$symsize))) {
  2763.                 return $rs;
  2764.             }
  2765.             if (($prim <= 0OR ($prim >= (1<<$symsize))) {
  2766.                 return $rs;
  2767.             }
  2768.             if (($nroots 0OR ($nroots >= (1<<$symsize))) {
  2769.                 return $rs;
  2770.             }
  2771.             if (($pad 0OR ($pad >= ((1<<$symsize-$nroots))) {
  2772.                 return $rs;
  2773.             }
  2774.             $rs array();
  2775.             $rs['mm'$symsize;
  2776.             $rs['nn'(<< $symsize1;
  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'][$A00// 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 (<< $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'][01;
  2812.             for ($i 0,$root=$fcr*$prim$i $nroots$i++$root += $prim{
  2813.                 $rs['genpoly'][$i+11;
  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$NROOTS0);
  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($parity0);
  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