survey_seahorse

Software Engineering Project - Fall 2018
Log | Files | Refs | README

qrcode.php (82952B)


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