]>
Raphaƫl G. Git Repositories - cdn/blob - vendor/phpqrcode/bindings/tcpdf/qrcode.php
2 //============================================================+
3 // File name : qrcode.php
5 // Last Update : 2010-03-29
7 // License : GNU LGPL v.3 (http://www.gnu.org/copyleft/lesser.html)
8 // ----------------------------------------------------------------------------
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.
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.
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
25 // ----------------------------------------------------------------------------
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
37 // Currently the following features are not supported:
38 // ECI and FNC1 mode, Micro QR Code, QR Code model 1,
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/
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
55 // Reed-Solomon code encoder is written by Phil Karn, KA9Q.
56 // Copyright (C) 2002-2006 Phil Karn, KA9Q
58 // QR Code is registered trademark of DENSO WAVE INCORPORATED
59 // http://www.denso-wave.com/qrcode/index-e.html
60 // ---------------------------------------------------------
62 // Author: Nicola Asuni
64 // (c) Copyright 2010:
68 // 09044 Quartucciu (CA)
72 //============================================================+
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.
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.
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
94 if (! defined ( 'QRCODEDEFS' )) {
97 * Indicate that definitions for this class are set
99 define ( 'QRCODEDEFS' , true );
101 // -----------------------------------------------------
103 // Encoding modes (characters which can be encoded in QRcode)
108 define ( 'QR_MODE_NL' , - 1 );
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.
113 define ( 'QR_MODE_NM' , 0 );
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.
118 define ( 'QR_MODE_AN' , 1 );
121 * Encoding mode 8bit byte data. In theory, 2953 characters or less can be stored in a QRcode.
123 define ( 'QR_MODE_8B' , 2 );
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.
128 define ( 'QR_MODE_KJ' , 3 );
131 * Encoding mode STRUCTURED (currently unsupported)
133 define ( 'QR_MODE_ST' , 4 );
135 // -----------------------------------------------------
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.
142 * Error correction level L : About 7% or less errors can be corrected.
144 define ( 'QR_ECLEVEL_L' , 0 );
147 * Error correction level M : About 15% or less errors can be corrected.
149 define ( 'QR_ECLEVEL_M' , 1 );
152 * Error correction level Q : About 25% or less errors can be corrected.
154 define ( 'QR_ECLEVEL_Q' , 2 );
157 * Error correction level H : About 30% or less errors can be corrected.
159 define ( 'QR_ECLEVEL_H' , 3 );
161 // -----------------------------------------------------
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.
169 * Maximum QR Code version.
171 define ( 'QRSPEC_VERSION_MAX' , 40 );
174 * Maximum matrix size for maximum version (version 40 is 177*177 matrix).
176 define ( 'QRSPEC_WIDTH_MAX' , 177 );
178 // -----------------------------------------------------
181 * Matrix index to get width from $capacity array.
183 define ( 'QRCAP_WIDTH' , 0 );
186 * Matrix index to get number of words from $capacity array.
188 define ( 'QRCAP_WORDS' , 1 );
191 * Matrix index to get remainder from $capacity array.
193 define ( 'QRCAP_REMINDER' , 2 );
196 * Matrix index to get error correction level from $capacity array.
198 define ( 'QRCAP_EC' , 3 );
200 // -----------------------------------------------------
202 // Structure (currently usupported)
205 * Number of header bits for structured mode
207 define ( 'STRUCTURE_HEADER_BITS' , 20 );
210 * Max number of symbols for structured mode
212 define ( 'MAX_STRUCTURED_SYMBOLS' , 16 );
214 // -----------------------------------------------------
219 * Down point base value for case 1 mask pattern (concatenation of same color in a line or a column)
224 * Down point base value for case 2 mask pattern (module block of same color)
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)
234 * Down point base value for case 4 mask pattern (ration of dark modules in whole)
238 // -----------------------------------------------------
240 // Optimization settings
243 * if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
245 define ( 'QR_FIND_BEST_MASK' , true );
248 * if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
250 define ( 'QR_FIND_FROM_RANDOM' , 2 );
253 * when QR_FIND_BEST_MASK === false
255 define ( 'QR_DEFAULT_MASK' , 2 );
257 // -----------------------------------------------------
259 } // end of definitions
261 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
263 if (! class_exists ( 'QRcode' , false )) {
265 // for compaibility with PHP4
266 if (! function_exists ( 'str_split' )) {
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.
273 function str_split ( $string , $split_length = 1 ) {
274 if (( strlen ( $string ) > $split_length ) OR (! $split_length )) {
276 $c = strlen ( $string );
277 $parts [] = substr ( $string , 0 , $split_length );
278 $string = substr ( $string , $split_length );
279 } while ( $string !== false );
281 $parts = array ( $string );
287 // #####################################################
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.
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.
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
311 * @var barcode array to be returned which is readable by TCPDF
314 protected $barcode_array = array ();
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.
320 protected $version = 0 ;
323 * @var Levels of error correction. See definitions for possible values.
326 protected $level = QR_ECLEVEL_L
;
332 protected $hint = QR_MODE_8B
;
335 * @var if true the input string will be converted to uppercase
338 protected $casesensitive = true ;
341 * @var structured QR code (not supported yet)
344 protected $structured = 0 ;
367 * @var X position of bit
373 * @var Y position of bit
390 // ---- QRrawcode ----
396 protected $datacode = array ();
399 * @var error correction code
402 protected $ecccode = array ();
411 * @var Reed-Solomon blocks
414 protected $rsblocks = array (); //of RSblock
426 protected $dataLength ;
429 * @var error correction length
432 protected $eccLength ;
446 protected $runLength = array ();
451 * @var input data string
454 protected $dataStr = '' ;
462 // Reed-Solomon items
465 * @var Reed-Solomon items
468 protected $rsitems = array ();
471 * @var array of frames
474 protected $frames = array ();
477 * @var alphabet-numeric convesion table
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 //
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.
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
541 * @var array Length indicator
544 protected $lengthTableBits = array (
552 * @var array Table of the error correction code (Reed-Solomon block)
553 * See Table 12-16 (pp.30-36), JIS X0510:2004.
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
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.
606 protected $alignmentPattern = array (
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
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]
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 , //
633 * @var array Format information
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 ) //
644 // -------------------------------------------------
645 // -------------------------------------------------
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>
656 public function __construct ( $code , $eclevel = 'L' ) {
657 $barcode_array = array ();
658 if (( is_null ( $code )) OR ( $code == '\0' ) OR ( $code == '' )) {
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
;
666 if (( $this- > hint
!= QR_MODE_8B
) AND ( $this- > hint
!= QR_MODE_KJ
)) {
669 if (( $this- > version
< 0 ) OR ( $this- > version
> QRSPEC_VERSION_MAX
)) {
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 ) {
681 foreach ( str_split ( $line ) as $char ) {
682 $arrAdd [] = ( $char == '1' )? 1 : 0 ;
684 $barcode_array [ 'bcode' ][] = $arrAdd ;
686 $this- > barcode_array
= $barcode_array ;
690 * Returns a barcode array which is readable by TCPDF
691 * @return array barcode array readable by TCPDF;
694 public function getBarcodeArray () {
695 return $this- > barcode_array
;
699 * Convert the frame in binary form
700 * @param array $frame array to binarize
701 * @return array frame in binary form
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' ;
715 * Encode the input string to QR code
716 * @param string $string input string to encode
718 protected function encodeString ( $string ) {
719 $this- > dataStr
= $string ;
720 if (! $this- > casesensitive
) {
723 $ret = $this- > splitString ();
727 $this- > encodeMask (- 1 );
732 * @param int $mask masking mode
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
)) {
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 );
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 ;
757 // inteleaved data and ecc codes
758 for ( $i = 0 ; $i < ( $this- > dataLength +
$this- > eccLength
); $i ++
) {
759 $code = $this- > getCode ();
761 for ( $j = 0 ; $j < 8 ; $j ++
) {
762 $addr = $this- > getNextPosition ();
763 $this- > setFrameAt ( $addr , 0x02 | (( $bit & $code ) != 0 ));
768 $j = $this- > getRemainder ( $this- > version
);
769 for ( $i = 0 ; $i < $j ; $i ++
) {
770 $addr = $this- > getNextPosition ();
771 $this- > setFrameAt ( $addr , 0x02 );
774 $this- > runLength
= array_fill ( 0 , QRSPEC_WIDTH_MAX +
1 , 0 );
776 if ( QR_FIND_BEST_MASK
) {
777 $masked = $this- > mask ( $this- > width
, $this- > frame
, $this- > level
);
779 $masked = $this- > makeMask ( $this- > width
, $this- > frame
, ( intval ( QR_DEFAULT_MASK
) %
8 ), $this- > level
);
782 $masked = $this- > makeMask ( $this- > width
, $this- > frame
, $mask , $this- > level
);
784 if ( $masked == NULL ) {
787 $this- > data
= $masked ;
790 // - - - - - - - - - - - - - - - - - - - - - - - - -
795 * Set frame value at specified position
796 * @param array $at x,y position
797 * @param int $val value of the character to set
799 protected function setFrameAt ( $at , $val ) {
800 $this- > frame
[ $at [ 'y' ]][ $at [ 'x' ]] = chr ( $val );
804 * Get frame value at specified position
805 * @param array $at x,y position
806 * @return value at specified position
808 protected function getFrameAt ( $at ) {
809 return ord ( $this- > frame
[ $at [ 'y' ]][ $at [ 'x' ]]);
813 * Return the next frame position
814 * @return array of x,y coordinates
816 protected function getNextPosition () {
818 if ( $this- > bit
== - 1 ) {
820 return array ( 'x' => $this- > x
, 'y' => $this- > y
);
825 if ( $this- > bit
== 0 ) {
833 if ( $this- > dir
< 0 ) {
854 if (( $x < 0 ) OR ( $y < 0 )) {
859 } while ( ord ( $this- > frame
[ $y ][ $x ]) & 0x80 );
860 return array ( 'x' => $x , 'y' => $y );
863 // - - - - - - - - - - - - - - - - - - - - - - - - -
869 * @param array $spec array of ECC specification
870 * @return 0 in case of success, -1 in case of error
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 );
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 );
893 if ( $this- > rsBlockNum2 ( $spec ) == 0 ) {
896 $dl = $this- > rsDataCodes2 ( $spec );
897 $el = $this- > rsEccCodes2 ( $spec );
898 $rs = $this- > init_rs ( 8 , 0x11d , 0 , 1 , $el , 255 - $dl - $el );
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 );
920 * Return Reed-Solomon block code.
921 * @return array rsblocks
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' ]) {
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 ];
942 // - - - - - - - - - - - - - - - - - - - - - - - - -
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
954 protected function writeFormatInformation ( $width , & $frame , $mask , $level ) {
956 $format = $this- > getFormatInfo ( $mask , $level );
957 for ( $i = 0 ; $i < 8 ; ++
$i ) {
964 $frame [ 8 ][ $width - 1 - $i ] = chr ( $v );
966 $frame [ $i ][ 8 ] = chr ( $v );
968 $frame [ $i +
1 ][ 8 ] = chr ( $v );
970 $format = $format >> 1 ;
972 for ( $i = 0 ; $i < 7 ; ++
$i ) {
979 $frame [ $width - 7 +
$i ][ 8 ] = chr ( $v );
981 $frame [ 8 ][ 7 ] = chr ( $v );
983 $frame [ 8 ][ 6 - $i ] = chr ( $v );
985 $format = $format >> 1 ;
992 * @param int $x X position
993 * @param int $y Y position
996 protected function mask0 ( $x , $y ) {
997 return ( $x +
$y ) & 1 ;
1002 * @param int $x X position
1003 * @param int $y Y position
1006 protected function mask1 ( $x , $y ) {
1012 * @param int $x X position
1013 * @param int $y Y position
1016 protected function mask2 ( $x , $y ) {
1022 * @param int $x X position
1023 * @param int $y Y position
1026 protected function mask3 ( $x , $y ) {
1027 return ( $x +
$y ) %
3 ;
1032 * @param int $x X position
1033 * @param int $y Y position
1036 protected function mask4 ( $x , $y ) {
1037 return ((( int )( $y / 2 )) +
(( int )( $x / 3 ))) & 1 ;
1042 * @param int $x X position
1043 * @param int $y Y position
1046 protected function mask5 ( $x , $y ) {
1047 return (( $x * $y ) & 1 ) +
( $x * $y ) %
3 ;
1052 * @param int $x X position
1053 * @param int $y Y position
1056 protected function mask6 ( $x , $y ) {
1057 return ((( $x * $y ) & 1 ) +
( $x * $y ) %
3 ) & 1 ;
1062 * @param int $x X position
1063 * @param int $y Y position
1066 protected function mask7 ( $x , $y ) {
1067 return ((( $x * $y ) %
3 ) +
(( $x +
$y ) & 1 )) & 1 ;
1072 * @param int $maskNo mask number
1073 * @param int $width width
1074 * @param array $frame frame
1075 * @return array bitmask
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 ;
1084 $maskFunc = call_user_func ( array ( $this , 'mask' . $maskNo ), $x , $y );
1085 $bitMask [ $y ][ $x ] = ( $maskFunc == 0 )? 1 : 0 ;
1094 * @param int $maskNo
1098 * @param boolean $maskGenOnly
1101 protected function makeMaskNo ( $maskNo , $width , $s , & $d , $maskGenOnly = false ) {
1104 $bitMask = $this- > generateMaskNo ( $maskNo , $width , $s , $d );
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 ]);
1114 $b +
= ( int )( ord ( $d [ $y ][ $x ]) & 1 );
1123 * @param array $frame
1124 * @param int $maskNo
1126 * @return array mask
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 );
1137 * @param int $length
1138 * @return int demerit
1140 protected function calcN1N3 ( $length ) {
1142 for ( $i = 0 ; $i < $length ; ++
$i ) {
1143 if ( $this- > runLength
[ $i ] >= 5 ) {
1144 $demerit +
= ( N1 +
( $this- > runLength
[ $i ] - 5 ));
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 ))) {
1155 } elseif ((( $i +
3 ) >= $length ) OR ( $this- > runLength
[ $i +
3 ] >= ( 4 * $fact ))) {
1168 * @param array $frame
1169 * @return int demerit
1171 protected function evaluateSymbol ( $width , $frame ) {
1174 for ( $y = 0 ; $y < $width ; ++
$y ) {
1176 $this- > runLength
[ 0 ] = 1 ;
1177 $frameY = $frame [ $y ];
1179 $frameYM = $frame [ $y-1 ];
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 ) {
1189 if (( $x == 0 ) AND ( ord ( $frameY [ $x ]) & 1 )) {
1190 $this- > runLength
[ 0 ] = - 1 ;
1192 $this- > runLength
[ $head ] = 1 ;
1194 if (( ord ( $frameY [ $x ]) ^
ord ( $frameY [ $x-1 ])) & 1 ) {
1196 $this- > runLength
[ $head ] = 1 ;
1198 $this- > runLength
[ $head ] ++
;
1202 $demerit +
= $this- > calcN1N3 ( $head +
1 );
1204 for ( $x = 0 ; $x < $width ; ++
$x ) {
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 ;
1211 $this- > runLength
[ $head ] = 1 ;
1213 if (( ord ( $frame [ $y ][ $x ]) ^
ord ( $frame [ $y-1 ][ $x ])) & 1 ) {
1215 $this- > runLength
[ $head ] = 1 ;
1217 $this- > runLength
[ $head ] ++
;
1221 $demerit +
= $this- > calcN1N3 ( $head +
1 );
1229 * @param array $frame
1231 * @return array best mask
1233 protected function mask ( $width , $frame , $level ) {
1234 $minDemerit = PHP_INT_MAX
;
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 );
1247 foreach ( $checked_masks as $i ) {
1248 $mask = array_fill ( 0 , $width , str_repeat ( "\0" , $width ));
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 ;
1265 // - - - - - - - - - - - - - - - - - - - - - - - - -
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
1275 protected function isdigitat ( $str , $pos ) {
1276 if ( $pos >= strlen ( $str )) {
1279 return (( ord ( $str [ $pos ]) >= ord ( '0' ))&&( ord ( $str [ $pos ]) <= ord ( '9' )));
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
1288 protected function isalnumat ( $str , $pos ) {
1289 if ( $pos >= strlen ( $str )) {
1292 return ( $this- > lookAnTable ( ord ( $str [ $pos ])) >= 0 );
1300 protected function identifyMode ( $pos ) {
1301 if ( $pos >= strlen ( $this- > dataStr
)) {
1304 $c = $this- > dataStr
[ $pos ];
1305 if ( $this- > isdigitat ( $this- > dataStr
, $pos )) {
1307 } elseif ( $this- > isalnumat ( $this- > dataStr
, $pos )) {
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 )) {
1325 protected function eatNum () {
1326 $ln = $this- > lengthIndicator ( QR_MODE_NM
, $this- > version
);
1328 while ( $this- > isdigitat ( $this- > dataStr
, $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
1338 return $this- > eat8 ();
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
1346 return $this- > eatAn ();
1349 $this- > items
= $this- > appendNewInputItem ( $this- > items
, QR_MODE_NM
, $run , str_split ( $this- > dataStr
));
1357 protected function eatAn () {
1358 $la = $this- > lengthIndicator ( QR_MODE_AN
, $this- > version
);
1359 $ln = $this- > lengthIndicator ( QR_MODE_NM
, $this- > version
);
1361 while ( $this- > isalnumat ( $this- > dataStr
, $p )) {
1362 if ( $this- > isdigitat ( $this- > dataStr
, $p )) {
1364 while ( $this- > isdigitat ( $this- > dataStr
, $q )) {
1367 $dif = $this- > estimateBitsModeAn ( $p ) // + 4 + la
1368 +
$this- > estimateBitsModeNum ( $q - $p ) +
4 +
$ln
1369 - $this- > estimateBitsModeAn ( $q ); // - 4 - la
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
1385 return $this- > eat8 ();
1388 $this- > items
= $this- > appendNewInputItem ( $this- > items
, QR_MODE_AN
, $run , str_split ( $this- > dataStr
));
1396 protected function eatKanji () {
1398 while ( $this- > identifyMode ( $p ) == QR_MODE_KJ
) {
1401 $this- > items
= $this- > appendNewInputItem ( $this- > items
, QR_MODE_KJ
, $p , str_split ( $this- > dataStr
));
1409 protected function eat8 () {
1410 $la = $this- > lengthIndicator ( QR_MODE_AN
, $this- > version
);
1411 $ln = $this- > lengthIndicator ( QR_MODE_NM
, $this- > version
);
1413 $dataStrLen = strlen ( $this- > dataStr
);
1414 while ( $p < $dataStrLen ) {
1415 $mode = $this- > identifyMode ( $p );
1416 if ( $mode == QR_MODE_KJ
) {
1419 if ( $mode == QR_MODE_NM
) {
1421 while ( $this- > isdigitat ( $this- > dataStr
, $q )) {
1424 $dif = $this- > estimateBitsMode8 ( $p ) // + 4 + l8
1425 +
$this- > estimateBitsModeNum ( $q - $p ) +
4 +
$ln
1426 - $this- > estimateBitsMode8 ( $q ); // - 4 - l8
1432 } elseif ( $mode == QR_MODE_AN
) {
1434 while ( $this- > isalnumat ( $this- > dataStr
, $q )) {
1437 $dif = $this- > estimateBitsMode8 ( $p ) // + 4 + l8
1438 +
$this- > estimateBitsModeAn ( $q - $p ) +
4 +
$la
1439 - $this- > estimateBitsMode8 ( $q ); // - 4 - l8
1450 $this- > items
= $this- > appendNewInputItem ( $this- > items
, QR_MODE_8B
, $run , str_split ( $this- > dataStr
));
1457 protected function splitString () {
1458 while ( strlen ( $this- > dataStr
) > 0 ) {
1459 if ( $this- > dataStr
== '' ) {
1462 $mode = $this- > identifyMode ( 0 );
1465 $length = $this- > eatNum ();
1469 $length = $this- > eatAn ();
1473 if ( $hint == QR_MODE_KJ
) {
1474 $length = $this- > eatKanji ();
1476 $length = $this- > eat8 ();
1481 $length = $this- > eat8 ();
1491 $this- > dataStr
= substr ( $this- > dataStr
, $length );
1498 protected function toUpper () {
1499 $stringLen = strlen ( $this- > dataStr
);
1501 while ( $p < $stringLen ) {
1502 $mode = $this- > identifyMode ( substr ( $this- > dataStr
, $p ), $this- > hint
);
1503 if ( $mode == QR_MODE_KJ
) {
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 );
1512 return $this- > dataStr
;
1515 // - - - - - - - - - - - - - - - - - - - - - - - - -
1523 * @param array $data
1524 * @param array $bstream
1525 * @return array input item
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 ));
1532 if (! $this- > check ( $mode , $size , $setData )) {
1535 $inputitem = array ();
1536 $inputitem [ 'mode' ] = $mode ;
1537 $inputitem [ 'size' ] = $size ;
1538 $inputitem [ 'data' ] = $setData ;
1539 $inputitem [ 'bstream' ] = $bstream ;
1545 * @param array $inputitem
1546 * @param int $version
1547 * @return array input item
1549 protected function encodeModeNum ( $inputitem , $version ) {
1550 $words = ( int )( $inputitem [ 'size' ] / 3 );
1551 $inputitem [ 'bstream' ] = array ();
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 );
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 );
1574 * @param array $inputitem
1575 * @param int $version
1576 * @return array input item
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 );
1588 if ( $inputitem [ 'size' ] & 1 ) {
1589 $val = $this- > lookAnTable ( ord ( $inputitem [ 'data' ][( $words * 2 )]));
1590 $inputitem [ 'bstream' ] = $this- > appendNum ( $inputitem [ 'bstream' ], 6 , $val );
1597 * @param array $inputitem
1598 * @param int $version
1599 * @return array input item
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 ]));
1613 * @param array $inputitem
1614 * @param int $version
1615 * @return array input item
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 ) {
1628 $h = ( $val >> 8 ) * 0xc0 ;
1629 $val = ( $val & 0xff ) +
$h ;
1630 $inputitem [ 'bstream' ] = $this- > appendNum ( $inputitem [ 'bstream' ], 13 , $val );
1636 * encodeModeStructure
1637 * @param array $inputitem
1638 * @return array input item
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 ]));
1651 * @param array $inputitem
1652 * @param int $version
1653 * @return array input item
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' ]);
1667 switch ( $inputitem [ 'mode' ]) {
1669 $inputitem = $this- > encodeModeNum ( $inputitem , $version );
1673 $inputitem = $this- > encodeModeAn ( $inputitem , $version );
1677 $inputitem = $this- > encodeMode8 ( $inputitem , $version );
1681 $inputitem = $this- > encodeModeKanji ( $inputitem , $version );
1685 $inputitem = $this- > encodeModeStructure ( $inputitem );
1696 // - - - - - - - - - - - - - - - - - - - - - - - - -
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.
1710 protected function appendNewInputItem ( $items , $mode , $size , $data ) {
1711 $items [] = $this- > newInputItem ( $mode , $size , $data );
1716 * insertStructuredAppendHeader
1717 * @param array $items
1720 * @param int $parity
1721 * @return array items
1723 protected function insertStructuredAppendHeader ( $items , $size , $index , $parity ) {
1724 if ( $size > MAX_STRUCTURED_SYMBOLS
) {
1727 if (( $index <= 0 ) OR ( $index > MAX_STRUCTURED_SYMBOLS
)) {
1730 $buf = array ( $size , $index , $parity );
1731 $entry = $this- > newInputItem ( QR_MODE_ST
, 3 , buf
);
1732 array_unshift ( $items , $entry );
1738 * @param array $items
1739 * @return int parity
1741 protected function calcParity ( $items ) {
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 ];
1756 * @param array $data
1757 * @return boolean true or false
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' ))){
1769 * estimateBitsModeNum
1771 * @return int number of bits
1773 protected function estimateBitsModeNum ( $size ) {
1774 $w = ( int ) $size / 3 ;
1776 switch ( $size - $w * 3 ) {
1793 * Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19).
1794 * @param int $c character value
1797 protected function lookAnTable ( $c ) {
1798 return (( $c > 127 )?- 1 : $this- > anTable
[ $c ]);
1804 * @param array $data
1805 * @return boolean true or false
1807 protected function checkModeAn ( $size , $data ) {
1808 for ( $i = 0 ; $i < $size ; ++
$i ) {
1809 if ( $this- > lookAnTable ( ord ( $data [ $i ])) == - 1 ) {
1817 * estimateBitsModeAn
1819 * @return int number of bits
1821 protected function estimateBitsModeAn ( $size ) {
1822 $w = ( int )( $size / 2 );
1833 * @return int number of bits
1835 protected function estimateBitsMode8 ( $size ) {
1840 * estimateBitsModeKanji
1842 * @return int number of bits
1844 protected function estimateBitsModeKanji ( $size ) {
1845 return ( int )(( $size / 2 ) * 13 );
1851 * @param array $data
1852 * @return boolean true or false
1854 protected function checkModeKanji ( $size , $data ) {
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 )) {
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
1874 protected function check ( $mode , $size , $data ) {
1880 return $this- > checkModeNum ( $size , $data );
1883 return $this- > checkModeAn ( $size , $data );
1886 return $this- > checkModeKanji ( $size , $data );
1902 * estimateBitStreamSize
1903 * @param array $items
1904 * @param int $version
1907 protected function estimateBitStreamSize ( $items , $version ) {
1909 if ( $version == 0 ) {
1912 foreach ( $items as $item ) {
1913 switch ( $item [ 'mode' ]) {
1915 $bits = $this- > estimateBitsModeNum ( $item [ 'size' ]);
1919 $bits = $this- > estimateBitsModeAn ( $item [ 'size' ]);
1923 $bits = $this- > estimateBitsMode8 ( $item [ 'size' ]);
1927 $bits = $this- > estimateBitsModeKanji ( $item [ 'size' ]);
1931 return STRUCTURE_HEADER_BITS
;
1937 $l = $this- > lengthIndicator ( $item [ 'mode' ], $version );
1939 $num = ( int )(( $item [ 'size' ] +
$m - 1 ) / $m );
1940 $bits +
= $num * ( 4 +
$l );
1947 * @param array $items
1948 * @return int version
1950 protected function estimateVersion ( $items ) {
1955 $bits = $this- > estimateBitStreamSize ( $items , $prev );
1956 $version = $this- > getMinimumVersion (( int )(( $bits +
7 ) / 8 ), $this- > level
);
1960 } while ( $version > $prev );
1967 * @param int $version
1971 protected function lengthOfCode ( $mode , $version , $bits ) {
1972 $payload = $bits - 4 - $this- > lengthIndicator ( $mode , $version );
1975 $chunks = ( int )( $payload / 10 );
1976 $remain = $payload - $chunks * 10 ;
1977 $size = $chunks * 3 ;
1980 } elseif ( $remain >= 4 ) {
1986 $chunks = ( int )( $payload / 11 );
1987 $remain = $payload - $chunks * 11 ;
1988 $size = $chunks * 2 ;
1995 $size = ( int )( $payload / 8 );
1999 $size = ( int )(( $payload / 13 ) * 2 );
2003 $size = ( int )( $payload / 8 );
2011 $maxsize = $this- > maximumWords ( $mode , $version );
2015 if ( $size > $maxsize ) {
2023 * @param array $items
2024 * @return array of items and total bits
2026 protected function createBitStream ( $items ) {
2028 foreach ( $items as $key => $item ) {
2029 $items [ $key ] = $this- > encodeBitStream ( $item , $this- > version
);
2030 $bits = count ( $items [ $key ][ 'bstream' ]);
2033 return array ( $items , $total );
2038 * @param array $items
2039 * @return array items
2041 protected function convertData ( $items ) {
2042 $ver = $this- > estimateVersion ( $items );
2043 if ( $ver > $this- > version
) {
2044 $this- > version
= $ver ;
2047 $cbs = $this- > createBitStream ( $items );
2053 $ver = $this- > getMinimumVersion (( int )(( $bits +
7 ) / 8 ), $this- > level
);
2056 } elseif ( $ver > $this- > version
) {
2057 $this- > version
= $ver ;
2066 * Append Padding Bit to bitstream
2067 * @param array $bstream
2068 * @return array bitstream
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 ) {
2077 if ( $maxbits - $bits < 5 ) {
2078 return $this- > appendNum ( $bstream , $maxbits - $bits , 0 );
2081 $words = ( int )(( $bits +
7 ) / 8 );
2083 $padding = $this- > appendNum ( $padding , $words * 8 - $bits +
4 , 0 );
2084 $padlen = $maxwords - $words ;
2087 for ( $i = 0 ; $i < $padlen ; ++
$i ) {
2088 $padbuf [ $i ] = ( $i & 1 )? 0x11 : 0xec ;
2090 $padding = $this- > appendBytes ( $padding , $padlen , $padbuf );
2092 return $this- > appendBitstream ( $bstream , $padding );
2097 * @param array $bstream
2098 * @return array bitstream
2100 protected function mergeBitStream ( $items ) {
2101 $items = $this- > convertData ( $items );
2103 foreach ( $items as $item ) {
2104 $bstream = $this- > appendBitstream ( $bstream , $item [ 'bstream' ]);
2110 * Returns a stream of bits.
2112 * @return array padded merged byte stream
2114 protected function getBitStream ( $items ) {
2115 $bstream = $this- > mergeBitStream ( $items );
2116 return $this- > appendPaddingBit ( $bstream );
2120 * Pack all bit streams padding bits into a byte array.
2122 * @return array padded merged byte stream
2124 protected function getByteStream ( $items ) {
2125 $bstream = $this- > getBitStream ( $items );
2126 return $this- > bitstreamToByte ( $bstream );
2129 // - - - - - - - - - - - - - - - - - - - - - - - - -
2134 * Return an array with zeros
2135 * @param int $setLength array size
2138 protected function allocate ( $setLength ) {
2139 return array_fill ( 0 , $setLength , 0 );
2143 * Return new bitstream from number
2144 * @param int $bits number of bits
2145 * @param int $num number
2146 * @return array bitstream
2148 protected function newFromNum ( $bits , $num ) {
2149 $bstream = $this- > allocate ( $bits );
2150 $mask = 1 << ( $bits - 1 );
2151 for ( $i = 0 ; $i < $bits ; ++
$i ) {
2163 * Return new bitstream from bytes
2164 * @param int $size size
2165 * @param array $data bytes
2166 * @return array bitstream
2168 protected function newFromBytes ( $size , $data ) {
2169 $bstream = $this- > allocate ( $size * 8 );
2171 for ( $i = 0 ; $i < $size ; ++
$i ) {
2173 for ( $j = 0 ; $j < 8 ; ++
$j ) {
2174 if ( $data [ $i ] & $mask ) {
2187 * Append one bitstream to another
2188 * @param array $bitstream original bitstream
2189 * @param array $append bitstream to append
2190 * @return array bitstream
2192 protected function appendBitstream ( $bitstream , $append ) {
2193 if ((! is_array ( $append )) OR ( count ( $append ) == 0 )) {
2196 if ( count ( $bitstream ) == 0 ) {
2199 return array_values ( array_merge ( $bitstream , $append ));
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
2209 protected function appendNum ( $bitstream , $bits , $num ) {
2213 $b = $this- > newFromNum ( $bits , $num );
2214 return $this- > appendBitstream ( $bitstream , $b );
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
2224 protected function appendBytes ( $bitstream , $size , $data ) {
2228 $b = $this- > newFromBytes ( $size , $data );
2229 return $this- > appendBitstream ( $bitstream , $b );
2233 * Convert bitstream to bytes
2234 * @param array $bitstream original bitstream
2235 * @return array of bytes
2237 protected function bitstreamToByte ( $bstream ) {
2238 $size = count ( $bstream );
2242 $data = array_fill ( 0 , ( int )(( $size +
7 ) / 8 ), 0 );
2243 $bytes = ( int )( $size / 8 );
2245 for ( $i = 0 ; $i < $bytes ; $i ++
) {
2247 for ( $j = 0 ; $j < 8 ; $j ++
) {
2256 for ( $j = 0 ; $j <( $size & 7 ); $j ++
) {
2266 // - - - - - - - - - - - - - - - - - - - - - - - - -
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
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 ));
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)
2290 protected function getDataLength ( $version , $level ) {
2291 return $this- > capacity
[ $version ][ QRCAP_WORDS
] - $this- > capacity
[ $version ][ QRCAP_EC
][ $level ];
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)
2300 protected function getECCLength ( $version , $level ){
2301 return $this- > capacity
[ $version ][ QRCAP_EC
][ $level ];
2305 * Return the width of the symbol for the version.
2306 * @param int $version version
2309 protected function getWidth ( $version ) {
2310 return $this- > capacity
[ $version ][ QRCAP_WIDTH
];
2314 * Return the numer of remainder bits.
2315 * @param int $version version
2316 * @return int number of remainder bits
2318 protected function getRemainder ( $version ) {
2319 return $this- > capacity
[ $version ][ QRCAP_REMINDER
];
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
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 ) {
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).
2344 protected function lengthIndicator ( $mode , $version ) {
2345 if ( $mode == QR_MODE_ST
) {
2348 if ( $version <= 9 ) {
2350 } elseif ( $version <= 26 ) {
2355 return $this- > lengthTableBits
[ $mode ][ $l ];
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)
2364 protected function maximumWords ( $mode , $version ) {
2365 if ( $mode == QR_MODE_ST
) {
2368 if ( $version <= 9 ) {
2370 } else if ( $version <= 26 ) {
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
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
2390 protected function getEccSpec ( $version , $level , $spec ) {
2391 if ( count ( $spec ) < 5 ) {
2392 $spec = array ( 0 , 0 , 0 , 0 , 0 );
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 );
2400 $spec [ 1 ] = ( int )( $data / $b1 );
2401 $spec [ 2 ] = ( int )( $ecc / $b1 );
2406 $spec [ 1 ] = ( int )( $data / ( $b1 +
$b2 ));
2407 $spec [ 2 ] = ( int )( $ecc / ( $b1 +
$b2 ));
2409 $spec [ 4 ] = $spec [ 1 ] +
1 ;
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
2422 protected function putAlignmentMarker ( $frame , $ox , $oy ) {
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 "
2432 for ( $y = 0 ; $y < 5 ; $y ++
) {
2433 $frame = $this- > qrstrset ( $frame , $xStart , $yStart +
$y , $finder [ $y ]);
2439 * Put an alignment pattern.
2440 * @param int $version version
2441 * @param array $fram frame
2442 * @param int $width width
2443 * @return array frame
2445 protected function putAlignmentPattern ( $version , $frame , $width ) {
2449 $d = $this- > alignmentPattern
[ $version ][ 1 ] - $this- > alignmentPattern
[ $version ][ 0 ];
2453 $w = ( int )(( $width - $this- > alignmentPattern
[ $version ][ 0 ]) / $d +
2 );
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 );
2461 $cx = $this- > alignmentPattern
[ $version ][ 0 ];
2463 for ( $x = 1 ; $x < $wo ; ++
$x ) {
2464 $frame = $this- > putAlignmentMarker ( $frame , 6 , $cx );
2465 $frame = $this- > putAlignmentMarker ( $frame , $cx , 6 );
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 );
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
2485 protected function getVersionPattern ( $version ) {
2486 if (( $version < 7 ) OR ( $version > QRSPEC_VERSION_MAX
)) {
2489 return $this- > versionPattern
[( $version - 7 )];
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
2498 protected function getFormatInfo ( $mask , $level ) {
2499 if (( $mask < 0 ) OR ( $mask > 7 )) {
2502 if (( $level < 0 ) OR ( $level > 3 )) {
2505 return $this- > formatInfo
[ $level ][ $mask ];
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
2516 protected function putFinderPattern ( $frame , $ox , $oy ) {
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 "
2526 for ( $y = 0 ; $y < 7 ; $y ++
) {
2527 $frame = $this- > qrstrset ( $frame , $ox , ( $oy +
$y ), $finder [ $y ]);
2533 * Return a copy of initialized frame.
2534 * @param int $version version
2535 * @return Array of unsigned char.
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 );
2542 $frame = $this- > putFinderPattern ( $frame , 0 , 0 );
2543 $frame = $this- > putFinderPattern ( $frame , $width - 7 , 0 );
2544 $frame = $this- > putFinderPattern ( $frame , 0 , $width - 7 );
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 " ;
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 );
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 " ;
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 ));
2572 // Alignment pattern
2573 $frame = $this- > putAlignmentPattern ( $version , $frame , $width );
2574 // Version information
2575 if ( $version >= 7 ) {
2576 $vinf = $this- > getVersionPattern ( $version );
2578 for ( $x = 0 ; $x < 6 ; ++
$x ) {
2579 for ( $y = 0 ; $y < 3 ; ++
$y ) {
2580 $frame [( $width - 11 ) +
$y ][ $x ] = chr ( 0x88 | ( $v & 1 ));
2585 for ( $y = 0 ; $y < 6 ; ++
$y ) {
2586 for ( $x = 0 ; $x < 3 ; ++
$x ) {
2587 $frame [ $y ][ $x +
( $width - 11 )] = chr ( 0x88 | ( $v & 1 ));
2592 // and a little bit...
2593 $frame [ $width - 8 ][ 8 ] = " \x81 " ;
2598 * Set new frame for the specified version.
2599 * @param int $version version
2600 * @return Array of unsigned char.
2602 protected function newFrame ( $version ) {
2603 if (( $version < 1 ) OR ( $version > QRSPEC_VERSION_MAX
)) {
2606 if (! isset ( $this- > frames
[ $version ])) {
2607 $this- > frames
[ $version ] = $this- > createFrame ( $version );
2609 if ( is_null ( $this- > frames
[ $version ])) {
2612 return $this- > frames
[ $version ];
2616 * Return block number 0
2617 * @param array $spec
2620 protected function rsBlockNum ( $spec ) {
2621 return ( $spec [ 0 ] +
$spec [ 3 ]);
2625 * Return block number 1
2626 * @param array $spec
2629 protected function rsBlockNum1 ( $spec ) {
2634 * Return data codes 1
2635 * @param array $spec
2638 protected function rsDataCodes1 ( $spec ) {
2643 * Return ecc codes 1
2644 * @param array $spec
2647 protected function rsEccCodes1 ( $spec ) {
2652 * Return block number 2
2653 * @param array $spec
2656 protected function rsBlockNum2 ( $spec ) {
2661 * Return data codes 2
2662 * @param array $spec
2665 protected function rsDataCodes2 ( $spec ) {
2670 * Return ecc codes 2
2671 * @param array $spec
2674 protected function rsEccCodes2 ( $spec ) {
2679 * Return data length
2680 * @param array $spec
2683 protected function rsDataLength ( $spec ) {
2684 return ( $spec [ 0 ] * $spec [ 1 ]) +
( $spec [ 3 ] * $spec [ 4 ]);
2689 * @param array $spec
2692 protected function rsEccLength ( $spec ) {
2693 return ( $spec [ 0 ] +
$spec [ 3 ]) * $spec [ 2 ];
2696 // - - - - - - - - - - - - - - - - - - - - - - - - -
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>.
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 )) {
2718 $rs = $this- > init_rs_char ( $symsize , $gfpoly , $fcr , $prim , $nroots , $pad );
2719 array_unshift ( $this- > rsitems
, $rs );
2723 // - - - - - - - - - - - - - - - - - - - - - - - - -
2729 * @param array RS values
2730 * @param int $x X position
2731 * @return int X osition
2733 protected function modnn ( $rs , $x ) {
2734 while ( $x >= $rs [ 'nn' ]) {
2736 $x = ( $x >> $rs [ 'mm' ]) +
( $x & $rs [ 'nn' ]);
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>.
2751 protected function init_rs_char ( $symsize , $gfpoly , $fcr , $prim , $nroots , $pad ) {
2752 // Based on Reed solomon encoder by Phil Karn, KA9Q (GNU-LGPLv2)
2754 // Check parameter ranges
2755 if (( $symsize < 0 ) OR ( $symsize > 8 )) {
2758 if (( $fcr < 0 ) OR ( $fcr >= ( 1 << $symsize ))) {
2761 if (( $prim <= 0 ) OR ( $prim >= ( 1 << $symsize ))) {
2764 if (( $nroots < 0 ) OR ( $nroots >= ( 1 << $symsize ))) {
2767 if (( $pad < 0 ) OR ( $pad >= (( 1 << $symsize ) - 1 - $nroots ))) {
2771 $rs [ 'mm' ] = $symsize ;
2772 $rs [ 'nn' ] = ( 1 << $symsize ) - 1 ;
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 ;)
2779 // Generate Galois field lookup tables
2780 $rs [ 'index_of' ][ 0 ] = $A0 ; // log(zero) = -inf
2781 $rs [ 'alpha_to' ][ $A0 ] = 0 ; // alpha**-inf = 0
2783 for ( $i = 0 ; $i < $rs [ 'nn' ]; ++
$i ) {
2784 $rs [ 'index_of' ][ $sr ] = $i ;
2785 $rs [ 'alpha_to' ][ $i ] = $sr ;
2787 if ( $sr & ( 1 << $symsize )) {
2793 // field generator polynomial is not primitive!
2796 // Form RS code generator polynomial from its roots
2797 $rs [ 'genpoly' ] = array_fill ( 0 , ( $nroots +
1 ), 0 );
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!
2806 $rs [ 'iprim' ] = ( int )( $iprim / $prim );
2807 $rs [ 'genpoly' ][ 0 ] = 1 ;
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 )];
2817 $rs [ 'genpoly' ][ $j ] = $rs [ 'genpoly' ][ $j-1 ];
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 )];
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 ]];
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
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
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 )])];
2862 array_shift ( $parity );
2863 if ( $feedback != $A0 ) {
2864 array_push ( $parity , $ALPHA_TO [ $this- > modnn ( $rs , $feedback +
$GENPOLY [ 0 ])]);
2866 array_push ( $parity , 0 );
2872 } // end QRcode class
2874 } // END OF "class_exists QRcode"