vendor/tecnickcom/tcpdf/include/barcodes/qrcode.php line 895

Open in your IDE?
  1. <?php
  2. //============================================================+
  3. // File name   : qrcode.php
  4. // Version     : 1.0.010
  5. // Begin       : 2010-03-22
  6. // Last Update : 2012-07-25
  7. // Author      : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
  8. // License     : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
  9. // -------------------------------------------------------------------
  10. // Copyright (C) 2010-2012 Nicola Asuni - Tecnick.com LTD
  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.  * @file
  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.  * @author Nicola Asuni
  78.  * @version 1.0.010
  79.  */
  80. // definitions
  81. if (!defined('QRCODEDEFS')) {
  82.     /**
  83.      * Indicate that definitions for this class are set
  84.      */
  85.     define('QRCODEDEFS'true);
  86.     // -----------------------------------------------------
  87.     // Encoding modes (characters which can be encoded in QRcode)
  88.     /**
  89.      * Encoding mode
  90.      */
  91.     define('QR_MODE_NL', -1);
  92.     /**
  93.      * Encoding mode numeric (0-9). 3 characters are encoded to 10bit length. In theory, 7089 characters or less can be stored in a QRcode.
  94.      */
  95.     define('QR_MODE_NM'0);
  96.     /**
  97.      * 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.
  98.      */
  99.     define('QR_MODE_AN'1);
  100.     /**
  101.      * Encoding mode 8bit byte data. In theory, 2953 characters or less can be stored in a QRcode.
  102.      */
  103.     define('QR_MODE_8B'2);
  104.     /**
  105.      * 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.
  106.      */
  107.     define('QR_MODE_KJ'3);
  108.     /**
  109.      * Encoding mode STRUCTURED (currently unsupported)
  110.      */
  111.     define('QR_MODE_ST'4);
  112.     // -----------------------------------------------------
  113.     // Levels of error correction.
  114.     // QRcode has a function of an error correcting for miss reading that white is black.
  115.     // Error correcting is defined in 4 level as below.
  116.     /**
  117.      * Error correction level L : About 7% or less errors can be corrected.
  118.      */
  119.     define('QR_ECLEVEL_L'0);
  120.     /**
  121.      * Error correction level M : About 15% or less errors can be corrected.
  122.      */
  123.     define('QR_ECLEVEL_M'1);
  124.     /**
  125.      * Error correction level Q : About 25% or less errors can be corrected.
  126.      */
  127.     define('QR_ECLEVEL_Q'2);
  128.     /**
  129.      * Error correction level H : About 30% or less errors can be corrected.
  130.      */
  131.     define('QR_ECLEVEL_H'3);
  132.     // -----------------------------------------------------
  133.     // Version. Size of QRcode is defined as version.
  134.     // Version is from 1 to 40.
  135.     // Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases.
  136.     // So version 40 is 177*177 matrix.
  137.     /**
  138.      * Maximum QR Code version.
  139.      */
  140.     define('QRSPEC_VERSION_MAX'40);
  141.     /**
  142.      * Maximum matrix size for maximum version (version 40 is 177*177 matrix).
  143.      */
  144.     define('QRSPEC_WIDTH_MAX'177);
  145.     // -----------------------------------------------------
  146.     /**
  147.      * Matrix index to get width from $capacity array.
  148.      */
  149.     define('QRCAP_WIDTH',    0);
  150.     /**
  151.      * Matrix index to get number of words from $capacity array.
  152.      */
  153.     define('QRCAP_WORDS',    1);
  154.     /**
  155.      * Matrix index to get remainder from $capacity array.
  156.      */
  157.     define('QRCAP_REMINDER'2);
  158.     /**
  159.      * Matrix index to get error correction level from $capacity array.
  160.      */
  161.     define('QRCAP_EC',       3);
  162.     // -----------------------------------------------------
  163.     // Structure (currently usupported)
  164.     /**
  165.      * Number of header bits for structured mode
  166.      */
  167.     define('STRUCTURE_HEADER_BITS',  20);
  168.     /**
  169.      * Max number of symbols for structured mode
  170.      */
  171.     define('MAX_STRUCTURED_SYMBOLS'16);
  172.     // -----------------------------------------------------
  173.     // Masks
  174.     /**
  175.      * Down point base value for case 1 mask pattern (concatenation of same color in a line or a column)
  176.      */
  177.     define('N1',  3);
  178.     /**
  179.      * Down point base value for case 2 mask pattern (module block of same color)
  180.      */
  181.     define('N2',  3);
  182.     /**
  183.      * 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)
  184.      */
  185.     define('N3'40);
  186.     /**
  187.      * Down point base value for case 4 mask pattern (ration of dark modules in whole)
  188.      */
  189.     define('N4'10);
  190.     // -----------------------------------------------------
  191.     // Optimization settings
  192.     /**
  193.      * if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
  194.      */
  195.     define('QR_FIND_BEST_MASK'true);
  196.     /**
  197.      * if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
  198.      */
  199.     define('QR_FIND_FROM_RANDOM'2);
  200.     /**
  201.      * when QR_FIND_BEST_MASK === false
  202.      */
  203.     define('QR_DEFAULT_MASK'2);
  204.     // -----------------------------------------------------
  205. // end of definitions
  206. /**
  207.  * @class QRcode
  208.  * Class to create QR-code arrays for TCPDF class.
  209.  * QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD.
  210.  * The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness.
  211.  * This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004.
  212.  * Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode.
  213.  *
  214.  * 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).
  215.  * Please read comments on this class source file for full copyright and license information.
  216.  *
  217.  * @package com.tecnick.tcpdf
  218.  * @author Nicola Asuni
  219.  * @version 1.0.010
  220.  */
  221. class QRcode {
  222.     /**
  223.      * Barcode array to be returned which is readable by TCPDF.
  224.      * @protected
  225.      */
  226.     protected $barcode_array = array();
  227.     /**
  228.      * 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.
  229.      * @protected
  230.      */
  231.     protected $version 0;
  232.     /**
  233.      * Levels of error correction. See definitions for possible values.
  234.      * @protected
  235.      */
  236.     protected $level QR_ECLEVEL_L;
  237.     /**
  238.      * Encoding mode.
  239.      * @protected
  240.      */
  241.     protected $hint QR_MODE_8B;
  242.     /**
  243.      * Boolean flag, if true the input string will be converted to uppercase.
  244.      * @protected
  245.      */
  246.     protected $casesensitive true;
  247.     /**
  248.      * Structured QR code (not supported yet).
  249.      * @protected
  250.      */
  251.     protected $structured 0;
  252.     /**
  253.      * Mask data.
  254.      * @protected
  255.      */
  256.     protected $data;
  257.     // FrameFiller
  258.     /**
  259.      * Width.
  260.      * @protected
  261.      */
  262.     protected $width;
  263.     /**
  264.      * Frame.
  265.      * @protected
  266.      */
  267.     protected $frame;
  268.     /**
  269.      * X position of bit.
  270.      * @protected
  271.      */
  272.     protected $x;
  273.     /**
  274.      * Y position of bit.
  275.      * @protected
  276.      */
  277.     protected $y;
  278.     /**
  279.      * Direction.
  280.      * @protected
  281.      */
  282.     protected $dir;
  283.     /**
  284.      * Single bit value.
  285.      * @protected
  286.      */
  287.     protected $bit;
  288.     // ---- QRrawcode ----
  289.     /**
  290.      * Data code.
  291.      * @protected
  292.      */
  293.     protected $datacode = array();
  294.     /**
  295.      * Error correction code.
  296.      * @protected
  297.      */
  298.     protected $ecccode = array();
  299.     /**
  300.      * Blocks.
  301.      * @protected
  302.      */
  303.     protected $blocks;
  304.     /**
  305.      * Reed-Solomon blocks.
  306.      * @protected
  307.      */
  308.     protected $rsblocks = array(); //of RSblock
  309.     /**
  310.      * Counter.
  311.      * @protected
  312.      */
  313.     protected $count;
  314.     /**
  315.      * Data length.
  316.      * @protected
  317.      */
  318.     protected $dataLength;
  319.     /**
  320.      * Error correction length.
  321.      * @protected
  322.      */
  323.     protected $eccLength;
  324.     /**
  325.      * Value b1.
  326.      * @protected
  327.      */
  328.     protected $b1;
  329.     // ---- QRmask ----
  330.     /**
  331.      * Run length.
  332.      * @protected
  333.      */
  334.     protected $runLength = array();
  335.     // ---- QRsplit ----
  336.     /**
  337.      * Input data string.
  338.      * @protected
  339.      */
  340.     protected $dataStr '';
  341.     /**
  342.      * Input items.
  343.      * @protected
  344.      */
  345.     protected $items;
  346.     // Reed-Solomon items
  347.     /**
  348.      * Reed-Solomon items.
  349.      * @protected
  350.      */
  351.     protected $rsitems = array();
  352.     /**
  353.      * Array of frames.
  354.      * @protected
  355.      */
  356.     protected $frames = array();
  357.     /**
  358.      * Alphabet-numeric convesion table.
  359.      * @protected
  360.      */
  361.     protected $anTable = array(
  362.         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1//
  363.         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1//
  364.         36, -1, -1, -13738, -1, -1, -1, -13940, -1414243//
  365.          0,  1,  2,  3,  4,  5,  6,  7,  8,  944, -1, -1, -1, -1, -1//
  366.         -1101112131415161718192021222324//
  367.         2526272829303132333435, -1, -1, -1, -1, -1//
  368.         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1//
  369.         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1  //
  370.         );
  371.     /**
  372.      * Array Table of the capacity of symbols.
  373.      * See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004.
  374.      * @protected
  375.      */
  376.     protected $capacity = array(
  377.         array(  0,    00, array(   0,    0,    0,    0)), //
  378.         array( 21,   260, array(   7,   10,   13,   17)), //  1
  379.         array( 25,   447, array(  10,   16,   22,   28)), //
  380.         array( 29,   707, array(  15,   26,   36,   44)), //
  381.         array( 33,  1007, array(  20,   36,   52,   64)), //
  382.         array( 37,  1347, array(  26,   48,   72,   88)), //  5
  383.         array( 41,  1727, array(  36,   64,   96,  112)), //
  384.         array( 45,  1960, array(  40,   72,  108,  130)), //
  385.         array( 49,  2420, array(  48,   88,  132,  156)), //
  386.         array( 53,  2920, array(  60,  110,  160,  192)), //
  387.         array( 57,  3460, array(  72,  130,  192,  224)), // 10
  388.         array( 61,  4040, array(  80,  150,  224,  264)), //
  389.         array( 65,  4660, array(  96,  176,  260,  308)), //
  390.         array( 69,  5320, array( 104,  198,  288,  352)), //
  391.         array( 73,  5813, array( 120,  216,  320,  384)), //
  392.         array( 77,  6553, array( 132,  240,  360,  432)), // 15
  393.         array( 81,  7333, array( 144,  280,  408,  480)), //
  394.         array( 85,  8153, array( 168,  308,  448,  532)), //
  395.         array( 89,  9013, array( 180,  338,  504,  588)), //
  396.         array( 93,  9913, array( 196,  364,  546,  650)), //
  397.         array( 9710853, array( 224,  416,  600,  700)), // 20
  398.         array(10111564, array( 224,  442,  644,  750)), //
  399.         array(10512584, array( 252,  476,  690,  816)), //
  400.         array(10913644, array( 270,  504,  750,  900)), //
  401.         array(11314744, array( 300,  560,  810,  960)), //
  402.         array(11715884, array( 312,  588,  8701050)), // 25
  403.         array(12117064, array( 336,  644,  9521110)), //
  404.         array(12518284, array( 360,  70010201200)), //
  405.         array(12919213, array( 390,  72810501260)), //
  406.         array(13320513, array( 420,  78411401350)), //
  407.         array(13721853, array( 450,  81212001440)), // 30
  408.         array(14123233, array( 480,  86812901530)), //
  409.         array(14524653, array( 510,  92413501620)), //
  410.         array(14926113, array( 540,  98014401710)), //
  411.         array(15327613, array( 570103615301800)), //
  412.         array(15728760, array( 570106415901890)), // 35
  413.         array(16130340, array( 600112016801980)), //
  414.         array(16531960, array( 630120417702100)), //
  415.         array(16933620, array( 660126018602220)), //
  416.         array(17335320, array( 720131619502310)), //
  417.         array(17737060, array( 750137220402430))  // 40
  418.     );
  419.     /**
  420.      * Array Length indicator.
  421.      * @protected
  422.      */
  423.     protected $lengthTableBits = array(
  424.         array(101214),
  425.         array( 91113),
  426.         array( 81616),
  427.         array( 81012)
  428.     );
  429.     /**
  430.      * Array Table of the error correction code (Reed-Solomon block).
  431.      * See Table 12-16 (pp.30-36), JIS X0510:2004.
  432.      * @protected
  433.      */
  434.     protected $eccTable = array(
  435.         array(array( 0,  0), array( 0,  0), array( 0,  0), array( 0,  0)), //
  436.         array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)), //  1
  437.         array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)), //
  438.         array(array( 1,  0), array( 1,  0), array( 2,  0), array( 2,  0)), //
  439.         array(array( 1,  0), array( 2,  0), array( 2,  0), array( 4,  0)), //
  440.         array(array( 1,  0), array( 2,  0), array( 2,  2), array( 2,  2)), //  5
  441.         array(array( 2,  0), array( 4,  0), array( 4,  0), array( 4,  0)), //
  442.         array(array( 2,  0), array( 4,  0), array( 2,  4), array( 4,  1)), //
  443.         array(array( 2,  0), array( 2,  2), array( 4,  2), array( 4,  2)), //
  444.         array(array( 2,  0), array( 3,  2), array( 4,  4), array( 4,  4)), //
  445.         array(array( 2,  2), array( 4,  1), array( 6,  2), array( 6,  2)), // 10
  446.         array(array( 4,  0), array( 1,  4), array( 4,  4), array( 3,  8)), //
  447.         array(array( 2,  2), array( 6,  2), array( 4,  6), array( 7,  4)), //
  448.         array(array( 4,  0), array( 8,  1), array( 8,  4), array(12,  4)), //
  449.         array(array( 3,  1), array( 4,  5), array(11,  5), array(11,  5)), //
  450.         array(array( 5,  1), array( 5,  5), array( 5,  7), array(11,  7)), // 15
  451.         array(array( 5,  1), array( 7,  3), array(15,  2), array( 313)), //
  452.         array(array( 1,  5), array(10,  1), array( 115), array( 217)), //
  453.         array(array( 5,  1), array( 9,  4), array(17,  1), array( 219)), //
  454.         array(array( 3,  4), array( 311), array(17,  4), array( 916)), //
  455.         array(array( 3,  5), array( 313), array(15,  5), array(1510)), // 20
  456.         array(array( 4,  4), array(17,  0), array(17,  6), array(19,  6)), //
  457.         array(array( 2,  7), array(17,  0), array( 716), array(34,  0)), //
  458.         array(array( 4,  5), array( 414), array(1114), array(1614)), //
  459.         array(array( 6,  4), array( 614), array(1116), array(30,  2)), //
  460.         array(array( 8,  4), array( 813), array( 722), array(2213)), // 25
  461.         array(array(10,  2), array(19,  4), array(28,  6), array(33,  4)), //
  462.         array(array( 8,  4), array(22,  3), array( 826), array(1228)), //
  463.         array(array( 310), array( 323), array( 431), array(1131)), //
  464.         array(array( 7,  7), array(21,  7), array( 137), array(1926)), //
  465.         array(array( 510), array(1910), array(1525), array(2325)), // 30
  466.         array(array(13,  3), array( 229), array(42,  1), array(2328)), //
  467.         array(array(17,  0), array(1023), array(1035), array(1935)), //
  468.         array(array(17,  1), array(1421), array(2919), array(1146)), //
  469.         array(array(13,  6), array(1423), array(44,  7), array(59,  1)), //
  470.         array(array(12,  7), array(1226), array(3914), array(2241)), // 35
  471.         array(array( 614), array( 634), array(4610), array( 264)), //
  472.         array(array(17,  4), array(2914), array(4910), array(2446)), //
  473.         array(array( 418), array(1332), array(4814), array(4232)), //
  474.         array(array(20,  4), array(40,  7), array(4322), array(1067)), //
  475.         array(array(19,  6), array(1831), array(3434), array(2061))  // 40
  476.     );
  477.     /**
  478.      * Array Positions of alignment patterns.
  479.      * 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.
  480.      * See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
  481.      * @protected
  482.      */
  483.     protected $alignmentPattern = array(
  484.         array( 0,  0),
  485.         array( 0,  0), array(18,  0), array(22,  0), array(26,  0), array(30,  0), //  1- 5
  486.         array(34,  0), array(2238), array(2442), array(2646), array(2850), //  6-10
  487.         array(3054), array(3258), array(3462), array(2646), array(2648), // 11-15
  488.         array(2650), array(3054), array(3056), array(3058), array(3462), // 16-20
  489.         array(2850), array(2650), array(3054), array(2854), array(3258), // 21-25
  490.         array(3058), array(3462), array(2650), array(3054), array(2652), // 26-30
  491.         array(3056), array(3460), array(3058), array(3462), array(3054), // 31-35
  492.         array(2450), array(2854), array(3258), array(2654), array(3058)  // 35-40
  493.     );
  494.     /**
  495.      * Array Version information pattern (BCH coded).
  496.      * See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
  497.      * size: [QRSPEC_VERSION_MAX - 6]
  498.      * @protected
  499.      */
  500.     protected $versionPattern = array(
  501.         0x07c940x085bc0x09a990x0a4d30x0bbf60x0c7620x0d8470x0e60d//
  502.         0x0f9280x10b780x1145d0x12a170x135320x149a60x156830x168c9//
  503.         0x177ec0x18ec40x191e10x1afab0x1b08e0x1cc1a0x1d33f0x1ed75//
  504.         0x1f2500x209d50x216f00x228ba0x2379f0x24b0b0x2542e0x26a64//
  505.         0x275410x28c69
  506.     );
  507.     /**
  508.      * Array Format information
  509.      * @protected
  510.      */
  511.     protected $formatInfo = array(
  512.         array(0x77c40x72f30x7daa0x789d0x662f0x63180x6c410x6976), //
  513.         array(0x54120x51250x5e7c0x5b4b0x45f90x40ce0x4f970x4aa0), //
  514.         array(0x355f0x30680x3f310x3a060x24b40x21830x2eda0x2bed), //
  515.         array(0x16890x13be0x1ce70x19d00x07620x02550x0d0c0x083b)  //
  516.     );
  517.     // -------------------------------------------------
  518.     // -------------------------------------------------
  519.     /**
  520.      * This is the class constructor.
  521.      * Creates a QRcode object
  522.      * @param string $code code to represent using QRcode
  523.      * @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>
  524.      * @public
  525.      * @since 1.0.000
  526.      */
  527.     public function __construct($code$eclevel 'L') {
  528.         $barcode_array = array();
  529.         if ((is_null($code)) OR ($code == '\0') OR ($code == '')) {
  530.             return false;
  531.         }
  532.         // set error correction level
  533.         $this->level array_search($eclevel, array('L''M''Q''H'));
  534.         if ($this->level === false) {
  535.             $this->level QR_ECLEVEL_L;
  536.         }
  537.         if (($this->hint != QR_MODE_8B) AND ($this->hint != QR_MODE_KJ)) {
  538.             return false;
  539.         }
  540.         if (($this->version 0) OR ($this->version QRSPEC_VERSION_MAX)) {
  541.             return false;
  542.         }
  543.         $this->items = array();
  544.         $this->encodeString($code);
  545.         if (is_null($this->data)) {
  546.             return false;
  547.         }
  548.         $qrTab $this->binarize($this->data);
  549.         $size count($qrTab);
  550.         $barcode_array['num_rows'] = $size;
  551.         $barcode_array['num_cols'] = $size;
  552.         $barcode_array['bcode'] = array();
  553.         foreach ($qrTab as $line) {
  554.             $arrAdd = array();
  555.             foreach (str_split($line) as $char) {
  556.                 $arrAdd[] = ($char=='1')?1:0;
  557.             }
  558.             $barcode_array['bcode'][] = $arrAdd;
  559.         }
  560.         $this->barcode_array $barcode_array;
  561.     }
  562.     /**
  563.      * Returns a barcode array which is readable by TCPDF
  564.      * @return array barcode array readable by TCPDF;
  565.      * @public
  566.      */
  567.     public function getBarcodeArray() {
  568.         return $this->barcode_array;
  569.     }
  570.     /**
  571.      * Convert the frame in binary form
  572.      * @param array $frame array to binarize
  573.      * @return array frame in binary form
  574.      */
  575.     protected function binarize($frame) {
  576.         $len count($frame);
  577.         // the frame is square (width = height)
  578.         foreach ($frame as &$frameLine) {
  579.             for ($i=0$i<$len$i++) {
  580.                 $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
  581.             }
  582.         }
  583.         return $frame;
  584.     }
  585.     /**
  586.      * Encode the input string to QR code
  587.      * @param string $string input string to encode
  588.      */
  589.     protected function encodeString($string) {
  590.         $this->dataStr $string;
  591.         if (!$this->casesensitive) {
  592.             $this->toUpper();
  593.         }
  594.         $ret $this->splitString();
  595.         if ($ret 0) {
  596.             return NULL;
  597.         }
  598.         $this->encodeMask(-1);
  599.     }
  600.     /**
  601.      * Encode mask
  602.      * @param int $mask masking mode
  603.      */
  604.     protected function encodeMask($mask) {
  605.         $spec = array(00000);
  606.         $this->datacode $this->getByteStream($this->items);
  607.         if (is_null($this->datacode)) {
  608.             return NULL;
  609.         }
  610.         $spec $this->getEccSpec($this->version$this->level$spec);
  611.         $this->b1 $this->rsBlockNum1($spec);
  612.         $this->dataLength $this->rsDataLength($spec);
  613.         $this->eccLength $this->rsEccLength($spec);
  614.         $this->ecccode array_fill(0$this->eccLength0);
  615.         $this->blocks $this->rsBlockNum($spec);
  616.         $ret $this->init($spec);
  617.         if ($ret 0) {
  618.             return NULL;
  619.         }
  620.         $this->count 0;
  621.         $this->width $this->getWidth($this->version);
  622.         $this->frame $this->newFrame($this->version);
  623.         $this->$this->width 1;
  624.         $this->$this->width 1;
  625.         $this->dir = -1;
  626.         $this->bit = -1;
  627.         // inteleaved data and ecc codes
  628.         for ($i=0$i < ($this->dataLength $this->eccLength); $i++) {
  629.             $code $this->getCode();
  630.             $bit 0x80;
  631.             for ($j=0$j<8$j++) {
  632.                 $addr $this->getNextPosition();
  633.                 $this->setFrameAt($addr0x02 | (($bit $code) != 0));
  634.                 $bit $bit >> 1;
  635.             }
  636.         }
  637.         // remainder bits
  638.         $j $this->getRemainder($this->version);
  639.         for ($i=0$i<$j$i++) {
  640.             $addr $this->getNextPosition();
  641.             $this->setFrameAt($addr0x02);
  642.         }
  643.         // masking
  644.         $this->runLength array_fill(0QRSPEC_WIDTH_MAX 10);
  645.         if ($mask 0) {
  646.             if (QR_FIND_BEST_MASK) {
  647.                 $masked $this->mask($this->width$this->frame$this->level);
  648.             } else {
  649.                 $masked $this->makeMask($this->width$this->frame, (intval(QR_DEFAULT_MASK) % 8), $this->level);
  650.             }
  651.         } else {
  652.             $masked $this->makeMask($this->width$this->frame$mask$this->level);
  653.         }
  654.         if ($masked == NULL) {
  655.             return NULL;
  656.         }
  657.         $this->data $masked;
  658.     }
  659.     // - - - - - - - - - - - - - - - - - - - - - - - - -
  660.     // FrameFiller
  661.     /**
  662.      * Set frame value at specified position
  663.      * @param array $at x,y position
  664.      * @param int $val value of the character to set
  665.      */
  666.     protected function setFrameAt($at$val) {
  667.         $this->frame[$at['y']][$at['x']] = chr($val);
  668.     }
  669.     /**
  670.      * Get frame value at specified position
  671.      * @param array $at x,y position
  672.      * @return value at specified position
  673.      */
  674.     protected function getFrameAt($at) {
  675.         return ord($this->frame[$at['y']][$at['x']]);
  676.     }
  677.     /**
  678.      * Return the next frame position
  679.      * @return array of x,y coordinates
  680.      */
  681.     protected function getNextPosition() {
  682.         do {
  683.             if ($this->bit == -1) {
  684.                 $this->bit 0;
  685.                 return array('x'=>$this->x'y'=>$this->y);
  686.             }
  687.             $x $this->x;
  688.             $y $this->y;
  689.             $w $this->width;
  690.             if ($this->bit == 0) {
  691.                 $x--;
  692.                 $this->bit++;
  693.             } else {
  694.                 $x++;
  695.                 $y += $this->dir;
  696.                 $this->bit--;
  697.             }
  698.             if ($this->dir 0) {
  699.                 if ($y 0) {
  700.                     $y 0;
  701.                     $x -= 2;
  702.                     $this->dir 1;
  703.                     if ($x == 6) {
  704.                         $x--;
  705.                         $y 9;
  706.                     }
  707.                 }
  708.             } else {
  709.                 if ($y == $w) {
  710.                     $y $w 1;
  711.                     $x -= 2;
  712.                     $this->dir = -1;
  713.                     if ($x == 6) {
  714.                         $x--;
  715.                         $y -= 8;
  716.                     }
  717.                 }
  718.             }
  719.             if (($x 0) OR ($y 0)) {
  720.                 return NULL;
  721.             }
  722.             $this->$x;
  723.             $this->$y;
  724.         } while(ord($this->frame[$y][$x]) & 0x80);
  725.         return array('x'=>$x'y'=>$y);
  726.     }
  727.     // - - - - - - - - - - - - - - - - - - - - - - - - -
  728.     // QRrawcode
  729.     /**
  730.      * Initialize code.
  731.      * @param array $spec array of ECC specification
  732.      * @return int 0 in case of success, -1 in case of error
  733.      */
  734.     protected function init($spec) {
  735.         $dl $this->rsDataCodes1($spec);
  736.         $el $this->rsEccCodes1($spec);
  737.         $rs $this->init_rs(80x11d01$el255 $dl $el);
  738.         $blockNo 0;
  739.         $dataPos 0;
  740.         $eccPos 0;
  741.         $endfor $this->rsBlockNum1($spec);
  742.         for ($i=0$i $endfor; ++$i) {
  743.             $ecc array_slice($this->ecccode$eccPos);
  744.             $this->rsblocks[$blockNo] = array();
  745.             $this->rsblocks[$blockNo]['dataLength'] = $dl;
  746.             $this->rsblocks[$blockNo]['data'] = array_slice($this->datacode$dataPos);
  747.             $this->rsblocks[$blockNo]['eccLength'] = $el;
  748.             $ecc $this->encode_rs_char($rs$this->rsblocks[$blockNo]['data'], $ecc);
  749.             $this->rsblocks[$blockNo]['ecc'] = $ecc;
  750.             $this->ecccode array_merge(array_slice($this->ecccode,0$eccPos), $ecc);
  751.             $dataPos += $dl;
  752.             $eccPos += $el;
  753.             $blockNo++;
  754.         }
  755.         if ($this->rsBlockNum2($spec) == 0) {
  756.             return 0;
  757.         }
  758.         $dl $this->rsDataCodes2($spec);
  759.         $el $this->rsEccCodes2($spec);
  760.         $rs $this->init_rs(80x11d01$el255 $dl $el);
  761.         if ($rs == NULL) {
  762.             return -1;
  763.         }
  764.         $endfor $this->rsBlockNum2($spec);
  765.         for ($i=0$i $endfor; ++$i) {
  766.             $ecc array_slice($this->ecccode$eccPos);
  767.             $this->rsblocks[$blockNo] = array();
  768.             $this->rsblocks[$blockNo]['dataLength'] = $dl;
  769.             $this->rsblocks[$blockNo]['data'] = array_slice($this->datacode$dataPos);
  770.             $this->rsblocks[$blockNo]['eccLength'] = $el;
  771.             $ecc $this->encode_rs_char($rs$this->rsblocks[$blockNo]['data'], $ecc);
  772.             $this->rsblocks[$blockNo]['ecc'] = $ecc;
  773.             $this->ecccode array_merge(array_slice($this->ecccode0$eccPos), $ecc);
  774.             $dataPos += $dl;
  775.             $eccPos += $el;
  776.             $blockNo++;
  777.         }
  778.         return 0;
  779.     }
  780.     /**
  781.      * Return Reed-Solomon block code.
  782.      * @return array rsblocks
  783.      */
  784.     protected function getCode() {
  785.         if ($this->count $this->dataLength) {
  786.             $row $this->count $this->blocks;
  787.             $col $this->count $this->blocks;
  788.             if ($col >= $this->rsblocks[0]['dataLength']) {
  789.                 $row += $this->b1;
  790.             }
  791.             $ret $this->rsblocks[$row]['data'][$col];
  792.         } elseif ($this->count $this->dataLength $this->eccLength) {
  793.             $row = ($this->count $this->dataLength) % $this->blocks;
  794.             $col = ($this->count $this->dataLength) / $this->blocks;
  795.             $ret $this->rsblocks[$row]['ecc'][$col];
  796.         } else {
  797.             return 0;
  798.         }
  799.         $this->count++;
  800.         return $ret;
  801.     }
  802.     // - - - - - - - - - - - - - - - - - - - - - - - - -
  803.     // QRmask
  804.     /**
  805.      * Write Format Information on frame and returns the number of black bits
  806.      * @param int $width frame width
  807.      * @param array $frame frame
  808.      * @param array $mask masking mode
  809.      * @param int $level error correction level
  810.      * @return int blacks
  811.      */
  812.      protected function writeFormatInformation($width, &$frame$mask$level) {
  813.         $blacks 0;
  814.         $format =  $this->getFormatInfo($mask$level);
  815.         for ($i=0$i<8; ++$i) {
  816.             if ($format 1) {
  817.                 $blacks += 2;
  818.                 $v 0x85;
  819.             } else {
  820.                 $v 0x84;
  821.             }
  822.             $frame[8][$width $i] = chr($v);
  823.             if ($i 6) {
  824.                 $frame[$i][8] = chr($v);
  825.             } else {
  826.                 $frame[$i 1][8] = chr($v);
  827.             }
  828.             $format $format >> 1;
  829.         }
  830.         for ($i=0$i<7; ++$i) {
  831.         if ($format 1) {
  832.             $blacks += 2;
  833.             $v 0x85;
  834.         } else {
  835.             $v 0x84;
  836.         }
  837.         $frame[$width $i][8] = chr($v);
  838.         if ($i == 0) {
  839.             $frame[8][7] = chr($v);
  840.         } else {
  841.             $frame[8][$i] = chr($v);
  842.         }
  843.         $format $format >> 1;
  844.         }
  845.         return $blacks;
  846.     }
  847.     /**
  848.      * mask0
  849.      * @param int $x X position
  850.      * @param int $y Y position
  851.      * @return int mask
  852.      */
  853.      protected function mask0($x$y) {
  854.         return ($x $y) & 1;
  855.     }
  856.     /**
  857.      * mask1
  858.      * @param int $x X position
  859.      * @param int $y Y position
  860.      * @return int mask
  861.      */
  862.      protected function mask1($x$y) {
  863.         return ($y 1);
  864.     }
  865.     /**
  866.      * mask2
  867.      * @param int $x X position
  868.      * @param int $y Y position
  869.      * @return int mask
  870.      */
  871.      protected function mask2($x$y) {
  872.         return ($x 3);
  873.     }
  874.     /**
  875.      * mask3
  876.      * @param int $x X position
  877.      * @param int $y Y position
  878.      * @return int mask
  879.      */
  880.      protected function mask3($x$y) {
  881.         return ($x $y) % 3;
  882.     }
  883.     /**
  884.      * mask4
  885.      * @param int $x X position
  886.      * @param int $y Y position
  887.      * @return int mask
  888.      */
  889.      protected function mask4($x$y) {
  890.         return (((int)($y 2)) + ((int)($x 3))) & 1;
  891.     }
  892.     /**
  893.      * mask5
  894.      * @param int $x X position
  895.      * @param int $y Y position
  896.      * @return int mask
  897.      */
  898.      protected function mask5($x$y) {
  899.         return (($x $y) & 1) + ($x $y) % 3;
  900.     }
  901.     /**
  902.      * mask6
  903.      * @param int $x X position
  904.      * @param int $y Y position
  905.      * @return int mask
  906.      */
  907.      protected function mask6($x$y) {
  908.         return ((($x $y) & 1) + ($x $y) % 3) & 1;
  909.     }
  910.     /**
  911.      * mask7
  912.      * @param int $x X position
  913.      * @param int $y Y position
  914.      * @return int mask
  915.      */
  916.      protected function mask7($x$y) {
  917.         return ((($x $y) % 3) + (($x $y) & 1)) & 1;
  918.     }
  919.     /**
  920.      * Return bitmask
  921.      * @param int $maskNo mask number
  922.      * @param int $width width
  923.      * @param array $frame frame
  924.      * @return array bitmask
  925.      */
  926.     protected function generateMaskNo($maskNo$width$frame) {
  927.         $bitMask array_fill(0$widtharray_fill(0$width0));
  928.         for ($y=0$y<$width; ++$y) {
  929.             for ($x=0$x<$width; ++$x) {
  930.                 if (ord($frame[$y][$x]) & 0x80) {
  931.                     $bitMask[$y][$x] = 0;
  932.                 } else {
  933.                     $maskFunc call_user_func(array($this'mask'.$maskNo), $x$y);
  934.                     $bitMask[$y][$x] = ($maskFunc == 0)?1:0;
  935.                 }
  936.             }
  937.         }
  938.         return $bitMask;
  939.     }
  940.     /**
  941.      * makeMaskNo
  942.      * @param int $maskNo
  943.      * @param int $width
  944.      * @param int $s
  945.      * @param int $d
  946.      * @param boolean $maskGenOnly
  947.      * @return int b
  948.      */
  949.      protected function makeMaskNo($maskNo$width$s, &$d$maskGenOnly=false) {
  950.         $b 0;
  951.         $bitMask = array();
  952.         $bitMask $this->generateMaskNo($maskNo$width$s$d);
  953.         if ($maskGenOnly) {
  954.             return;
  955.         }
  956.         $d $s;
  957.         for ($y=0$y<$width; ++$y) {
  958.             for ($x=0$x<$width; ++$x) {
  959.                 if ($bitMask[$y][$x] == 1) {
  960.                     $d[$y][$x] = chr(ord($s[$y][$x]) ^ ((int)($bitMask[$y][$x])));
  961.                 }
  962.                 $b += (int)(ord($d[$y][$x]) & 1);
  963.             }
  964.         }
  965.         return $b;
  966.     }
  967.     /**
  968.      * makeMask
  969.      * @param int $width
  970.      * @param array $frame
  971.      * @param int $maskNo
  972.      * @param int $level
  973.      * @return array mask
  974.      */
  975.      protected function makeMask($width$frame$maskNo$level) {
  976.         $masked array_fill(0$widthstr_repeat("\0"$width));
  977.         $this->makeMaskNo($maskNo$width$frame$masked);
  978.         $this->writeFormatInformation($width$masked$maskNo$level);
  979.         return $masked;
  980.     }
  981.     /**
  982.      * calcN1N3
  983.      * @param int $length
  984.      * @return int demerit
  985.      */
  986.      protected function calcN1N3($length) {
  987.         $demerit 0;
  988.         for ($i=0$i<$length; ++$i) {
  989.             if ($this->runLength[$i] >= 5) {
  990.                 $demerit += (N1 + ($this->runLength[$i] - 5));
  991.             }
  992.             if ($i 1) {
  993.                 if (($i >= 3) AND ($i < ($length-2)) AND ($this->runLength[$i] % == 0)) {
  994.                     $fact = (int)($this->runLength[$i] / 3);
  995.                     if (($this->runLength[$i-2] == $fact)
  996.                         AND ($this->runLength[$i-1] == $fact)
  997.                         AND ($this->runLength[$i+1] == $fact)
  998.                         AND ($this->runLength[$i+2] == $fact)) {
  999.                         if (($this->runLength[$i-3] < 0) OR ($this->runLength[$i-3] >= ($fact))) {
  1000.                             $demerit += N3;
  1001.                         } elseif ((($i+3) >= $length) OR ($this->runLength[$i+3] >= ($fact))) {
  1002.                             $demerit += N3;
  1003.                         }
  1004.                     }
  1005.                 }
  1006.             }
  1007.         }
  1008.         return $demerit;
  1009.     }
  1010.     /**
  1011.      * evaluateSymbol
  1012.      * @param int $width
  1013.      * @param array $frame
  1014.      * @return int demerit
  1015.      */
  1016.      protected function evaluateSymbol($width$frame) {
  1017.         $head 0;
  1018.         $demerit 0;
  1019.         for ($y=0$y<$width; ++$y) {
  1020.             $head 0;
  1021.             $this->runLength[0] = 1;
  1022.             $frameY $frame[$y];
  1023.             if ($y 0) {
  1024.                 $frameYM $frame[$y-1];
  1025.             }
  1026.             for ($x=0$x<$width; ++$x) {
  1027.                 if (($x 0) AND ($y 0)) {
  1028.                     $b22 ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
  1029.                     $w22 ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
  1030.                     if (($b22 | ($w22 1)) & 1) {
  1031.                         $demerit += N2;
  1032.                     }
  1033.                 }
  1034.                 if (($x == 0) AND (ord($frameY[$x]) & 1)) {
  1035.                     $this->runLength[0] = -1;
  1036.                     $head 1;
  1037.                     $this->runLength[$head] = 1;
  1038.                 } elseif ($x 0) {
  1039.                     if ((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
  1040.                         $head++;
  1041.                         $this->runLength[$head] = 1;
  1042.                     } else {
  1043.                         $this->runLength[$head]++;
  1044.                     }
  1045.                 }
  1046.             }
  1047.             $demerit += $this->calcN1N3($head+1);
  1048.         }
  1049.         for ($x=0$x<$width; ++$x) {
  1050.             $head 0;
  1051.             $this->runLength[0] = 1;
  1052.             for ($y=0$y<$width; ++$y) {
  1053.                 if (($y == 0) AND (ord($frame[$y][$x]) & 1)) {
  1054.                     $this->runLength[0] = -1;
  1055.                     $head 1;
  1056.                     $this->runLength[$head] = 1;
  1057.                 } elseif ($y 0) {
  1058.                     if ((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
  1059.                         $head++;
  1060.                         $this->runLength[$head] = 1;
  1061.                     } else {
  1062.                         $this->runLength[$head]++;
  1063.                     }
  1064.                 }
  1065.             }
  1066.             $demerit += $this->calcN1N3($head+1);
  1067.         }
  1068.         return $demerit;
  1069.     }
  1070.     /**
  1071.      * mask
  1072.      * @param int $width
  1073.      * @param array $frame
  1074.      * @param int $level
  1075.      * @return array best mask
  1076.      */
  1077.      protected function mask($width$frame$level) {
  1078.         $minDemerit PHP_INT_MAX;
  1079.         $bestMaskNum 0;
  1080.         $bestMask = array();
  1081.         $checked_masks = array(01234567);
  1082.         if (QR_FIND_FROM_RANDOM !== false) {
  1083.             $howManuOut - (QR_FIND_FROM_RANDOM 9);
  1084.             for ($i 0$i <  $howManuOut; ++$i) {
  1085.                 $remPos rand (0count($checked_masks)-1);
  1086.                 unset($checked_masks[$remPos]);
  1087.                 $checked_masks array_values($checked_masks);
  1088.             }
  1089.         }
  1090.         $bestMask $frame;
  1091.         foreach ($checked_masks as $i) {
  1092.             $mask array_fill(0$widthstr_repeat("\0"$width));
  1093.             $demerit 0;
  1094.             $blacks 0;
  1095.             $blacks  $this->makeMaskNo($i$width$frame$mask);
  1096.             $blacks += $this->writeFormatInformation($width$mask$i$level);
  1097.             $blacks  = (int)(100 $blacks / ($width $width));
  1098.             $demerit = (int)((int)(abs($blacks 50) / 5) * N4);
  1099.             $demerit += $this->evaluateSymbol($width$mask);
  1100.             if ($demerit $minDemerit) {
  1101.                 $minDemerit $demerit;
  1102.                 $bestMask $mask;
  1103.                 $bestMaskNum $i;
  1104.             }
  1105.         }
  1106.         return $bestMask;
  1107.     }
  1108.     // - - - - - - - - - - - - - - - - - - - - - - - - -
  1109.     // QRsplit
  1110.     /**
  1111.      * Return true if the character at specified position is a number
  1112.      * @param string $str string
  1113.      * @param int $pos characted position
  1114.      * @return boolean true of false
  1115.      */
  1116.      protected function isdigitat($str$pos) {
  1117.         if ($pos >= strlen($str)) {
  1118.             return false;
  1119.         }
  1120.         return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
  1121.     }
  1122.     /**
  1123.      * Return true if the character at specified position is an alphanumeric character
  1124.      * @param string $str string
  1125.      * @param int $pos characted position
  1126.      * @return boolean true of false
  1127.      */
  1128.      protected function isalnumat($str$pos) {
  1129.         if ($pos >= strlen($str)) {
  1130.             return false;
  1131.         }
  1132.         return ($this->lookAnTable(ord($str[$pos])) >= 0);
  1133.     }
  1134.     /**
  1135.      * identifyMode
  1136.      * @param int $pos
  1137.      * @return int mode
  1138.      */
  1139.      protected function identifyMode($pos) {
  1140.         if ($pos >= strlen($this->dataStr)) {
  1141.             return QR_MODE_NL;
  1142.         }
  1143.         $c $this->dataStr[$pos];
  1144.         if ($this->isdigitat($this->dataStr$pos)) {
  1145.             return QR_MODE_NM;
  1146.         } elseif ($this->isalnumat($this->dataStr$pos)) {
  1147.             return QR_MODE_AN;
  1148.         } elseif ($this->hint == QR_MODE_KJ) {
  1149.             if ($pos+strlen($this->dataStr)) {
  1150.                 $d $this->dataStr[$pos+1];
  1151.                 $word = (ord($c) << 8) | ord($d);
  1152.                 if (($word >= 0x8140 && $word <= 0x9ffc) OR ($word >= 0xe040 && $word <= 0xebbf)) {
  1153.                     return QR_MODE_KJ;
  1154.                 }
  1155.             }
  1156.         }
  1157.         return QR_MODE_8B;
  1158.     }
  1159.     /**
  1160.      * eatNum
  1161.      * @return int run
  1162.      */
  1163.      protected function eatNum() {
  1164.         $ln $this->lengthIndicator(QR_MODE_NM$this->version);
  1165.         $p 0;
  1166.         while($this->isdigitat($this->dataStr$p)) {
  1167.             $p++;
  1168.         }
  1169.         $run $p;
  1170.         $mode $this->identifyMode($p);
  1171.         if ($mode == QR_MODE_8B) {
  1172.             $dif $this->estimateBitsModeNum($run) + $ln
  1173.             $this->estimateBitsMode8(1)         // + 4 + l8
  1174.             $this->estimateBitsMode8($run 1); // - 4 - l8
  1175.             if ($dif 0) {
  1176.                 return $this->eat8();
  1177.             }
  1178.         }
  1179.         if ($mode == QR_MODE_AN) {
  1180.             $dif $this->estimateBitsModeNum($run) + $ln
  1181.             $this->estimateBitsModeAn(1)        // + 4 + la
  1182.             $this->estimateBitsModeAn($run 1);// - 4 - la
  1183.             if ($dif 0) {
  1184.                 return $this->eatAn();
  1185.             }
  1186.         }
  1187.         $this->items $this->appendNewInputItem($this->itemsQR_MODE_NM$runstr_split($this->dataStr));
  1188.         return $run;
  1189.     }
  1190.     /**
  1191.      * eatAn
  1192.      * @return int run
  1193.      */
  1194.      protected function eatAn() {
  1195.         $la $this->lengthIndicator(QR_MODE_AN,  $this->version);
  1196.         $ln $this->lengthIndicator(QR_MODE_NM$this->version);
  1197.         $p =;
  1198.         while($this->isalnumat($this->dataStr$p)) {
  1199.             if ($this->isdigitat($this->dataStr$p)) {
  1200.                 $q $p;
  1201.                 while($this->isdigitat($this->dataStr$q)) {
  1202.                     $q++;
  1203.                 }
  1204.                 $dif $this->estimateBitsModeAn($p// + 4 + la
  1205.                 $this->estimateBitsModeNum($q $p) + $ln
  1206.                 $this->estimateBitsModeAn($q); // - 4 - la
  1207.                 if ($dif 0) {
  1208.                     break;
  1209.                 } else {
  1210.                     $p $q;
  1211.                 }
  1212.             } else {
  1213.                 $p++;
  1214.             }
  1215.         }
  1216.         $run $p;
  1217.         if (!$this->isalnumat($this->dataStr$p)) {
  1218.             $dif $this->estimateBitsModeAn($run) + $la
  1219.             $this->estimateBitsMode8(1// + 4 + l8
  1220.             $this->estimateBitsMode8($run 1); // - 4 - l8
  1221.             if ($dif 0) {
  1222.                 return $this->eat8();
  1223.             }
  1224.         }
  1225.         $this->items $this->appendNewInputItem($this->itemsQR_MODE_AN$runstr_split($this->dataStr));
  1226.         return $run;
  1227.     }
  1228.     /**
  1229.      * eatKanji
  1230.      * @return int run
  1231.      */
  1232.      protected function eatKanji() {
  1233.         $p 0;
  1234.         while($this->identifyMode($p) == QR_MODE_KJ) {
  1235.             $p += 2;
  1236.         }
  1237.         $this->items $this->appendNewInputItem($this->itemsQR_MODE_KJ$pstr_split($this->dataStr));
  1238.         $run $p;
  1239.         return $run;
  1240.     }
  1241.     /**
  1242.      * eat8
  1243.      * @return int run
  1244.      */
  1245.      protected function eat8() {
  1246.         $la $this->lengthIndicator(QR_MODE_AN$this->version);
  1247.         $ln $this->lengthIndicator(QR_MODE_NM$this->version);
  1248.         $p 1;
  1249.         $dataStrLen strlen($this->dataStr);
  1250.         while($p $dataStrLen) {
  1251.             $mode $this->identifyMode($p);
  1252.             if ($mode == QR_MODE_KJ) {
  1253.                 break;
  1254.             }
  1255.             if ($mode == QR_MODE_NM) {
  1256.                 $q $p;
  1257.                 while($this->isdigitat($this->dataStr$q)) {
  1258.                     $q++;
  1259.                 }
  1260.                 $dif $this->estimateBitsMode8($p// + 4 + l8
  1261.                 $this->estimateBitsModeNum($q $p) + $ln
  1262.                 $this->estimateBitsMode8($q); // - 4 - l8
  1263.                 if ($dif 0) {
  1264.                     break;
  1265.                 } else {
  1266.                     $p $q;
  1267.                 }
  1268.             } elseif ($mode == QR_MODE_AN) {
  1269.                 $q $p;
  1270.                 while($this->isalnumat($this->dataStr$q)) {
  1271.                     $q++;
  1272.                 }
  1273.                 $dif $this->estimateBitsMode8($p)  // + 4 + l8
  1274.                 $this->estimateBitsModeAn($q $p) + $la
  1275.                 $this->estimateBitsMode8($q); // - 4 - l8
  1276.                 if ($dif 0) {
  1277.                     break;
  1278.                 } else {
  1279.                     $p $q;
  1280.                 }
  1281.             } else {
  1282.                 $p++;
  1283.             }
  1284.         }
  1285.         $run $p;
  1286.         $this->items $this->appendNewInputItem($this->itemsQR_MODE_8B$runstr_split($this->dataStr));
  1287.         return $run;
  1288.     }
  1289.     /**
  1290.      * splitString
  1291.      * @return int
  1292.      */
  1293.      protected function splitString() {
  1294.         while (strlen($this->dataStr) > 0) {
  1295.             $mode $this->identifyMode(0);
  1296.             switch ($mode) {
  1297.                 case QR_MODE_NM: {
  1298.                     $length $this->eatNum();
  1299.                     break;
  1300.                 }
  1301.                 case QR_MODE_AN: {
  1302.                     $length $this->eatAn();
  1303.                     break;
  1304.                 }
  1305.                 case QR_MODE_KJ: {
  1306.                     if ($this->hint == QR_MODE_KJ) {
  1307.                         $length $this->eatKanji();
  1308.                     } else {
  1309.                         $length $this->eat8();
  1310.                     }
  1311.                     break;
  1312.                 }
  1313.                 default: {
  1314.                     $length $this->eat8();
  1315.                     break;
  1316.                 }
  1317.             }
  1318.             if ($length == 0) {
  1319.                 return 0;
  1320.             }
  1321.             if ($length 0) {
  1322.                 return -1;
  1323.             }
  1324.             $this->dataStr substr($this->dataStr$length);
  1325.         }
  1326.         return 0;
  1327.     }
  1328.     /**
  1329.      * toUpper
  1330.      */
  1331.      protected function toUpper() {
  1332.         $stringLen strlen($this->dataStr);
  1333.         $p 0;
  1334.         while ($p $stringLen) {
  1335.             $mode $this->identifyMode(substr($this->dataStr$p), $this->hint);
  1336.             if ($mode == QR_MODE_KJ) {
  1337.                 $p += 2;
  1338.             } else {
  1339.                 if ((ord($this->dataStr[$p]) >= ord('a')) AND (ord($this->dataStr[$p]) <= ord('z'))) {
  1340.                     $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
  1341.                 }
  1342.                 $p++;
  1343.             }
  1344.         }
  1345.         return $this->dataStr;
  1346.     }
  1347.     // - - - - - - - - - - - - - - - - - - - - - - - - -
  1348.     // QRinputItem
  1349.     /**
  1350.      * newInputItem
  1351.      * @param int $mode
  1352.      * @param int $size
  1353.      * @param array $data
  1354.      * @param array $bstream
  1355.      * @return array input item
  1356.      */
  1357.      protected function newInputItem($mode$size$data$bstream=null) {
  1358.         $setData array_slice($data0$size);
  1359.         if (count($setData) < $size) {
  1360.             $setData array_merge($setDataarray_fill(0, ($size count($setData)), 0));
  1361.         }
  1362.         if (!$this->check($mode$size$setData)) {
  1363.             return NULL;
  1364.         }
  1365.         $inputitem = array();
  1366.         $inputitem['mode'] = $mode;
  1367.         $inputitem['size'] = $size;
  1368.         $inputitem['data'] = $setData;
  1369.         $inputitem['bstream'] = $bstream;
  1370.         return $inputitem;
  1371.     }
  1372.     /**
  1373.      * encodeModeNum
  1374.      * @param array $inputitem
  1375.      * @param int $version
  1376.      * @return array input item
  1377.      */
  1378.      protected function encodeModeNum($inputitem$version) {
  1379.         $words = (int)($inputitem['size'] / 3);
  1380.         $inputitem['bstream'] = array();
  1381.         $val 0x1;
  1382.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4$val);
  1383.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_NM$version), $inputitem['size']);
  1384.         for ($i=0$i $words; ++$i) {
  1385.             $val  = (ord($inputitem['data'][$i*3  ]) - ord('0')) * 100;
  1386.             $val += (ord($inputitem['data'][$i*3+1]) - ord('0')) * 10;
  1387.             $val += (ord($inputitem['data'][$i*3+2]) - ord('0'));
  1388.             $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 10$val);
  1389.         }
  1390.         if ($inputitem['size'] - $words == 1) {
  1391.             $val ord($inputitem['data'][$words*3]) - ord('0');
  1392.             $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4$val);
  1393.         } elseif (($inputitem['size'] - ($words 3)) == 2) {
  1394.             $val  = (ord($inputitem['data'][$words*3  ]) - ord('0')) * 10;
  1395.             $val += (ord($inputitem['data'][$words*3+1]) - ord('0'));
  1396.             $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 7$val);
  1397.         }
  1398.         return $inputitem;
  1399.     }
  1400.     /**
  1401.      * encodeModeAn
  1402.      * @param array $inputitem
  1403.      * @param int $version
  1404.      * @return array input item
  1405.      */
  1406.      protected function encodeModeAn($inputitem$version) {
  1407.         $words = (int)($inputitem['size'] / 2);
  1408.         $inputitem['bstream'] = array();
  1409.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 40x02);
  1410.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_AN$version), $inputitem['size']);
  1411.         for ($i=0$i $words; ++$i) {
  1412.             $val  = (int)($this->lookAnTable(ord($inputitem['data'][$i*2])) * 45);
  1413.             $val += (int)($this->lookAnTable(ord($inputitem['data'][($i*2)+1])));
  1414.             $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 11$val);
  1415.         }
  1416.         if ($inputitem['size'] & 1) {
  1417.             $val $this->lookAnTable(ord($inputitem['data'][($words 2)]));
  1418.             $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 6$val);
  1419.         }
  1420.         return $inputitem;
  1421.     }
  1422.     /**
  1423.      * encodeMode8
  1424.      * @param array $inputitem
  1425.      * @param int $version
  1426.      * @return array input item
  1427.      */
  1428.      protected function encodeMode8($inputitem$version) {
  1429.         $inputitem['bstream'] = array();
  1430.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 40x4);
  1431.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_8B$version), $inputitem['size']);
  1432.         for ($i=0$i $inputitem['size']; ++$i) {
  1433.             $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 8ord($inputitem['data'][$i]));
  1434.         }
  1435.         return $inputitem;
  1436.     }
  1437.     /**
  1438.      * encodeModeKanji
  1439.      * @param array $inputitem
  1440.      * @param int $version
  1441.      * @return array input item
  1442.      */
  1443.      protected function encodeModeKanji($inputitem$version) {
  1444.         $inputitem['bstream'] = array();
  1445.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 40x8);
  1446.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_KJ$version), (int)($inputitem['size'] / 2));
  1447.         for ($i=0$i<$inputitem['size']; $i+=2) {
  1448.             $val = (ord($inputitem['data'][$i]) << 8) | ord($inputitem['data'][$i+1]);
  1449.             if ($val <= 0x9ffc) {
  1450.                 $val -= 0x8140;
  1451.             } else {
  1452.                 $val -= 0xc140;
  1453.             }
  1454.             $h = ($val >> 8) * 0xc0;
  1455.             $val = ($val 0xff) + $h;
  1456.             $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 13$val);
  1457.         }
  1458.         return $inputitem;
  1459.     }
  1460.     /**
  1461.      * encodeModeStructure
  1462.      * @param array $inputitem
  1463.      * @return array input item
  1464.      */
  1465.      protected function encodeModeStructure($inputitem) {
  1466.         $inputitem['bstream'] = array();
  1467.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 40x03);
  1468.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4ord($inputitem['data'][1]) - 1);
  1469.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4ord($inputitem['data'][0]) - 1);
  1470.         $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 8ord($inputitem['data'][2]));
  1471.         return $inputitem;
  1472.     }
  1473.     /**
  1474.      * encodeBitStream
  1475.      * @param array $inputitem
  1476.      * @param int $version
  1477.      * @return array input item
  1478.      */
  1479.      protected function encodeBitStream($inputitem$version) {
  1480.         $inputitem['bstream'] = array();
  1481.         $words $this->maximumWords($inputitem['mode'], $version);
  1482.         if ($inputitem['size'] > $words) {
  1483.             $st1 $this->newInputItem($inputitem['mode'], $words$inputitem['data']);
  1484.             $st2 $this->newInputItem($inputitem['mode'], $inputitem['size'] - $wordsarray_slice($inputitem['data'], $words));
  1485.             $st1 $this->encodeBitStream($st1$version);
  1486.             $st2 $this->encodeBitStream($st2$version);
  1487.             $inputitem['bstream'] = array();
  1488.             $inputitem['bstream'] = $this->appendBitstream($inputitem['bstream'], $st1['bstream']);
  1489.             $inputitem['bstream'] = $this->appendBitstream($inputitem['bstream'], $st2['bstream']);
  1490.         } else {
  1491.             switch($inputitem['mode']) {
  1492.                 case QR_MODE_NM: {
  1493.                     $inputitem $this->encodeModeNum($inputitem$version);
  1494.                     break;
  1495.                 }
  1496.                 case QR_MODE_AN: {
  1497.                     $inputitem $this->encodeModeAn($inputitem$version);
  1498.                     break;
  1499.                 }
  1500.                 case QR_MODE_8B: {
  1501.                     $inputitem $this->encodeMode8($inputitem$version);
  1502.                     break;
  1503.                 }
  1504.                 case QR_MODE_KJ: {
  1505.                     $inputitem $this->encodeModeKanji($inputitem$version);
  1506.                     break;
  1507.                 }
  1508.                 case QR_MODE_ST: {
  1509.                     $inputitem $this->encodeModeStructure($inputitem);
  1510.                     break;
  1511.                 }
  1512.                 default: {
  1513.                     break;
  1514.                 }
  1515.             }
  1516.         }
  1517.         return $inputitem;
  1518.     }
  1519.     // - - - - - - - - - - - - - - - - - - - - - - - - -
  1520.     // QRinput
  1521.     /**
  1522.      * Append data to an input object.
  1523.      * The data is copied and appended to the input object.
  1524.      * @param array $items input items
  1525.      * @param int $mode encoding mode.
  1526.      * @param int $size size of data (byte).
  1527.      * @param array $data array of input data.
  1528.      * @return array items
  1529.      *
  1530.      */
  1531.     protected function appendNewInputItem($items$mode$size$data) {
  1532.         $newitem $this->newInputItem($mode$size$data);
  1533.         if (!empty($newitem)) {
  1534.             $items[] = $newitem;
  1535.         }
  1536.         return $items;
  1537.     }
  1538.     /**
  1539.      * insertStructuredAppendHeader
  1540.      * @param array $items
  1541.      * @param int $size
  1542.      * @param int $index
  1543.      * @param int $parity
  1544.      * @return array items
  1545.      */
  1546.      protected function insertStructuredAppendHeader($items$size$index$parity) {
  1547.         if ($size MAX_STRUCTURED_SYMBOLS) {
  1548.             return -1;
  1549.         }
  1550.         if (($index <= 0) OR ($index MAX_STRUCTURED_SYMBOLS)) {
  1551.             return -1;
  1552.         }
  1553.         $buf = array($size$index$parity);
  1554.         $entry $this->newInputItem(QR_MODE_ST3buf);
  1555.         array_unshift($items$entry);
  1556.         return $items;
  1557.     }
  1558.     /**
  1559.      * calcParity
  1560.      * @param array $items
  1561.      * @return int parity
  1562.      */
  1563.      protected function calcParity($items) {
  1564.         $parity 0;
  1565.         foreach ($items as $item) {
  1566.             if ($item['mode'] != QR_MODE_ST) {
  1567.                 for ($i=$item['size']-1$i>=0; --$i) {
  1568.                     $parity ^= $item['data'][$i];
  1569.                 }
  1570.             }
  1571.         }
  1572.         return $parity;
  1573.     }
  1574.     /**
  1575.      * checkModeNum
  1576.      * @param int $size
  1577.      * @param array $data
  1578.      * @return boolean true or false
  1579.      */
  1580.      protected function checkModeNum($size$data) {
  1581.         for ($i=0$i<$size; ++$i) {
  1582.             if ((ord($data[$i]) < ord('0')) OR (ord($data[$i]) > ord('9'))){
  1583.                 return false;
  1584.             }
  1585.         }
  1586.         return true;
  1587.     }
  1588.     /**
  1589.      * Look up the alphabet-numeric conversion table (see JIS X0510:2004, pp.19).
  1590.      * @param int $c character value
  1591.      * @return int value
  1592.      */
  1593.     protected function lookAnTable($c) {
  1594.         return (($c 127)?-1:$this->anTable[$c]);
  1595.     }
  1596.     /**
  1597.      * checkModeAn
  1598.      * @param int $size
  1599.      * @param array $data
  1600.      * @return boolean true or false
  1601.      */
  1602.      protected function checkModeAn($size$data) {
  1603.         for ($i=0$i<$size; ++$i) {
  1604.             if ($this->lookAnTable(ord($data[$i])) == -1) {
  1605.                 return false;
  1606.             }
  1607.         }
  1608.         return true;
  1609.     }
  1610.     /**
  1611.      * estimateBitsModeNum
  1612.      * @param int $size
  1613.      * @return int number of bits
  1614.      */
  1615.      protected function estimateBitsModeNum($size) {
  1616.         $w = (int)($size 3);
  1617.         $bits = ($w 10);
  1618.         switch($size - ($w 3)) {
  1619.             case 1: {
  1620.                 $bits += 4;
  1621.                 break;
  1622.             }
  1623.             case 2: {
  1624.                 $bits += 7;
  1625.                 break;
  1626.             }
  1627.         }
  1628.         return $bits;
  1629.     }
  1630.     /**
  1631.      * estimateBitsModeAn
  1632.      * @param int $size
  1633.      * @return int number of bits
  1634.      */
  1635.      protected function estimateBitsModeAn($size) {
  1636.         $bits = (int)($size 5.5); // (size / 2 ) * 11
  1637.         if ($size 1) {
  1638.             $bits += 6;
  1639.         }
  1640.         return $bits;
  1641.     }
  1642.     /**
  1643.      * estimateBitsMode8
  1644.      * @param int $size
  1645.      * @return int number of bits
  1646.      */
  1647.      protected function estimateBitsMode8($size) {
  1648.         return (int)($size 8);
  1649.     }
  1650.     /**
  1651.      * estimateBitsModeKanji
  1652.      * @param int $size
  1653.      * @return int number of bits
  1654.      */
  1655.      protected function estimateBitsModeKanji($size) {
  1656.         return (int)($size 6.5); // (size / 2 ) * 13
  1657.     }
  1658.     /**
  1659.      * checkModeKanji
  1660.      * @param int $size
  1661.      * @param array $data
  1662.      * @return boolean true or false
  1663.      */
  1664.      protected function checkModeKanji($size$data) {
  1665.         if ($size 1) {
  1666.             return false;
  1667.         }
  1668.         for ($i=0$i<$size$i+=2) {
  1669.             $val = (ord($data[$i]) << 8) | ord($data[$i+1]);
  1670.             if (($val 0x8140) OR (($val 0x9ffc) AND ($val 0xe040)) OR ($val 0xebbf)) {
  1671.                 return false;
  1672.             }
  1673.         }
  1674.         return true;
  1675.     }
  1676.     /**
  1677.      * Validate the input data.
  1678.      * @param int $mode encoding mode.
  1679.      * @param int $size size of data (byte).
  1680.      * @param array $data data to validate
  1681.      * @return boolean true in case of valid data, false otherwise
  1682.      */
  1683.     protected function check($mode$size$data) {
  1684.         if ($size <= 0) {
  1685.             return false;
  1686.         }
  1687.         switch($mode) {
  1688.             case QR_MODE_NM: {
  1689.                 return $this->checkModeNum($size$data);
  1690.             }
  1691.             case QR_MODE_AN: {
  1692.                 return $this->checkModeAn($size$data);
  1693.             }
  1694.             case QR_MODE_KJ: {
  1695.                 return $this->checkModeKanji($size$data);
  1696.             }
  1697.             case QR_MODE_8B: {
  1698.                 return true;
  1699.             }
  1700.             case QR_MODE_ST: {
  1701.                 return true;
  1702.             }
  1703.             default: {
  1704.                 break;
  1705.             }
  1706.         }
  1707.         return false;
  1708.     }
  1709.     /**
  1710.      * estimateBitStreamSize
  1711.      * @param array $items
  1712.      * @param int $version
  1713.      * @return int bits
  1714.      */
  1715.      protected function estimateBitStreamSize($items$version) {
  1716.         $bits 0;
  1717.         if ($version == 0) {
  1718.             $version 1;
  1719.         }
  1720.         foreach ($items as $item) {
  1721.             switch($item['mode']) {
  1722.                 case QR_MODE_NM: {
  1723.                     $bits $this->estimateBitsModeNum($item['size']);
  1724.                     break;
  1725.                 }
  1726.                 case QR_MODE_AN: {
  1727.                     $bits $this->estimateBitsModeAn($item['size']);
  1728.                     break;
  1729.                 }
  1730.                 case QR_MODE_8B: {
  1731.                     $bits $this->estimateBitsMode8($item['size']);
  1732.                     break;
  1733.                 }
  1734.                 case QR_MODE_KJ: {
  1735.                     $bits $this->estimateBitsModeKanji($item['size']);
  1736.                     break;
  1737.                 }
  1738.                 case QR_MODE_ST: {
  1739.                     return STRUCTURE_HEADER_BITS;
  1740.                 }
  1741.                 default: {
  1742.                     return 0;
  1743.                 }
  1744.             }
  1745.             $l $this->lengthIndicator($item['mode'], $version);
  1746.             $m << $l;
  1747.             $num = (int)(($item['size'] + $m 1) / $m);
  1748.             $bits += $num * ($l);
  1749.         }
  1750.         return $bits;
  1751.     }
  1752.     /**
  1753.      * estimateVersion
  1754.      * @param array $items
  1755.      * @return int version
  1756.      */
  1757.      protected function estimateVersion($items) {
  1758.         $version 0;
  1759.         $prev 0;
  1760.         do {
  1761.             $prev $version;
  1762.             $bits $this->estimateBitStreamSize($items$prev);
  1763.             $version $this->getMinimumVersion((int)(($bits 7) / 8), $this->level);
  1764.             if ($version 0) {
  1765.                 return -1;
  1766.             }
  1767.         } while ($version $prev);
  1768.         return $version;
  1769.     }
  1770.     /**
  1771.      * lengthOfCode
  1772.      * @param int $mode
  1773.      * @param int $version
  1774.      * @param int $bits
  1775.      * @return int size
  1776.      */
  1777.      protected function lengthOfCode($mode$version$bits) {
  1778.         $payload $bits $this->lengthIndicator($mode$version);
  1779.         switch($mode) {
  1780.             case QR_MODE_NM: {
  1781.                 $chunks = (int)($payload 10);
  1782.                 $remain $payload $chunks 10;
  1783.                 $size $chunks 3;
  1784.                 if ($remain >= 7) {
  1785.                     $size += 2;
  1786.                 } elseif ($remain >= 4) {
  1787.                     $size += 1;
  1788.                 }
  1789.                 break;
  1790.             }
  1791.             case QR_MODE_AN: {
  1792.                 $chunks = (int)($payload 11);
  1793.                 $remain $payload $chunks 11;
  1794.                 $size $chunks 2;
  1795.                 if ($remain >= 6) {
  1796.                     ++$size;
  1797.                 }
  1798.                 break;
  1799.             }
  1800.             case QR_MODE_8B: {
  1801.                 $size = (int)($payload 8);
  1802.                 break;
  1803.             }
  1804.             case QR_MODE_KJ: {
  1805.                 $size = (int)(($payload 13) * 2);
  1806.                 break;
  1807.             }
  1808.             case QR_MODE_ST: {
  1809.                 $size = (int)($payload 8);
  1810.                 break;
  1811.             }
  1812.             default: {
  1813.                 $size 0;
  1814.                 break;
  1815.             }
  1816.         }
  1817.         $maxsize $this->maximumWords($mode$version);
  1818.         if ($size 0) {
  1819.             $size 0;
  1820.         }
  1821.         if ($size $maxsize) {
  1822.             $size $maxsize;
  1823.         }
  1824.         return $size;
  1825.     }
  1826.     /**
  1827.      * createBitStream
  1828.      * @param array $items
  1829.      * @return array of items and total bits
  1830.      */
  1831.      protected function createBitStream($items) {
  1832.         $total 0;
  1833.         foreach ($items as $key => $item) {
  1834.             $items[$key] = $this->encodeBitStream($item$this->version);
  1835.             $bits count($items[$key]['bstream']);
  1836.             $total += $bits;
  1837.         }
  1838.         return array($items$total);
  1839.     }
  1840.     /**
  1841.      * convertData
  1842.      * @param array $items
  1843.      * @return array items
  1844.      */
  1845.      protected function convertData($items) {
  1846.         $ver $this->estimateVersion($items);
  1847.         if ($ver $this->version) {
  1848.             $this->version $ver;
  1849.         }
  1850.         while (true) {
  1851.             $cbs $this->createBitStream($items);
  1852.             $items $cbs[0];
  1853.             $bits $cbs[1];
  1854.             if ($bits 0) {
  1855.                 return -1;
  1856.             }
  1857.             $ver $this->getMinimumVersion((int)(($bits 7) / 8), $this->level);
  1858.             if ($ver 0) {
  1859.                 return -1;
  1860.             } elseif ($ver $this->version) {
  1861.                 $this->version $ver;
  1862.             } else {
  1863.                 break;
  1864.             }
  1865.         }
  1866.         return $items;
  1867.     }
  1868.     /**
  1869.      * Append Padding Bit to bitstream
  1870.      * @param array $bstream
  1871.      * @return array bitstream
  1872.      */
  1873.      protected function appendPaddingBit($bstream) {
  1874.          if (is_null($bstream)) {
  1875.              return null;
  1876.          }
  1877.         $bits count($bstream);
  1878.         $maxwords $this->getDataLength($this->version$this->level);
  1879.         $maxbits $maxwords 8;
  1880.         if ($maxbits == $bits) {
  1881.             return $bstream;
  1882.         }
  1883.         if ($maxbits $bits 5) {
  1884.             return $this->appendNum($bstream$maxbits $bits0);
  1885.         }
  1886.         $bits += 4;
  1887.         $words = (int)(($bits 7) / 8);
  1888.         $padding = array();
  1889.         $padding $this->appendNum($padding$words $bits 40);
  1890.         $padlen $maxwords $words;
  1891.         if ($padlen 0) {
  1892.             $padbuf = array();
  1893.             for ($i=0$i<$padlen; ++$i) {
  1894.                 $padbuf[$i] = ($i&1)?0x11:0xec;
  1895.             }
  1896.             $padding $this->appendBytes($padding$padlen$padbuf);
  1897.         }
  1898.         return $this->appendBitstream($bstream$padding);
  1899.     }
  1900.     /**
  1901.      * mergeBitStream
  1902.      * @param array $items items
  1903.      * @return array bitstream
  1904.      */
  1905.      protected function mergeBitStream($items) {
  1906.         $items $this->convertData($items);
  1907.         if (!is_array($items)) {
  1908.             return null;
  1909.         }
  1910.         $bstream = array();
  1911.         foreach ($items as $item) {
  1912.             $bstream $this->appendBitstream($bstream$item['bstream']);
  1913.         }
  1914.         return $bstream;
  1915.     }
  1916.     /**
  1917.      * Returns a stream of bits.
  1918.      * @param int $items
  1919.      * @return array padded merged byte stream
  1920.      */
  1921.     protected function getBitStream($items) {
  1922.         $bstream $this->mergeBitStream($items);
  1923.         return $this->appendPaddingBit($bstream);
  1924.     }
  1925.     /**
  1926.      * Pack all bit streams padding bits into a byte array.
  1927.      * @param int $items
  1928.      * @return array padded merged byte stream
  1929.      */
  1930.     protected function getByteStream($items) {
  1931.         $bstream $this->getBitStream($items);
  1932.         return $this->bitstreamToByte($bstream);
  1933.     }
  1934.     // - - - - - - - - - - - - - - - - - - - - - - - - -
  1935.     // QRbitstream
  1936.     /**
  1937.      * Return an array with zeros
  1938.      * @param int $setLength array size
  1939.      * @return array
  1940.      */
  1941.      protected function allocate($setLength) {
  1942.         return array_fill(0$setLength0);
  1943.     }
  1944.     /**
  1945.      * Return new bitstream from number
  1946.      * @param int $bits number of bits
  1947.      * @param int $num number
  1948.      * @return array bitstream
  1949.      */
  1950.      protected function newFromNum($bits$num) {
  1951.         $bstream $this->allocate($bits);
  1952.         $mask << ($bits 1);
  1953.         for ($i=0$i<$bits; ++$i) {
  1954.             if ($num $mask) {
  1955.                 $bstream[$i] = 1;
  1956.             } else {
  1957.                 $bstream[$i] = 0;
  1958.             }
  1959.             $mask $mask >> 1;
  1960.         }
  1961.         return $bstream;
  1962.     }
  1963.     /**
  1964.      * Return new bitstream from bytes
  1965.      * @param int $size size
  1966.      * @param array $data bytes
  1967.      * @return array bitstream
  1968.      */
  1969.      protected function newFromBytes($size$data) {
  1970.         $bstream $this->allocate($size 8);
  1971.         $p=0;
  1972.         for ($i=0$i<$size; ++$i) {
  1973.             $mask 0x80;
  1974.             for ($j=0$j<8; ++$j) {
  1975.                 if ($data[$i] & $mask) {
  1976.                     $bstream[$p] = 1;
  1977.                 } else {
  1978.                     $bstream[$p] = 0;
  1979.                 }
  1980.                 $p++;
  1981.                 $mask $mask >> 1;
  1982.             }
  1983.         }
  1984.         return $bstream;
  1985.     }
  1986.     /**
  1987.      * Append one bitstream to another
  1988.      * @param array $bitstream original bitstream
  1989.      * @param array $append bitstream to append
  1990.      * @return array bitstream
  1991.      */
  1992.      protected function appendBitstream($bitstream$append) {
  1993.         if ((!is_array($append)) OR (count($append) == 0)) {
  1994.             return $bitstream;
  1995.         }
  1996.         if (count($bitstream) == 0) {
  1997.             return $append;
  1998.         }
  1999.         return array_values(array_merge($bitstream$append));
  2000.     }
  2001.     /**
  2002.      * Append one bitstream created from number to another
  2003.      * @param array $bitstream original bitstream
  2004.      * @param int $bits number of bits
  2005.      * @param int $num number
  2006.      * @return array bitstream
  2007.      */
  2008.      protected function appendNum($bitstream$bits$num) {
  2009.         if ($bits == 0) {
  2010.             return 0;
  2011.         }
  2012.         $b $this->newFromNum($bits$num);
  2013.         return $this->appendBitstream($bitstream$b);
  2014.     }
  2015.     /**
  2016.      * Append one bitstream created from bytes to another
  2017.      * @param array $bitstream original bitstream
  2018.      * @param int $size size
  2019.      * @param array $data bytes
  2020.      * @return array bitstream
  2021.      */
  2022.      protected function appendBytes($bitstream$size$data) {
  2023.         if ($size == 0) {
  2024.             return 0;
  2025.         }
  2026.         $b $this->newFromBytes($size$data);
  2027.         return $this->appendBitstream($bitstream$b);
  2028.     }
  2029.     /**
  2030.      * Convert bitstream to bytes
  2031.      * @param array $bstream original bitstream
  2032.      * @return array of bytes
  2033.      */
  2034.      protected function bitstreamToByte($bstream) {
  2035.         if (is_null($bstream)) {
  2036.              return null;
  2037.          }
  2038.         $size count($bstream);
  2039.         if ($size == 0) {
  2040.             return array();
  2041.         }
  2042.         $data array_fill(0, (int)(($size 7) / 8), 0);
  2043.         $bytes = (int)($size 8);
  2044.         $p 0;
  2045.         for ($i=0$i<$bytes$i++) {
  2046.             $v 0;
  2047.             for ($j=0$j<8$j++) {
  2048.                 $v $v << 1;
  2049.                 $v |= $bstream[$p];
  2050.                 $p++;
  2051.             }
  2052.             $data[$i] = $v;
  2053.         }
  2054.         if ($size 7) {
  2055.             $v 0;
  2056.             for ($j=0$j<($size 7); $j++) {
  2057.                 $v $v << 1;
  2058.                 $v |= $bstream[$p];
  2059.                 $p++;
  2060.             }
  2061.             $data[$bytes] = $v;
  2062.         }
  2063.         return $data;
  2064.     }
  2065.     // - - - - - - - - - - - - - - - - - - - - - - - - -
  2066.     // QRspec
  2067.     /**
  2068.      * Replace a value on the array at the specified position
  2069.      * @param array $srctab
  2070.      * @param int $x X position
  2071.      * @param int $y Y position
  2072.      * @param string $repl value to replace
  2073.      * @param int $replLen length of the repl string
  2074.      * @return array srctab
  2075.      */
  2076.      protected function qrstrset($srctab$x$y$repl$replLen=false) {
  2077.         $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl$x, ($replLen !== false)?$replLen:strlen($repl));
  2078.         return $srctab;
  2079.     }
  2080.     /**
  2081.      * Return maximum data code length (bytes) for the version.
  2082.      * @param int $version version
  2083.      * @param int $level error correction level
  2084.      * @return int maximum size (bytes)
  2085.      */
  2086.     protected function getDataLength($version$level) {
  2087.         return $this->capacity[$version][QRCAP_WORDS] - $this->capacity[$version][QRCAP_EC][$level];
  2088.     }
  2089.     /**
  2090.      * Return maximum error correction code length (bytes) for the version.
  2091.      * @param int $version version
  2092.      * @param int $level error correction level
  2093.      * @return int ECC size (bytes)
  2094.      */
  2095.     protected function getECCLength($version$level){
  2096.         return $this->capacity[$version][QRCAP_EC][$level];
  2097.     }
  2098.     /**
  2099.      * Return the width of the symbol for the version.
  2100.      * @param int $version version
  2101.      * @return int width
  2102.      */
  2103.     protected function getWidth($version) {
  2104.         return $this->capacity[$version][QRCAP_WIDTH];
  2105.     }
  2106.     /**
  2107.      * Return the numer of remainder bits.
  2108.      * @param int $version version
  2109.      * @return int number of remainder bits
  2110.      */
  2111.     protected function getRemainder($version) {
  2112.         return $this->capacity[$version][QRCAP_REMINDER];
  2113.     }
  2114.     /**
  2115.      * Return a version number that satisfies the input code length.
  2116.      * @param int $size input code length (bytes)
  2117.      * @param int $level error correction level
  2118.      * @return int version number
  2119.      */
  2120.     protected function getMinimumVersion($size$level) {
  2121.         for ($i 1$i <= QRSPEC_VERSION_MAX; ++$i) {
  2122.             $words = ($this->capacity[$i][QRCAP_WORDS] - $this->capacity[$i][QRCAP_EC][$level]);
  2123.             if ($words >= $size) {
  2124.                 return $i;
  2125.             }
  2126.         }
  2127.         // the size of input data is greater than QR capacity, try to lover the error correction mode
  2128.         return -1;
  2129.     }
  2130.     /**
  2131.      * Return the size of length indicator for the mode and version.
  2132.      * @param int $mode encoding mode
  2133.      * @param int $version version
  2134.      * @return int the size of the appropriate length indicator (bits).
  2135.      */
  2136.     protected function lengthIndicator($mode$version) {
  2137.         if ($mode == QR_MODE_ST) {
  2138.             return 0;
  2139.         }
  2140.         if ($version <= 9) {
  2141.             $l 0;
  2142.         } elseif ($version <= 26) {
  2143.             $l 1;
  2144.         } else {
  2145.             $l 2;
  2146.         }
  2147.         return $this->lengthTableBits[$mode][$l];
  2148.     }
  2149.     /**
  2150.      * Return the maximum length for the mode and version.
  2151.      * @param int $mode encoding mode
  2152.      * @param int $version version
  2153.      * @return int the maximum length (bytes)
  2154.      */
  2155.     protected function maximumWords($mode$version) {
  2156.         if ($mode == QR_MODE_ST) {
  2157.             return 3;
  2158.         }
  2159.         if ($version <= 9) {
  2160.             $l 0;
  2161.         } else if ($version <= 26) {
  2162.             $l 1;
  2163.         } else {
  2164.             $l 2;
  2165.         }
  2166.         $bits $this->lengthTableBits[$mode][$l];
  2167.         $words = (<< $bits) - 1;
  2168.         if ($mode == QR_MODE_KJ) {
  2169.             $words *= 2// the number of bytes is required
  2170.         }
  2171.         return $words;
  2172.     }
  2173.     /**
  2174.      * Return an array of ECC specification.
  2175.      * @param int $version version
  2176.      * @param int $level error correction level
  2177.      * @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}
  2178.      * @return array spec
  2179.      */
  2180.     protected function getEccSpec($version$level$spec) {
  2181.         if (count($spec) < 5) {
  2182.             $spec = array(00000);
  2183.         }
  2184.         $b1 $this->eccTable[$version][$level][0];
  2185.         $b2 $this->eccTable[$version][$level][1];
  2186.         $data $this->getDataLength($version$level);
  2187.         $ecc $this->getECCLength($version$level);
  2188.         if ($b2 == 0) {
  2189.             $spec[0] = $b1;
  2190.             $spec[1] = (int)($data $b1);
  2191.             $spec[2] = (int)($ecc $b1);
  2192.             $spec[3] = 0;
  2193.             $spec[4] = 0;
  2194.         } else {
  2195.             $spec[0] = $b1;
  2196.             $spec[1] = (int)($data / ($b1 $b2));
  2197.             $spec[2] = (int)($ecc  / ($b1 $b2));
  2198.             $spec[3] = $b2;
  2199.             $spec[4] = $spec[1] + 1;
  2200.         }
  2201.         return $spec;
  2202.     }
  2203.     /**
  2204.      * Put an alignment marker.
  2205.      * @param array $frame frame
  2206.      * @param int $ox X center coordinate of the pattern
  2207.      * @param int $oy Y center coordinate of the pattern
  2208.      * @return array frame
  2209.      */
  2210.     protected function putAlignmentMarker($frame$ox$oy) {
  2211.         $finder = array(
  2212.             "\xa1\xa1\xa1\xa1\xa1",
  2213.             "\xa1\xa0\xa0\xa0\xa1",
  2214.             "\xa1\xa0\xa1\xa0\xa1",
  2215.             "\xa1\xa0\xa0\xa0\xa1",
  2216.             "\xa1\xa1\xa1\xa1\xa1"
  2217.             );
  2218.         $yStart $oy 2;
  2219.         $xStart $ox 2;
  2220.         for ($y=0$y 5$y++) {
  2221.             $frame $this->qrstrset($frame$xStart$yStart+$y$finder[$y]);
  2222.         }
  2223.         return $frame;
  2224.     }
  2225.     /**
  2226.      * Put an alignment pattern.
  2227.      * @param int $version version
  2228.      * @param array $frame frame
  2229.      * @param int $width width
  2230.      * @return array frame
  2231.      */
  2232.      protected function putAlignmentPattern($version$frame$width) {
  2233.         if ($version 2) {
  2234.             return $frame;
  2235.         }
  2236.         $d $this->alignmentPattern[$version][1] - $this->alignmentPattern[$version][0];
  2237.         if ($d 0) {
  2238.             $w 2;
  2239.         } else {
  2240.             $w = (int)(($width $this->alignmentPattern[$version][0]) / $d 2);
  2241.         }
  2242.         if ($w $w == 1) {
  2243.             $x $this->alignmentPattern[$version][0];
  2244.             $y $this->alignmentPattern[$version][0];
  2245.             $frame $this->putAlignmentMarker($frame$x$y);
  2246.             return $frame;
  2247.         }
  2248.         $cx $this->alignmentPattern[$version][0];
  2249.         $wo $w 1;
  2250.         for ($x=1$x $wo; ++$x) {
  2251.             $frame $this->putAlignmentMarker($frame6$cx);
  2252.             $frame $this->putAlignmentMarker($frame$cx,  6);
  2253.             $cx += $d;
  2254.         }
  2255.         $cy $this->alignmentPattern[$version][0];
  2256.         for ($y=0$y $wo; ++$y) {
  2257.             $cx $this->alignmentPattern[$version][0];
  2258.             for ($x=0$x $wo; ++$x) {
  2259.                 $frame $this->putAlignmentMarker($frame$cx$cy);
  2260.                 $cx += $d;
  2261.             }
  2262.             $cy += $d;
  2263.         }
  2264.         return $frame;
  2265.     }
  2266.     /**
  2267.      * Return BCH encoded version information pattern that is used for the symbol of version 7 or greater. Use lower 18 bits.
  2268.      * @param int $version version
  2269.      * @return string BCH encoded version information pattern
  2270.      */
  2271.     protected function getVersionPattern($version) {
  2272.         if (($version 7) OR ($version QRSPEC_VERSION_MAX)) {
  2273.             return 0;
  2274.         }
  2275.         return $this->versionPattern[($version 7)];
  2276.     }
  2277.     /**
  2278.      * Return BCH encoded format information pattern.
  2279.      * @param array $mask
  2280.      * @param int $level error correction level
  2281.      * @return string BCH encoded format information pattern
  2282.      */
  2283.     protected function getFormatInfo($mask$level) {
  2284.         if (($mask 0) OR ($mask 7)) {
  2285.             return 0;
  2286.         }
  2287.         if (($level 0) OR ($level 3)) {
  2288.             return 0;
  2289.         }
  2290.         return $this->formatInfo[$level][$mask];
  2291.     }
  2292.     /**
  2293.      * Put a finder pattern.
  2294.      * @param array $frame frame
  2295.      * @param int $ox X center coordinate of the pattern
  2296.      * @param int $oy Y center coordinate of the pattern
  2297.      * @return array frame
  2298.      */
  2299.     protected function putFinderPattern($frame$ox$oy) {
  2300.         $finder = array(
  2301.         "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
  2302.         "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
  2303.         "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
  2304.         "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
  2305.         "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
  2306.         "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
  2307.         "\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
  2308.         );
  2309.         for ($y=0$y 7$y++) {
  2310.             $frame $this->qrstrset($frame$ox, ($oy $y), $finder[$y]);
  2311.         }
  2312.         return $frame;
  2313.     }
  2314.     /**
  2315.      * Return a copy of initialized frame.
  2316.      * @param int $version version
  2317.      * @return array array of unsigned char.
  2318.      */
  2319.     protected function createFrame($version) {
  2320.         $width $this->capacity[$version][QRCAP_WIDTH];
  2321.         $frameLine str_repeat ("\0"$width);
  2322.         $frame array_fill(0$width$frameLine);
  2323.         // Finder pattern
  2324.         $frame $this->putFinderPattern($frame00);
  2325.         $frame $this->putFinderPattern($frame$width 70);
  2326.         $frame $this->putFinderPattern($frame0$width 7);
  2327.         // Separator
  2328.         $yOffset $width 7;
  2329.         for ($y=0$y 7; ++$y) {
  2330.             $frame[$y][7] = "\xc0";
  2331.             $frame[$y][$width 8] = "\xc0";
  2332.             $frame[$yOffset][7] = "\xc0";
  2333.             ++$yOffset;
  2334.         }
  2335.         $setPattern str_repeat("\xc0"8);
  2336.         $frame $this->qrstrset($frame07$setPattern);
  2337.         $frame $this->qrstrset($frame$width-87$setPattern);
  2338.         $frame $this->qrstrset($frame0$width 8$setPattern);
  2339.         // Format info
  2340.         $setPattern str_repeat("\x84"9);
  2341.         $frame $this->qrstrset($frame08$setPattern);
  2342.         $frame $this->qrstrset($frame$width 88$setPattern8);
  2343.         $yOffset $width 8;
  2344.         for ($y=0$y 8; ++$y,++$yOffset) {
  2345.             $frame[$y][8] = "\x84";
  2346.             $frame[$yOffset][8] = "\x84";
  2347.         }
  2348.         // Timing pattern
  2349.         $wo $width 15;
  2350.         for ($i=1$i $wo; ++$i) {
  2351.             $frame[6][7+$i] = chr(0x90 | ($i 1));
  2352.             $frame[7+$i][6] = chr(0x90 | ($i 1));
  2353.         }
  2354.         // Alignment pattern
  2355.         $frame $this->putAlignmentPattern($version$frame$width);
  2356.         // Version information
  2357.         if ($version >= 7) {
  2358.             $vinf $this->getVersionPattern($version);
  2359.             $v $vinf;
  2360.             for ($x=0$x<6; ++$x) {
  2361.                 for ($y=0$y<3; ++$y) {
  2362.                     $frame[($width 11)+$y][$x] = chr(0x88 | ($v 1));
  2363.                     $v $v >> 1;
  2364.                 }
  2365.             }
  2366.             $v $vinf;
  2367.             for ($y=0$y<6; ++$y) {
  2368.                 for ($x=0$x<3; ++$x) {
  2369.                     $frame[$y][$x+($width 11)] = chr(0x88 | ($v 1));
  2370.                     $v $v >> 1;
  2371.                 }
  2372.             }
  2373.         }
  2374.         // and a little bit...
  2375.         $frame[$width 8][8] = "\x81";
  2376.         return $frame;
  2377.     }
  2378.     /**
  2379.      * Set new frame for the specified version.
  2380.      * @param int $version version
  2381.      * @return array array of unsigned char.
  2382.      */
  2383.     protected function newFrame($version) {
  2384.         if (($version 1) OR ($version QRSPEC_VERSION_MAX)) {
  2385.             return NULL;
  2386.         }
  2387.         if (!isset($this->frames[$version])) {
  2388.             $this->frames[$version] = $this->createFrame($version);
  2389.         }
  2390.         if (is_null($this->frames[$version])) {
  2391.             return NULL;
  2392.         }
  2393.         return $this->frames[$version];
  2394.     }
  2395.     /**
  2396.      * Return block number 0
  2397.      * @param array $spec
  2398.      * @return int value
  2399.      */
  2400.      protected function rsBlockNum($spec) {
  2401.         return ($spec[0] + $spec[3]);
  2402.     }
  2403.     /**
  2404.     * Return block number 1
  2405.      * @param array $spec
  2406.      * @return int value
  2407.      */
  2408.      protected function rsBlockNum1($spec) {
  2409.         return $spec[0];
  2410.     }
  2411.     /**
  2412.      * Return data codes 1
  2413.      * @param array $spec
  2414.      * @return int value
  2415.      */
  2416.      protected function rsDataCodes1($spec) {
  2417.         return $spec[1];
  2418.     }
  2419.     /**
  2420.      * Return ecc codes 1
  2421.      * @param array $spec
  2422.      * @return int value
  2423.      */
  2424.      protected function rsEccCodes1($spec) {
  2425.         return $spec[2];
  2426.     }
  2427.     /**
  2428.      * Return block number 2
  2429.      * @param array $spec
  2430.      * @return int value
  2431.      */
  2432.      protected function rsBlockNum2($spec) {
  2433.         return $spec[3];
  2434.     }
  2435.     /**
  2436.      * Return data codes 2
  2437.      * @param array $spec
  2438.      * @return int value
  2439.      */
  2440.      protected function rsDataCodes2($spec) {
  2441.         return $spec[4];
  2442.     }
  2443.     /**
  2444.      * Return ecc codes 2
  2445.      * @param array $spec
  2446.      * @return int value
  2447.      */
  2448.      protected function rsEccCodes2($spec) {
  2449.         return $spec[2];
  2450.     }
  2451.     /**
  2452.      * Return data length
  2453.      * @param array $spec
  2454.      * @return int value
  2455.      */
  2456.      protected function rsDataLength($spec) {
  2457.         return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]);
  2458.     }
  2459.     /**
  2460.      * Return ecc length
  2461.      * @param array $spec
  2462.      * @return int value
  2463.      */
  2464.      protected function rsEccLength($spec) {
  2465.         return ($spec[0] + $spec[3]) * $spec[2];
  2466.     }
  2467.     // - - - - - - - - - - - - - - - - - - - - - - - - -
  2468.     // QRrs
  2469.     /**
  2470.      * Initialize a Reed-Solomon codec and add it to existing rsitems
  2471.      * @param int $symsize symbol size, bits
  2472.      * @param int $gfpoly  Field generator polynomial coefficients
  2473.      * @param int $fcr  first root of RS code generator polynomial, index form
  2474.      * @param int $prim  primitive element to generate polynomial roots
  2475.      * @param int $nroots RS code generator polynomial degree (number of roots)
  2476.      * @param int $pad  padding bytes at front of shortened block
  2477.      * @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>.
  2478.      */
  2479.      protected function init_rs($symsize$gfpoly$fcr$prim$nroots$pad) {
  2480.         foreach ($this->rsitems as $rs) {
  2481.             if (($rs['pad'] != $pad) OR ($rs['nroots'] != $nroots) OR ($rs['mm'] != $symsize)
  2482.                 OR ($rs['gfpoly'] != $gfpoly) OR ($rs['fcr'] != $fcr) OR ($rs['prim'] != $prim)) {
  2483.                 continue;
  2484.             }
  2485.             return $rs;
  2486.         }
  2487.         $rs $this->init_rs_char($symsize$gfpoly$fcr$prim$nroots$pad);
  2488.         array_unshift($this->rsitems$rs);
  2489.         return $rs;
  2490.     }
  2491.     // - - - - - - - - - - - - - - - - - - - - - - - - -
  2492.     // QRrsItem
  2493.     /**
  2494.      * modnn
  2495.      * @param array $rs RS values
  2496.      * @param int $x X position
  2497.      * @return int X osition
  2498.      */
  2499.      protected function modnn($rs$x) {
  2500.         while ($x >= $rs['nn']) {
  2501.             $x -= $rs['nn'];
  2502.             $x = ($x >> $rs['mm']) + ($x $rs['nn']);
  2503.         }
  2504.         return $x;
  2505.     }
  2506.     /**
  2507.      * Initialize a Reed-Solomon codec and returns an array of values.
  2508.      * @param int $symsize symbol size, bits
  2509.      * @param int $gfpoly  Field generator polynomial coefficients
  2510.      * @param int $fcr  first root of RS code generator polynomial, index form
  2511.      * @param int $prim  primitive element to generate polynomial roots
  2512.      * @param int $nroots RS code generator polynomial degree (number of roots)
  2513.      * @param int $pad  padding bytes at front of shortened block
  2514.      * @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>.
  2515.      */
  2516.     protected function init_rs_char($symsize$gfpoly$fcr$prim$nroots$pad) {
  2517.         // Based on Reed solomon encoder by Phil Karn, KA9Q (GNU-LGPLv2)
  2518.         $rs null;
  2519.         // Check parameter ranges
  2520.         if (($symsize 0) OR ($symsize 8)) {
  2521.             return $rs;
  2522.         }
  2523.         if (($fcr 0) OR ($fcr >= (1<<$symsize))) {
  2524.             return $rs;
  2525.         }
  2526.         if (($prim <= 0) OR ($prim >= (1<<$symsize))) {
  2527.             return $rs;
  2528.         }
  2529.         if (($nroots 0) OR ($nroots >= (1<<$symsize))) {
  2530.             return $rs;
  2531.         }
  2532.         if (($pad 0) OR ($pad >= ((1<<$symsize) -$nroots))) {
  2533.             return $rs;
  2534.         }
  2535.         $rs = array();
  2536.         $rs['mm'] = $symsize;
  2537.         $rs['nn'] = (<< $symsize) - 1;
  2538.         $rs['pad'] = $pad;
  2539.         $rs['alpha_to'] = array_fill(0, ($rs['nn'] + 1), 0);
  2540.         $rs['index_of'] = array_fill(0, ($rs['nn'] + 1), 0);
  2541.         // PHP style macro replacement ;)
  2542.         $NN =& $rs['nn'];
  2543.         $A0 =& $NN;
  2544.         // Generate Galois field lookup tables
  2545.         $rs['index_of'][0] = $A0// log(zero) = -inf
  2546.         $rs['alpha_to'][$A0] = 0// alpha**-inf = 0
  2547.         $sr 1;
  2548.         for ($i=0$i<$rs['nn']; ++$i) {
  2549.             $rs['index_of'][$sr] = $i;
  2550.             $rs['alpha_to'][$i] = $sr;
  2551.             $sr <<= 1;
  2552.             if ($sr & (<< $symsize)) {
  2553.                 $sr ^= $gfpoly;
  2554.             }
  2555.             $sr &= $rs['nn'];
  2556.         }
  2557.         if ($sr != 1) {
  2558.             // field generator polynomial is not primitive!
  2559.             return NULL;
  2560.         }
  2561.         // Form RS code generator polynomial from its roots
  2562.         $rs['genpoly'] = array_fill(0, ($nroots 1), 0);
  2563.         $rs['fcr'] = $fcr;
  2564.         $rs['prim'] = $prim;
  2565.         $rs['nroots'] = $nroots;
  2566.         $rs['gfpoly'] = $gfpoly;
  2567.         // Find prim-th root of 1, used in decoding
  2568.         for ($iprim=1; ($iprim $prim) != 0$iprim += $rs['nn']) {
  2569.             ; // intentional empty-body loop!
  2570.         }
  2571.         $rs['iprim'] = (int)($iprim $prim);
  2572.         $rs['genpoly'][0] = 1;
  2573.         for ($i 0,$root=$fcr*$prim$i $nroots$i++, $root += $prim) {
  2574.             $rs['genpoly'][$i+1] = 1;
  2575.             // Multiply rs->genpoly[] by  @**(root + x)
  2576.             for ($j $i$j 0; --$j) {
  2577.                 if ($rs['genpoly'][$j] != 0) {
  2578.                     $rs['genpoly'][$j] = $rs['genpoly'][$j-1] ^ $rs['alpha_to'][$this->modnn($rs$rs['index_of'][$rs['genpoly'][$j]] + $root)];
  2579.                 } else {
  2580.                     $rs['genpoly'][$j] = $rs['genpoly'][$j-1];
  2581.                 }
  2582.             }
  2583.             // rs->genpoly[0] can never be zero
  2584.             $rs['genpoly'][0] = $rs['alpha_to'][$this->modnn($rs$rs['index_of'][$rs['genpoly'][0]] + $root)];
  2585.         }
  2586.         // convert rs->genpoly[] to index form for quicker encoding
  2587.         for ($i 0$i <= $nroots; ++$i) {
  2588.             $rs['genpoly'][$i] = $rs['index_of'][$rs['genpoly'][$i]];
  2589.         }
  2590.         return $rs;
  2591.     }
  2592.     /**
  2593.      * Encode a Reed-Solomon codec and returns the parity array
  2594.      * @param array $rs RS values
  2595.      * @param array $data data
  2596.      * @param array $parity parity
  2597.      * @return parity array
  2598.      */
  2599.      protected function encode_rs_char($rs$data$parity) {
  2600.         $MM       =& $rs['mm']; // bits per symbol
  2601.         $NN       =& $rs['nn']; // the total number of symbols in a RS block
  2602.         $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
  2603.         $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
  2604.         $GENPOLY  =& $rs['genpoly']; // an array of NROOTS+1 elements containing the generator polynomial in index form
  2605.         $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
  2606.         $FCR      =& $rs['fcr']; // first consecutive root, index form
  2607.         $PRIM     =& $rs['prim']; // primitive element, index form
  2608.         $IPRIM    =& $rs['iprim']; // prim-th root of 1, index form
  2609.         $PAD      =& $rs['pad']; // the number of pad symbols in a block
  2610.         $A0       =& $NN;
  2611.         $parity array_fill(0$NROOTS0);
  2612.         for ($i=0$i < ($NN $NROOTS $PAD); $i++) {
  2613.             $feedback $INDEX_OF[$data[$i] ^ $parity[0]];
  2614.             if ($feedback != $A0) {
  2615.                 // feedback term is non-zero
  2616.                 // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
  2617.                 // always be for the polynomials constructed by init_rs()
  2618.                 $feedback $this->modnn($rs$NN $GENPOLY[$NROOTS] + $feedback);
  2619.                 for ($j=1$j $NROOTS; ++$j) {
  2620.                 $parity[$j] ^= $ALPHA_TO[$this->modnn($rs$feedback $GENPOLY[($NROOTS $j)])];
  2621.                 }
  2622.             }
  2623.             // Shift
  2624.             array_shift($parity);
  2625.             if ($feedback != $A0) {
  2626.                 array_push($parity$ALPHA_TO[$this->modnn($rs$feedback $GENPOLY[0])]);
  2627.             } else {
  2628.                 array_push($parity0);
  2629.             }
  2630.         }
  2631.         return $parity;
  2632.     }
  2633. // end QRcode class
  2634. //============================================================+
  2635. // END OF FILE
  2636. //============================================================+