1<?php
2
3/*
4 * PHP QR Code encoder
5 *
6 * This file contains MERGED version of PHP QR Code library.
7 * It was auto-generated from full version for your convenience.
8 *
9 * This merged version was configured to not requre any external files,
10 * with disabled cache, error loging and weker but faster mask matching.
11 * If you need tune it up please use non-merged version.
12 *
13 * For full version, documentation, examples of use please visit:
14 *
15 *    http://phpqrcode.sourceforge.net/
16 *    https://sourceforge.net/projects/phpqrcode/
17 *
18 * PHP QR Code is distributed under LGPL 3
19 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
20 *
21 * This library is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU Lesser General Public
23 * License as published by the Free Software Foundation; either
24 * version 3 of the License, or any later version.
25 *
26 * This library is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 * Lesser General Public License for more details.
30 *
31 * You should have received a copy of the GNU Lesser General Public
32 * License along with this library; if not, write to the Free Software
33 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 */
35
36
37
38/*
39 * Version: 1.1.4
40 * Build: 2010100721
41 */
42
43
44
45//---- qrconst.php -----------------------------
46
47
48
49
50
51/*
52 * PHP QR Code encoder
53 *
54 * Common constants
55 *
56 * Based on libqrencode C library distributed under LGPL 2.1
57 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
58 *
59 * PHP QR Code is distributed under LGPL 3
60 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
61 *
62 * This library is free software; you can redistribute it and/or
63 * modify it under the terms of the GNU Lesser General Public
64 * License as published by the Free Software Foundation; either
65 * version 3 of the License, or any later version.
66 *
67 * This library is distributed in the hope that it will be useful,
68 * but WITHOUT ANY WARRANTY; without even the implied warranty of
69 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
70 * Lesser General Public License for more details.
71 *
72 * You should have received a copy of the GNU Lesser General Public
73 * License along with this library; if not, write to the Free Software
74 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
75 */
76
77	// Encoding modes
78
79	define('QR_MODE_NUL', -1);
80	define('QR_MODE_NUM', 0);
81	define('QR_MODE_AN', 1);
82	define('QR_MODE_8', 2);
83	define('QR_MODE_KANJI', 3);
84	define('QR_MODE_STRUCTURE', 4);
85
86	// Levels of error correction.
87
88	define('QR_ECLEVEL_L', 0);
89	define('QR_ECLEVEL_M', 1);
90	define('QR_ECLEVEL_Q', 2);
91	define('QR_ECLEVEL_H', 3);
92
93	// Supported output formats
94
95	define('QR_FORMAT_TEXT', 0);
96	define('QR_FORMAT_PNG',  1);
97
98	class qrstr {
99		public static function set(&$srctab, $x, $y, $repl, $replLen = false) {
100			$srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl));
101		}
102	}
103
104
105
106//---- merged_config.php -----------------------------
107
108
109
110
111/*
112 * PHP QR Code encoder
113 *
114 * Config file, tuned-up for merged verion
115 */
116
117    define('QR_CACHEABLE', false);       // use cache - more disk reads but less CPU power, masks and format templates are stored there
118    define('QR_CACHE_DIR', false);       // used when QR_CACHEABLE === true
119    define('QR_LOG_DIR', false);         // default error logs dir
120
121    define('QR_FIND_BEST_MASK', true);                                                          // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
122    define('QR_FIND_FROM_RANDOM', 2);                                                       // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
123    define('QR_DEFAULT_MASK', 2);                                                               // when QR_FIND_BEST_MASK === false
124
125    define('QR_PNG_MAXIMUM_SIZE',  1024);                                                       // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images
126
127
128
129
130//---- qrtools.php -----------------------------
131
132
133
134
135/*
136 * PHP QR Code encoder
137 *
138 * Toolset, handy and debug utilites.
139 *
140 * PHP QR Code is distributed under LGPL 3
141 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
142 *
143 * This library is free software; you can redistribute it and/or
144 * modify it under the terms of the GNU Lesser General Public
145 * License as published by the Free Software Foundation; either
146 * version 3 of the License, or any later version.
147 *
148 * This library is distributed in the hope that it will be useful,
149 * but WITHOUT ANY WARRANTY; without even the implied warranty of
150 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
151 * Lesser General Public License for more details.
152 *
153 * You should have received a copy of the GNU Lesser General Public
154 * License along with this library; if not, write to the Free Software
155 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
156 */
157
158    class QRtools {
159
160        //----------------------------------------------------------------------
161        public static function binarize($frame)
162        {
163            $len = count($frame);
164            foreach ($frame as &$frameLine) {
165
166                for($i=0; $i<$len; $i++) {
167                    $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
168                }
169            }
170
171            return $frame;
172        }
173
174        //----------------------------------------------------------------------
175        public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037')
176        {
177            $barcode_array = array();
178
179            if (!is_array($mode))
180                $mode = explode(',', $mode);
181
182            $eccLevel = 'L';
183
184            if (count($mode) > 1) {
185                $eccLevel = $mode[1];
186            }
187
188            $qrTab = QRcode::text($code, false, $eccLevel);
189            $size = count($qrTab);
190
191            $barcode_array['num_rows'] = $size;
192            $barcode_array['num_cols'] = $size;
193            $barcode_array['bcode'] = array();
194
195            foreach ($qrTab as $line) {
196                $arrAdd = array();
197                foreach(str_split($line) as $char)
198                    $arrAdd[] = ($char=='1')?1:0;
199                $barcode_array['bcode'][] = $arrAdd;
200            }
201
202            return $barcode_array;
203        }
204
205        //----------------------------------------------------------------------
206        public static function clearCache()
207        {
208            self::$frames = array();
209        }
210
211        //----------------------------------------------------------------------
212        public static function buildCache()
213        {
214			QRtools::markTime('before_build_cache');
215
216			$mask = new QRmask();
217            for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) {
218                $frame = QRspec::newFrame($a);
219                if (QR_IMAGE) {
220                    $fileName = QR_CACHE_DIR.'frame_'.$a.'.png';
221                    QRimage::png(self::binarize($frame), $fileName, 1, 0);
222                }
223
224				$width = count($frame);
225				$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
226				for ($maskNo=0; $maskNo<8; $maskNo++)
227					$mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true);
228            }
229
230			QRtools::markTime('after_build_cache');
231        }
232
233        //----------------------------------------------------------------------
234        public static function log($outfile, $err)
235        {
236            if (QR_LOG_DIR !== false) {
237                if ($err != '') {
238                    if ($outfile !== false) {
239                        file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
240                    } else {
241                        file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
242                    }
243                }
244            }
245        }
246
247        //----------------------------------------------------------------------
248        public static function dumpMask($frame)
249        {
250            $width = count($frame);
251            for($y=0;$y<$width;$y++) {
252                for($x=0;$x<$width;$x++) {
253                    echo ord($frame[$y][$x]).',';
254                }
255            }
256        }
257
258        //----------------------------------------------------------------------
259        public static function markTime($markerId)
260        {
261            list($usec, $sec) = explode(" ", microtime());
262            $time = ((float)$usec + (float)$sec);
263
264            if (!isset($GLOBALS['qr_time_bench']))
265                $GLOBALS['qr_time_bench'] = array();
266
267            $GLOBALS['qr_time_bench'][$markerId] = $time;
268        }
269
270        //----------------------------------------------------------------------
271        public static function timeBenchmark()
272        {
273            self::markTime('finish');
274
275            $lastTime = 0;
276            $startTime = 0;
277            $p = 0;
278
279            echo '<table cellpadding="3" cellspacing="1">
280                    <thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead>
281                    <tbody>';
282
283            foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
284                if ($p > 0) {
285                    echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime-$lastTime, 6).'s</td></tr>';
286                } else {
287                    $startTime = $thisTime;
288                }
289
290                $p++;
291                $lastTime = $thisTime;
292            }
293
294            echo '</tbody><tfoot>
295                <tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime-$startTime, 6).'s</td></tr>
296            </tfoot>
297            </table>';
298        }
299
300    }
301
302    //##########################################################################
303
304    QRtools::markTime('start');
305
306
307
308
309//---- qrspec.php -----------------------------
310
311
312
313
314/*
315 * PHP QR Code encoder
316 *
317 * QR Code specifications
318 *
319 * Based on libqrencode C library distributed under LGPL 2.1
320 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
321 *
322 * PHP QR Code is distributed under LGPL 3
323 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
324 *
325 * The following data / specifications are taken from
326 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
327 *  or
328 * "Automatic identification and data capture techniques --
329 *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
330 *
331 * This library is free software; you can redistribute it and/or
332 * modify it under the terms of the GNU Lesser General Public
333 * License as published by the Free Software Foundation; either
334 * version 3 of the License, or any later version.
335 *
336 * This library is distributed in the hope that it will be useful,
337 * but WITHOUT ANY WARRANTY; without even the implied warranty of
338 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
339 * Lesser General Public License for more details.
340 *
341 * You should have received a copy of the GNU Lesser General Public
342 * License along with this library; if not, write to the Free Software
343 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
344 */
345
346    define('QRSPEC_VERSION_MAX', 40);
347    define('QRSPEC_WIDTH_MAX',   177);
348
349    define('QRCAP_WIDTH',        0);
350    define('QRCAP_WORDS',        1);
351    define('QRCAP_REMINDER',     2);
352    define('QRCAP_EC',           3);
353
354    class QRspec {
355
356        public static $capacity = array(
357            array(  0,    0, 0, array(   0,    0,    0,    0)),
358            array( 21,   26, 0, array(   7,   10,   13,   17)), // 1
359            array( 25,   44, 7, array(  10,   16,   22,   28)),
360            array( 29,   70, 7, array(  15,   26,   36,   44)),
361            array( 33,  100, 7, array(  20,   36,   52,   64)),
362            array( 37,  134, 7, array(  26,   48,   72,   88)), // 5
363            array( 41,  172, 7, array(  36,   64,   96,  112)),
364            array( 45,  196, 0, array(  40,   72,  108,  130)),
365            array( 49,  242, 0, array(  48,   88,  132,  156)),
366            array( 53,  292, 0, array(  60,  110,  160,  192)),
367            array( 57,  346, 0, array(  72,  130,  192,  224)), //10
368            array( 61,  404, 0, array(  80,  150,  224,  264)),
369            array( 65,  466, 0, array(  96,  176,  260,  308)),
370            array( 69,  532, 0, array( 104,  198,  288,  352)),
371            array( 73,  581, 3, array( 120,  216,  320,  384)),
372            array( 77,  655, 3, array( 132,  240,  360,  432)), //15
373            array( 81,  733, 3, array( 144,  280,  408,  480)),
374            array( 85,  815, 3, array( 168,  308,  448,  532)),
375            array( 89,  901, 3, array( 180,  338,  504,  588)),
376            array( 93,  991, 3, array( 196,  364,  546,  650)),
377            array( 97, 1085, 3, array( 224,  416,  600,  700)), //20
378            array(101, 1156, 4, array( 224,  442,  644,  750)),
379            array(105, 1258, 4, array( 252,  476,  690,  816)),
380            array(109, 1364, 4, array( 270,  504,  750,  900)),
381            array(113, 1474, 4, array( 300,  560,  810,  960)),
382            array(117, 1588, 4, array( 312,  588,  870, 1050)), //25
383            array(121, 1706, 4, array( 336,  644,  952, 1110)),
384            array(125, 1828, 4, array( 360,  700, 1020, 1200)),
385            array(129, 1921, 3, array( 390,  728, 1050, 1260)),
386            array(133, 2051, 3, array( 420,  784, 1140, 1350)),
387            array(137, 2185, 3, array( 450,  812, 1200, 1440)), //30
388            array(141, 2323, 3, array( 480,  868, 1290, 1530)),
389            array(145, 2465, 3, array( 510,  924, 1350, 1620)),
390            array(149, 2611, 3, array( 540,  980, 1440, 1710)),
391            array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
392            array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35
393            array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
394            array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
395            array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
396            array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
397            array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40
398        );
399
400        //----------------------------------------------------------------------
401        public static function getDataLength($version, $level)
402        {
403            return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level];
404        }
405
406        //----------------------------------------------------------------------
407        public static function getECCLength($version, $level)
408        {
409            return self::$capacity[$version][QRCAP_EC][$level];
410        }
411
412        //----------------------------------------------------------------------
413        public static function getWidth($version)
414        {
415            return self::$capacity[$version][QRCAP_WIDTH];
416        }
417
418        //----------------------------------------------------------------------
419        public static function getRemainder($version)
420        {
421            return self::$capacity[$version][QRCAP_REMINDER];
422        }
423
424        //----------------------------------------------------------------------
425        public static function getMinimumVersion($size, $level)
426        {
427
428            for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) {
429                $words  = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level];
430                if($words >= $size)
431                    return $i;
432            }
433
434            return -1;
435        }
436
437        //######################################################################
438
439        public static $lengthTableBits = array(
440            array(10, 12, 14),
441            array( 9, 11, 13),
442            array( 8, 16, 16),
443            array( 8, 10, 12)
444        );
445
446        //----------------------------------------------------------------------
447        public static function lengthIndicator($mode, $version)
448        {
449            if ($mode == QR_MODE_STRUCTURE)
450                return 0;
451
452            if ($version <= 9) {
453                $l = 0;
454            } else if ($version <= 26) {
455                $l = 1;
456            } else {
457                $l = 2;
458            }
459
460            return self::$lengthTableBits[$mode][$l];
461        }
462
463        //----------------------------------------------------------------------
464        public static function maximumWords($mode, $version)
465        {
466            if($mode == QR_MODE_STRUCTURE)
467                return 3;
468
469            if($version <= 9) {
470                $l = 0;
471            } else if($version <= 26) {
472                $l = 1;
473            } else {
474                $l = 2;
475            }
476
477            $bits = self::$lengthTableBits[$mode][$l];
478            $words = (1 << $bits) - 1;
479
480            if($mode == QR_MODE_KANJI) {
481                $words *= 2; // the number of bytes is required
482            }
483
484            return $words;
485        }
486
487        // Error correction code -----------------------------------------------
488        // Table of the error correction code (Reed-Solomon block)
489        // See Table 12-16 (pp.30-36), JIS X0510:2004.
490
491        public static $eccTable = array(
492            array(array( 0,  0), array( 0,  0), array( 0,  0), array( 0,  0)),
493            array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)), // 1
494            array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)),
495            array(array( 1,  0), array( 1,  0), array( 2,  0), array( 2,  0)),
496            array(array( 1,  0), array( 2,  0), array( 2,  0), array( 4,  0)),
497            array(array( 1,  0), array( 2,  0), array( 2,  2), array( 2,  2)), // 5
498            array(array( 2,  0), array( 4,  0), array( 4,  0), array( 4,  0)),
499            array(array( 2,  0), array( 4,  0), array( 2,  4), array( 4,  1)),
500            array(array( 2,  0), array( 2,  2), array( 4,  2), array( 4,  2)),
501            array(array( 2,  0), array( 3,  2), array( 4,  4), array( 4,  4)),
502            array(array( 2,  2), array( 4,  1), array( 6,  2), array( 6,  2)), //10
503            array(array( 4,  0), array( 1,  4), array( 4,  4), array( 3,  8)),
504            array(array( 2,  2), array( 6,  2), array( 4,  6), array( 7,  4)),
505            array(array( 4,  0), array( 8,  1), array( 8,  4), array(12,  4)),
506            array(array( 3,  1), array( 4,  5), array(11,  5), array(11,  5)),
507            array(array( 5,  1), array( 5,  5), array( 5,  7), array(11,  7)), //15
508            array(array( 5,  1), array( 7,  3), array(15,  2), array( 3, 13)),
509            array(array( 1,  5), array(10,  1), array( 1, 15), array( 2, 17)),
510            array(array( 5,  1), array( 9,  4), array(17,  1), array( 2, 19)),
511            array(array( 3,  4), array( 3, 11), array(17,  4), array( 9, 16)),
512            array(array( 3,  5), array( 3, 13), array(15,  5), array(15, 10)), //20
513            array(array( 4,  4), array(17,  0), array(17,  6), array(19,  6)),
514            array(array( 2,  7), array(17,  0), array( 7, 16), array(34,  0)),
515            array(array( 4,  5), array( 4, 14), array(11, 14), array(16, 14)),
516            array(array( 6,  4), array( 6, 14), array(11, 16), array(30,  2)),
517            array(array( 8,  4), array( 8, 13), array( 7, 22), array(22, 13)), //25
518            array(array(10,  2), array(19,  4), array(28,  6), array(33,  4)),
519            array(array( 8,  4), array(22,  3), array( 8, 26), array(12, 28)),
520            array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)),
521            array(array( 7,  7), array(21,  7), array( 1, 37), array(19, 26)),
522            array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30
523            array(array(13,  3), array( 2, 29), array(42,  1), array(23, 28)),
524            array(array(17,  0), array(10, 23), array(10, 35), array(19, 35)),
525            array(array(17,  1), array(14, 21), array(29, 19), array(11, 46)),
526            array(array(13,  6), array(14, 23), array(44,  7), array(59,  1)),
527            array(array(12,  7), array(12, 26), array(39, 14), array(22, 41)), //35
528            array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
529            array(array(17,  4), array(29, 14), array(49, 10), array(24, 46)),
530            array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)),
531            array(array(20,  4), array(40,  7), array(43, 22), array(10, 67)),
532            array(array(19,  6), array(18, 31), array(34, 34), array(20, 61)),//40
533        );
534
535        //----------------------------------------------------------------------
536        // CACHEABLE!!!
537
538        public static function getEccSpec($version, $level, array &$spec)
539        {
540            if (count($spec) < 5) {
541                $spec = array(0,0,0,0,0);
542            }
543
544            $b1   = self::$eccTable[$version][$level][0];
545            $b2   = self::$eccTable[$version][$level][1];
546            $data = self::getDataLength($version, $level);
547            $ecc  = self::getECCLength($version, $level);
548
549            if($b2 == 0) {
550                $spec[0] = $b1;
551                $spec[1] = (int)($data / $b1);
552                $spec[2] = (int)($ecc / $b1);
553                $spec[3] = 0;
554                $spec[4] = 0;
555            } else {
556                $spec[0] = $b1;
557                $spec[1] = (int)($data / ($b1 + $b2));
558                $spec[2] = (int)($ecc  / ($b1 + $b2));
559                $spec[3] = $b2;
560                $spec[4] = $spec[1] + 1;
561            }
562        }
563
564        // Alignment pattern ---------------------------------------------------
565
566        // Positions of alignment patterns.
567        // This array includes only the second and the third position of the
568        // alignment patterns. Rest of them can be calculated from the distance
569        // between them.
570
571        // See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
572
573        public static $alignmentPattern = array(
574            array( 0,  0),
575            array( 0,  0), array(18,  0), array(22,  0), array(26,  0), array(30,  0), // 1- 5
576            array(34,  0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10
577            array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15
578            array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20
579            array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25
580            array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30
581            array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35
582            array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40
583        );
584
585
586        /** --------------------------------------------------------------------
587         * Put an alignment marker.
588         * @param frame
589         * @param width
590         * @param ox,oy center coordinate of the pattern
591         */
592        public static function putAlignmentMarker(array &$frame, $ox, $oy)
593        {
594            $finder = array(
595                "\xa1\xa1\xa1\xa1\xa1",
596                "\xa1\xa0\xa0\xa0\xa1",
597                "\xa1\xa0\xa1\xa0\xa1",
598                "\xa1\xa0\xa0\xa0\xa1",
599                "\xa1\xa1\xa1\xa1\xa1"
600            );
601
602            $yStart = $oy-2;
603            $xStart = $ox-2;
604
605            for($y=0; $y<5; $y++) {
606                QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]);
607            }
608        }
609
610        //----------------------------------------------------------------------
611        public static function putAlignmentPattern($version, &$frame, $width)
612        {
613            if($version < 2)
614                return;
615
616            $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
617            if($d < 0) {
618                $w = 2;
619            } else {
620                $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2);
621            }
622
623            if($w * $w - 3 == 1) {
624                $x = self::$alignmentPattern[$version][0];
625                $y = self::$alignmentPattern[$version][0];
626                self::putAlignmentMarker($frame, $x, $y);
627                return;
628            }
629
630            $cx = self::$alignmentPattern[$version][0];
631            for($x=1; $x<$w - 1; $x++) {
632                self::putAlignmentMarker($frame, 6, $cx);
633                self::putAlignmentMarker($frame, $cx,  6);
634                $cx += $d;
635            }
636
637            $cy = self::$alignmentPattern[$version][0];
638            for($y=0; $y<$w-1; $y++) {
639                $cx = self::$alignmentPattern[$version][0];
640                for($x=0; $x<$w-1; $x++) {
641                    self::putAlignmentMarker($frame, $cx, $cy);
642                    $cx += $d;
643                }
644                $cy += $d;
645            }
646        }
647
648        // Version information pattern -----------------------------------------
649
650		// Version information pattern (BCH coded).
651        // See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
652
653		// size: [QRSPEC_VERSION_MAX - 6]
654
655        public static $versionPattern = array(
656            0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
657            0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
658            0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
659            0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
660            0x27541, 0x28c69
661        );
662
663        //----------------------------------------------------------------------
664        public static function getVersionPattern($version)
665        {
666            if($version < 7 || $version > QRSPEC_VERSION_MAX)
667                return 0;
668
669            return self::$versionPattern[$version -7];
670        }
671
672        // Format information --------------------------------------------------
673        // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib)
674
675        public static $formatInfo = array(
676            array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
677            array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
678            array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed),
679            array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b)
680        );
681
682        public static function getFormatInfo($mask, $level)
683        {
684            if($mask < 0 || $mask > 7)
685                return 0;
686
687            if($level < 0 || $level > 3)
688                return 0;
689
690            return self::$formatInfo[$level][$mask];
691        }
692
693        // Frame ---------------------------------------------------------------
694        // Cache of initial frames.
695
696        public static $frames = array();
697
698        /** --------------------------------------------------------------------
699         * Put a finder pattern.
700         * @param frame
701         * @param width
702         * @param ox,oy upper-left coordinate of the pattern
703         */
704        public static function putFinderPattern(&$frame, $ox, $oy)
705        {
706            $finder = array(
707                "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
708                "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
709                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
710                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
711                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
712                "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
713                "\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
714            );
715
716            for($y=0; $y<7; $y++) {
717                QRstr::set($frame, $ox, $oy+$y, $finder[$y]);
718            }
719        }
720
721        //----------------------------------------------------------------------
722        public static function createFrame($version)
723        {
724            $width = self::$capacity[$version][QRCAP_WIDTH];
725            $frameLine = str_repeat ("\0", $width);
726            $frame = array_fill(0, $width, $frameLine);
727
728            // Finder pattern
729            self::putFinderPattern($frame, 0, 0);
730            self::putFinderPattern($frame, $width - 7, 0);
731            self::putFinderPattern($frame, 0, $width - 7);
732
733            // Separator
734            $yOffset = $width - 7;
735
736            for($y=0; $y<7; $y++) {
737                $frame[$y][7] = "\xc0";
738                $frame[$y][$width - 8] = "\xc0";
739                $frame[$yOffset][7] = "\xc0";
740                $yOffset++;
741            }
742
743            $setPattern = str_repeat("\xc0", 8);
744
745            QRstr::set($frame, 0, 7, $setPattern);
746            QRstr::set($frame, $width-8, 7, $setPattern);
747            QRstr::set($frame, 0, $width - 8, $setPattern);
748
749            // Format info
750            $setPattern = str_repeat("\x84", 9);
751            QRstr::set($frame, 0, 8, $setPattern);
752            QRstr::set($frame, $width - 8, 8, $setPattern, 8);
753
754            $yOffset = $width - 8;
755
756            for($y=0; $y<8; $y++,$yOffset++) {
757                $frame[$y][8] = "\x84";
758                $frame[$yOffset][8] = "\x84";
759            }
760
761            // Timing pattern
762
763            for($i=1; $i<$width-15; $i++) {
764                $frame[6][7+$i] = chr(0x90 | ($i & 1));
765                $frame[7+$i][6] = chr(0x90 | ($i & 1));
766            }
767
768            // Alignment pattern
769            self::putAlignmentPattern($version, $frame, $width);
770
771            // Version information
772            if($version >= 7) {
773                $vinf = self::getVersionPattern($version);
774
775                $v = $vinf;
776
777                for($x=0; $x<6; $x++) {
778                    for($y=0; $y<3; $y++) {
779                        $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1));
780                        $v = $v >> 1;
781                    }
782                }
783
784                $v = $vinf;
785                for($y=0; $y<6; $y++) {
786                    for($x=0; $x<3; $x++) {
787                        $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1));
788                        $v = $v >> 1;
789                    }
790                }
791            }
792
793            // and a little bit...
794            $frame[$width - 8][8] = "\x81";
795
796            return $frame;
797        }
798
799        //----------------------------------------------------------------------
800        public static function debug($frame, $binary_mode = false)
801        {
802            if ($binary_mode) {
803
804                    foreach ($frame as &$frameLine) {
805                        $frameLine = join('<span class="m">&nbsp;&nbsp;</span>', explode('0', $frameLine));
806                        $frameLine = join('&#9608;&#9608;', explode('1', $frameLine));
807                    }
808
809                    ?>
810                <style>
811                    .m { background-color: white; }
812                </style>
813                <?php
814                    echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
815                    echo join("<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $frame);
816                    echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
817
818            } else {
819
820                foreach ($frame as &$frameLine) {
821                    $frameLine = join('<span class="m">&nbsp;</span>',  explode("\xc0", $frameLine));
822                    $frameLine = join('<span class="m">&#9618;</span>', explode("\xc1", $frameLine));
823                    $frameLine = join('<span class="p">&nbsp;</span>',  explode("\xa0", $frameLine));
824                    $frameLine = join('<span class="p">&#9618;</span>', explode("\xa1", $frameLine));
825                    $frameLine = join('<span class="s">&#9671;</span>', explode("\x84", $frameLine)); //format 0
826                    $frameLine = join('<span class="s">&#9670;</span>', explode("\x85", $frameLine)); //format 1
827                    $frameLine = join('<span class="x">&#9762;</span>', explode("\x81", $frameLine)); //special bit
828                    $frameLine = join('<span class="c">&nbsp;</span>',  explode("\x90", $frameLine)); //clock 0
829                    $frameLine = join('<span class="c">&#9719;</span>', explode("\x91", $frameLine)); //clock 1
830                    $frameLine = join('<span class="f">&nbsp;</span>',  explode("\x88", $frameLine)); //version
831                    $frameLine = join('<span class="f">&#9618;</span>', explode("\x89", $frameLine)); //version
832                    $frameLine = join('&#9830;', explode("\x01", $frameLine));
833                    $frameLine = join('&#8901;', explode("\0", $frameLine));
834                }
835
836                ?>
837                <style>
838                    .p { background-color: yellow; }
839                    .m { background-color: #00FF00; }
840                    .s { background-color: #FF0000; }
841                    .c { background-color: aqua; }
842                    .x { background-color: pink; }
843                    .f { background-color: gold; }
844                </style>
845                <?php
846                echo "<pre><tt>";
847                echo join("<br/ >", $frame);
848                echo "</tt></pre>";
849
850            }
851        }
852
853        //----------------------------------------------------------------------
854        public static function serial($frame)
855        {
856            return gzcompress(join("\n", $frame), 9);
857        }
858
859        //----------------------------------------------------------------------
860        public static function unserial($code)
861        {
862            return explode("\n", gzuncompress($code));
863        }
864
865        //----------------------------------------------------------------------
866        public static function newFrame($version)
867        {
868            if($version < 1 || $version > QRSPEC_VERSION_MAX)
869                return null;
870
871            if(!isset(self::$frames[$version])) {
872
873                $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat';
874
875                if (QR_CACHEABLE) {
876                    if (file_exists($fileName)) {
877                        self::$frames[$version] = self::unserial(file_get_contents($fileName));
878                    } else {
879                        self::$frames[$version] = self::createFrame($version);
880                        file_put_contents($fileName, self::serial(self::$frames[$version]));
881                    }
882                } else {
883                    self::$frames[$version] = self::createFrame($version);
884                }
885            }
886
887            if(is_null(self::$frames[$version]))
888                return null;
889
890            return self::$frames[$version];
891        }
892
893        //----------------------------------------------------------------------
894        public static function rsBlockNum($spec)     { return $spec[0] + $spec[3]; }
895        public static function rsBlockNum1($spec)    { return $spec[0]; }
896        public static function rsDataCodes1($spec)   { return $spec[1]; }
897        public static function rsEccCodes1($spec)    { return $spec[2]; }
898        public static function rsBlockNum2($spec)    { return $spec[3]; }
899        public static function rsDataCodes2($spec)   { return $spec[4]; }
900        public static function rsEccCodes2($spec)    { return $spec[2]; }
901        public static function rsDataLength($spec)   { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]);    }
902        public static function rsEccLength($spec)    { return ($spec[0] + $spec[3]) * $spec[2]; }
903
904    }
905
906
907
908//---- qrimage.php -----------------------------
909
910
911
912
913/*
914 * PHP QR Code encoder
915 *
916 * Image output of code using GD2
917 *
918 * PHP QR Code is distributed under LGPL 3
919 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
920 *
921 * This library is free software; you can redistribute it and/or
922 * modify it under the terms of the GNU Lesser General Public
923 * License as published by the Free Software Foundation; either
924 * version 3 of the License, or any later version.
925 *
926 * This library is distributed in the hope that it will be useful,
927 * but WITHOUT ANY WARRANTY; without even the implied warranty of
928 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
929 * Lesser General Public License for more details.
930 *
931 * You should have received a copy of the GNU Lesser General Public
932 * License along with this library; if not, write to the Free Software
933 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
934 */
935
936    define('QR_IMAGE', true);
937
938    class QRimage {
939
940        //----------------------------------------------------------------------
941        public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE)
942        {
943            $image = self::image($frame, $pixelPerPoint, $outerFrame);
944
945            if ($filename === false) {
946                Header("Content-type: image/png");
947                ImagePng($image);
948            } else {
949                if($saveandprint===TRUE){
950                    ImagePng($image, $filename);
951                    header("Content-type: image/png");
952                    ImagePng($image);
953                }else{
954                    ImagePng($image, $filename);
955                }
956            }
957
958            ImageDestroy($image);
959        }
960
961        //----------------------------------------------------------------------
962        public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85)
963        {
964            $image = self::image($frame, $pixelPerPoint, $outerFrame);
965
966            if ($filename === false) {
967                Header("Content-type: image/jpeg");
968                ImageJpeg($image, null, $q);
969            } else {
970                ImageJpeg($image, $filename, $q);
971            }
972
973            ImageDestroy($image);
974        }
975
976        //----------------------------------------------------------------------
977        private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4)
978        {
979            $h = count($frame);
980            $w = strlen($frame[0]);
981
982            $imgW = $w + 2*$outerFrame;
983            $imgH = $h + 2*$outerFrame;
984
985            $base_image =ImageCreate($imgW, $imgH);
986
987            $col[0] = ImageColorAllocate($base_image,255,255,255);
988            $col[1] = ImageColorAllocate($base_image,0,0,0);
989
990            imagefill($base_image, 0, 0, $col[0]);
991
992            for($y=0; $y<$h; $y++) {
993                for($x=0; $x<$w; $x++) {
994                    if ($frame[$y][$x] == '1') {
995                        ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]);
996                    }
997                }
998            }
999
1000            $target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint);
1001            ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH);
1002            ImageDestroy($base_image);
1003
1004            return $target_image;
1005        }
1006    }
1007
1008
1009
1010//---- qrinput.php -----------------------------
1011
1012
1013
1014
1015/*
1016 * PHP QR Code encoder
1017 *
1018 * Input encoding class
1019 *
1020 * Based on libqrencode C library distributed under LGPL 2.1
1021 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
1022 *
1023 * PHP QR Code is distributed under LGPL 3
1024 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
1025 *
1026 * This library is free software; you can redistribute it and/or
1027 * modify it under the terms of the GNU Lesser General Public
1028 * License as published by the Free Software Foundation; either
1029 * version 3 of the License, or any later version.
1030 *
1031 * This library is distributed in the hope that it will be useful,
1032 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1033 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1034 * Lesser General Public License for more details.
1035 *
1036 * You should have received a copy of the GNU Lesser General Public
1037 * License along with this library; if not, write to the Free Software
1038 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1039 */
1040
1041    define('STRUCTURE_HEADER_BITS',  20);
1042    define('MAX_STRUCTURED_SYMBOLS', 16);
1043
1044    class QRinputItem {
1045
1046        public $mode;
1047        public $size;
1048        public $data;
1049        public $bstream;
1050
1051        public function __construct($mode, $size, $data, $bstream = null)
1052        {
1053            $setData = array_slice($data, 0, $size);
1054
1055            if (count($setData) < $size) {
1056                $setData = array_merge($setData, array_fill(0,$size-count($setData),0));
1057            }
1058
1059            if(!QRinput::check($mode, $size, $setData)) {
1060                throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData));
1061                return null;
1062            }
1063
1064            $this->mode = $mode;
1065            $this->size = $size;
1066            $this->data = $setData;
1067            $this->bstream = $bstream;
1068        }
1069
1070        //----------------------------------------------------------------------
1071        public function encodeModeNum($version)
1072        {
1073            try {
1074
1075                $words = (int)($this->size / 3);
1076                $bs = new QRbitstream();
1077
1078                $val = 0x1;
1079                $bs->appendNum(4, $val);
1080                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size);
1081
1082                for($i=0; $i<$words; $i++) {
1083                    $val  = (ord($this->data[$i*3  ]) - ord('0')) * 100;
1084                    $val += (ord($this->data[$i*3+1]) - ord('0')) * 10;
1085                    $val += (ord($this->data[$i*3+2]) - ord('0'));
1086                    $bs->appendNum(10, $val);
1087                }
1088
1089                if($this->size - $words * 3 == 1) {
1090                    $val = ord($this->data[$words*3]) - ord('0');
1091                    $bs->appendNum(4, $val);
1092                } else if($this->size - $words * 3 == 2) {
1093                    $val  = (ord($this->data[$words*3  ]) - ord('0')) * 10;
1094                    $val += (ord($this->data[$words*3+1]) - ord('0'));
1095                    $bs->appendNum(7, $val);
1096                }
1097
1098                $this->bstream = $bs;
1099                return 0;
1100
1101            } catch (Exception $e) {
1102                return -1;
1103            }
1104        }
1105
1106        //----------------------------------------------------------------------
1107        public function encodeModeAn($version)
1108        {
1109            try {
1110                $words = (int)($this->size / 2);
1111                $bs = new QRbitstream();
1112
1113                $bs->appendNum(4, 0x02);
1114                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size);
1115
1116                for($i=0; $i<$words; $i++) {
1117                    $val  = (int)QRinput::lookAnTable(ord($this->data[$i*2  ])) * 45;
1118                    $val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1]));
1119
1120                    $bs->appendNum(11, $val);
1121                }
1122
1123                if($this->size & 1) {
1124                    $val = QRinput::lookAnTable(ord($this->data[$words * 2]));
1125                    $bs->appendNum(6, $val);
1126                }
1127
1128                $this->bstream = $bs;
1129                return 0;
1130
1131            } catch (Exception $e) {
1132                return -1;
1133            }
1134        }
1135
1136        //----------------------------------------------------------------------
1137        public function encodeMode8($version)
1138        {
1139            try {
1140                $bs = new QRbitstream();
1141
1142                $bs->appendNum(4, 0x4);
1143                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size);
1144
1145                for($i=0; $i<$this->size; $i++) {
1146                    $bs->appendNum(8, ord($this->data[$i]));
1147                }
1148
1149                $this->bstream = $bs;
1150                return 0;
1151
1152            } catch (Exception $e) {
1153                return -1;
1154            }
1155        }
1156
1157        //----------------------------------------------------------------------
1158        public function encodeModeKanji($version)
1159        {
1160            try {
1161
1162                $bs = new QRbitrtream();
1163
1164                $bs->appendNum(4, 0x8);
1165                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2));
1166
1167                for($i=0; $i<$this->size; $i+=2) {
1168                    $val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]);
1169                    if($val <= 0x9ffc) {
1170                        $val -= 0x8140;
1171                    } else {
1172                        $val -= 0xc140;
1173                    }
1174
1175                    $h = ($val >> 8) * 0xc0;
1176                    $val = ($val & 0xff) + $h;
1177
1178                    $bs->appendNum(13, $val);
1179                }
1180
1181                $this->bstream = $bs;
1182                return 0;
1183
1184            } catch (Exception $e) {
1185                return -1;
1186            }
1187        }
1188
1189        //----------------------------------------------------------------------
1190        public function encodeModeStructure()
1191        {
1192            try {
1193                $bs =  new QRbitstream();
1194
1195                $bs->appendNum(4, 0x03);
1196                $bs->appendNum(4, ord($this->data[1]) - 1);
1197                $bs->appendNum(4, ord($this->data[0]) - 1);
1198                $bs->appendNum(8, ord($this->data[2]));
1199
1200                $this->bstream = $bs;
1201                return 0;
1202
1203            } catch (Exception $e) {
1204                return -1;
1205            }
1206        }
1207
1208        //----------------------------------------------------------------------
1209        public function estimateBitStreamSizeOfEntry($version)
1210        {
1211            $bits = 0;
1212
1213            if($version == 0)
1214                $version = 1;
1215
1216            switch($this->mode) {
1217                case QR_MODE_NUM:        $bits = QRinput::estimateBitsModeNum($this->size);    break;
1218                case QR_MODE_AN:        $bits = QRinput::estimateBitsModeAn($this->size);    break;
1219                case QR_MODE_8:            $bits = QRinput::estimateBitsMode8($this->size);    break;
1220                case QR_MODE_KANJI:        $bits = QRinput::estimateBitsModeKanji($this->size);break;
1221                case QR_MODE_STRUCTURE:    return STRUCTURE_HEADER_BITS;
1222                default:
1223                    return 0;
1224            }
1225
1226            $l = QRspec::lengthIndicator($this->mode, $version);
1227            $m = 1 << $l;
1228            $num = (int)(($this->size + $m - 1) / $m);
1229
1230            $bits += $num * (4 + $l);
1231
1232            return $bits;
1233        }
1234
1235        //----------------------------------------------------------------------
1236        public function encodeBitStream($version)
1237        {
1238            try {
1239
1240                unset($this->bstream);
1241                $words = QRspec::maximumWords($this->mode, $version);
1242
1243                if($this->size > $words) {
1244
1245                    $st1 = new QRinputItem($this->mode, $words, $this->data);
1246                    $st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words));
1247
1248                    $st1->encodeBitStream($version);
1249                    $st2->encodeBitStream($version);
1250
1251                    $this->bstream = new QRbitstream();
1252                    $this->bstream->append($st1->bstream);
1253                    $this->bstream->append($st2->bstream);
1254
1255                    unset($st1);
1256                    unset($st2);
1257
1258                } else {
1259
1260                    $ret = 0;
1261
1262                    switch($this->mode) {
1263                        case QR_MODE_NUM:        $ret = $this->encodeModeNum($version);    break;
1264                        case QR_MODE_AN:        $ret = $this->encodeModeAn($version);    break;
1265                        case QR_MODE_8:            $ret = $this->encodeMode8($version);    break;
1266                        case QR_MODE_KANJI:        $ret = $this->encodeModeKanji($version);break;
1267                        case QR_MODE_STRUCTURE:    $ret = $this->encodeModeStructure();    break;
1268
1269                        default:
1270                            break;
1271                    }
1272
1273                    if($ret < 0)
1274                        return -1;
1275                }
1276
1277                return $this->bstream->size();
1278
1279            } catch (Exception $e) {
1280                return -1;
1281            }
1282        }
1283    };
1284
1285    //##########################################################################
1286
1287    class QRinput {
1288
1289        public $items;
1290
1291        private $version;
1292        private $level;
1293
1294        //----------------------------------------------------------------------
1295        public function __construct($version = 0, $level = QR_ECLEVEL_L)
1296        {
1297            if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) {
1298                throw new Exception('Invalid version no');
1299                return NULL;
1300            }
1301
1302            $this->version = $version;
1303            $this->level = $level;
1304        }
1305
1306        //----------------------------------------------------------------------
1307        public function getVersion()
1308        {
1309            return $this->version;
1310        }
1311
1312        //----------------------------------------------------------------------
1313        public function setVersion($version)
1314        {
1315            if($version < 0 || $version > QRSPEC_VERSION_MAX) {
1316                throw new Exception('Invalid version no');
1317                return -1;
1318            }
1319
1320            $this->version = $version;
1321
1322            return 0;
1323        }
1324
1325        //----------------------------------------------------------------------
1326        public function getErrorCorrectionLevel()
1327        {
1328            return $this->level;
1329        }
1330
1331        //----------------------------------------------------------------------
1332        public function setErrorCorrectionLevel($level)
1333        {
1334            if($level > QR_ECLEVEL_H) {
1335                throw new Exception('Invalid ECLEVEL');
1336                return -1;
1337            }
1338
1339            $this->level = $level;
1340
1341            return 0;
1342        }
1343
1344        //----------------------------------------------------------------------
1345        public function appendEntry(QRinputItem $entry)
1346        {
1347            $this->items[] = $entry;
1348        }
1349
1350        //----------------------------------------------------------------------
1351        public function append($mode, $size, $data)
1352        {
1353            try {
1354                $entry = new QRinputItem($mode, $size, $data);
1355                $this->items[] = $entry;
1356                return 0;
1357            } catch (Exception $e) {
1358                return -1;
1359            }
1360        }
1361
1362        //----------------------------------------------------------------------
1363
1364        public function insertStructuredAppendHeader($size, $index, $parity)
1365        {
1366            if( $size > MAX_STRUCTURED_SYMBOLS ) {
1367                throw new Exception('insertStructuredAppendHeader wrong size');
1368            }
1369
1370            if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) {
1371                throw new Exception('insertStructuredAppendHeader wrong index');
1372            }
1373
1374            $buf = array($size, $index, $parity);
1375
1376            try {
1377                $entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf);
1378                array_unshift($this->items, $entry);
1379                return 0;
1380            } catch (Exception $e) {
1381                return -1;
1382            }
1383        }
1384
1385        //----------------------------------------------------------------------
1386        public function calcParity()
1387        {
1388            $parity = 0;
1389
1390            foreach($this->items as $item) {
1391                if($item->mode != QR_MODE_STRUCTURE) {
1392                    for($i=$item->size-1; $i>=0; $i--) {
1393                        $parity ^= $item->data[$i];
1394                    }
1395                }
1396            }
1397
1398            return $parity;
1399        }
1400
1401        //----------------------------------------------------------------------
1402        public static function checkModeNum($size, $data)
1403        {
1404            for($i=0; $i<$size; $i++) {
1405                if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){
1406                    return false;
1407                }
1408            }
1409
1410            return true;
1411        }
1412
1413        //----------------------------------------------------------------------
1414        public static function estimateBitsModeNum($size)
1415        {
1416            $w = (int)$size / 3;
1417            $bits = $w * 10;
1418
1419            switch($size - $w * 3) {
1420                case 1:
1421                    $bits += 4;
1422                    break;
1423                case 2:
1424                    $bits += 7;
1425                    break;
1426                default:
1427                    break;
1428            }
1429
1430            return $bits;
1431        }
1432
1433        //----------------------------------------------------------------------
1434        public static $anTable = array(
1435            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1436            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1437            36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
1438             0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 44, -1, -1, -1, -1, -1,
1439            -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1440            25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
1441            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1442            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1443        );
1444
1445        //----------------------------------------------------------------------
1446        public static function lookAnTable($c)
1447        {
1448            return (($c > 127)?-1:self::$anTable[$c]);
1449        }
1450
1451        //----------------------------------------------------------------------
1452        public static function checkModeAn($size, $data)
1453        {
1454            for($i=0; $i<$size; $i++) {
1455                if (self::lookAnTable(ord($data[$i])) == -1) {
1456                    return false;
1457                }
1458            }
1459
1460            return true;
1461        }
1462
1463        //----------------------------------------------------------------------
1464        public static function estimateBitsModeAn($size)
1465        {
1466            $w = (int)($size / 2);
1467            $bits = $w * 11;
1468
1469            if($size & 1) {
1470                $bits += 6;
1471            }
1472
1473            return $bits;
1474        }
1475
1476        //----------------------------------------------------------------------
1477        public static function estimateBitsMode8($size)
1478        {
1479            return $size * 8;
1480        }
1481
1482        //----------------------------------------------------------------------
1483        public function estimateBitsModeKanji($size)
1484        {
1485            return (int)(($size / 2) * 13);
1486        }
1487
1488        //----------------------------------------------------------------------
1489        public static function checkModeKanji($size, $data)
1490        {
1491            if($size & 1)
1492                return false;
1493
1494            for($i=0; $i<$size; $i+=2) {
1495                $val = (ord($data[$i]) << 8) | ord($data[$i+1]);
1496                if( $val < 0x8140
1497                || ($val > 0x9ffc && $val < 0xe040)
1498                || $val > 0xebbf) {
1499                    return false;
1500                }
1501            }
1502
1503            return true;
1504        }
1505
1506        /***********************************************************************
1507         * Validation
1508         **********************************************************************/
1509
1510        public static function check($mode, $size, $data)
1511        {
1512            if($size <= 0)
1513                return false;
1514
1515            switch($mode) {
1516                case QR_MODE_NUM:       return self::checkModeNum($size, $data);   break;
1517                case QR_MODE_AN:        return self::checkModeAn($size, $data);    break;
1518                case QR_MODE_KANJI:     return self::checkModeKanji($size, $data); break;
1519                case QR_MODE_8:         return true; break;
1520                case QR_MODE_STRUCTURE: return true; break;
1521
1522                default:
1523                    break;
1524            }
1525
1526            return false;
1527        }
1528
1529
1530        //----------------------------------------------------------------------
1531        public function estimateBitStreamSize($version)
1532        {
1533            $bits = 0;
1534
1535            foreach($this->items as $item) {
1536                $bits += $item->estimateBitStreamSizeOfEntry($version);
1537            }
1538
1539            return $bits;
1540        }
1541
1542        //----------------------------------------------------------------------
1543        public function estimateVersion()
1544        {
1545            $version = 0;
1546            $prev = 0;
1547            do {
1548                $prev = $version;
1549                $bits = $this->estimateBitStreamSize($prev);
1550                $version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
1551                if ($version < 0) {
1552                    return -1;
1553                }
1554            } while ($version > $prev);
1555
1556            return $version;
1557        }
1558
1559        //----------------------------------------------------------------------
1560        public static function lengthOfCode($mode, $version, $bits)
1561        {
1562            $payload = $bits - 4 - QRspec::lengthIndicator($mode, $version);
1563            switch($mode) {
1564                case QR_MODE_NUM:
1565                    $chunks = (int)($payload / 10);
1566                    $remain = $payload - $chunks * 10;
1567                    $size = $chunks * 3;
1568                    if($remain >= 7) {
1569                        $size += 2;
1570                    } else if($remain >= 4) {
1571                        $size += 1;
1572                    }
1573                    break;
1574                case QR_MODE_AN:
1575                    $chunks = (int)($payload / 11);
1576                    $remain = $payload - $chunks * 11;
1577                    $size = $chunks * 2;
1578                    if($remain >= 6)
1579                        $size++;
1580                    break;
1581                case QR_MODE_8:
1582                    $size = (int)($payload / 8);
1583                    break;
1584                case QR_MODE_KANJI:
1585                    $size = (int)(($payload / 13) * 2);
1586                    break;
1587                case QR_MODE_STRUCTURE:
1588                    $size = (int)($payload / 8);
1589                    break;
1590                default:
1591                    $size = 0;
1592                    break;
1593            }
1594
1595            $maxsize = QRspec::maximumWords($mode, $version);
1596            if($size < 0) $size = 0;
1597            if($size > $maxsize) $size = $maxsize;
1598
1599            return $size;
1600        }
1601
1602        //----------------------------------------------------------------------
1603        public function createBitStream()
1604        {
1605            $total = 0;
1606
1607            foreach($this->items as $item) {
1608                $bits = $item->encodeBitStream($this->version);
1609
1610                if($bits < 0)
1611                    return -1;
1612
1613                $total += $bits;
1614            }
1615
1616            return $total;
1617        }
1618
1619        //----------------------------------------------------------------------
1620        public function convertData()
1621        {
1622            $ver = $this->estimateVersion();
1623            if($ver > $this->getVersion()) {
1624                $this->setVersion($ver);
1625            }
1626
1627            for(;;) {
1628                $bits = $this->createBitStream();
1629
1630                if($bits < 0)
1631                    return -1;
1632
1633                $ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
1634                if($ver < 0) {
1635                    throw new Exception('WRONG VERSION');
1636                    return -1;
1637                } else if($ver > $this->getVersion()) {
1638                    $this->setVersion($ver);
1639                } else {
1640                    break;
1641                }
1642            }
1643
1644            return 0;
1645        }
1646
1647        //----------------------------------------------------------------------
1648        public function appendPaddingBit(&$bstream)
1649        {
1650            $bits = $bstream->size();
1651            $maxwords = QRspec::getDataLength($this->version, $this->level);
1652            $maxbits = $maxwords * 8;
1653
1654            if ($maxbits == $bits) {
1655                return 0;
1656            }
1657
1658            if ($maxbits - $bits < 5) {
1659                return $bstream->appendNum($maxbits - $bits, 0);
1660            }
1661
1662            $bits += 4;
1663            $words = (int)(($bits + 7) / 8);
1664
1665            $padding = new QRbitstream();
1666            $ret = $padding->appendNum($words * 8 - $bits + 4, 0);
1667
1668            if($ret < 0)
1669                return $ret;
1670
1671            $padlen = $maxwords - $words;
1672
1673            if($padlen > 0) {
1674
1675                $padbuf = array();
1676                for($i=0; $i<$padlen; $i++) {
1677                    $padbuf[$i] = ($i&1)?0x11:0xec;
1678                }
1679
1680                $ret = $padding->appendBytes($padlen, $padbuf);
1681
1682                if($ret < 0)
1683                    return $ret;
1684
1685            }
1686
1687            $ret = $bstream->append($padding);
1688
1689            return $ret;
1690        }
1691
1692        //----------------------------------------------------------------------
1693        public function mergeBitStream()
1694        {
1695            if($this->convertData() < 0) {
1696                return null;
1697            }
1698
1699            $bstream = new QRbitstream();
1700
1701            foreach($this->items as $item) {
1702                $ret = $bstream->append($item->bstream);
1703                if($ret < 0) {
1704                    return null;
1705                }
1706            }
1707
1708            return $bstream;
1709        }
1710
1711        //----------------------------------------------------------------------
1712        public function getBitStream()
1713        {
1714
1715            $bstream = $this->mergeBitStream();
1716
1717            if($bstream == null) {
1718                return null;
1719            }
1720
1721            $ret = $this->appendPaddingBit($bstream);
1722            if($ret < 0) {
1723                return null;
1724            }
1725
1726            return $bstream;
1727        }
1728
1729        //----------------------------------------------------------------------
1730        public function getByteStream()
1731        {
1732            $bstream = $this->getBitStream();
1733            if($bstream == null) {
1734                return null;
1735            }
1736
1737            return $bstream->toByte();
1738        }
1739    }
1740
1741
1742
1743
1744
1745
1746//---- qrbitstream.php -----------------------------
1747
1748
1749
1750
1751/*
1752 * PHP QR Code encoder
1753 *
1754 * Bitstream class
1755 *
1756 * Based on libqrencode C library distributed under LGPL 2.1
1757 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
1758 *
1759 * PHP QR Code is distributed under LGPL 3
1760 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
1761 *
1762 * This library is free software; you can redistribute it and/or
1763 * modify it under the terms of the GNU Lesser General Public
1764 * License as published by the Free Software Foundation; either
1765 * version 3 of the License, or any later version.
1766 *
1767 * This library is distributed in the hope that it will be useful,
1768 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1769 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1770 * Lesser General Public License for more details.
1771 *
1772 * You should have received a copy of the GNU Lesser General Public
1773 * License along with this library; if not, write to the Free Software
1774 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1775 */
1776
1777    class QRbitstream {
1778
1779        public $data = array();
1780
1781        //----------------------------------------------------------------------
1782        public function size()
1783        {
1784            return count($this->data);
1785        }
1786
1787        //----------------------------------------------------------------------
1788        public function allocate($setLength)
1789        {
1790            $this->data = array_fill(0, $setLength, 0);
1791            return 0;
1792        }
1793
1794        //----------------------------------------------------------------------
1795        public static function newFromNum($bits, $num)
1796        {
1797            $bstream = new QRbitstream();
1798            $bstream->allocate($bits);
1799
1800            $mask = 1 << ($bits - 1);
1801            for($i=0; $i<$bits; $i++) {
1802                if($num & $mask) {
1803                    $bstream->data[$i] = 1;
1804                } else {
1805                    $bstream->data[$i] = 0;
1806                }
1807                $mask = $mask >> 1;
1808            }
1809
1810            return $bstream;
1811        }
1812
1813        //----------------------------------------------------------------------
1814        public static function newFromBytes($size, $data)
1815        {
1816            $bstream = new QRbitstream();
1817            $bstream->allocate($size * 8);
1818            $p=0;
1819
1820            for($i=0; $i<$size; $i++) {
1821                $mask = 0x80;
1822                for($j=0; $j<8; $j++) {
1823                    if($data[$i] & $mask) {
1824                        $bstream->data[$p] = 1;
1825                    } else {
1826                        $bstream->data[$p] = 0;
1827                    }
1828                    $p++;
1829                    $mask = $mask >> 1;
1830                }
1831            }
1832
1833            return $bstream;
1834        }
1835
1836        //----------------------------------------------------------------------
1837        public function append(QRbitstream $arg)
1838        {
1839            if (is_null($arg)) {
1840                return -1;
1841            }
1842
1843            if($arg->size() == 0) {
1844                return 0;
1845            }
1846
1847            if($this->size() == 0) {
1848                $this->data = $arg->data;
1849                return 0;
1850            }
1851
1852            $this->data = array_values(array_merge($this->data, $arg->data));
1853
1854            return 0;
1855        }
1856
1857        //----------------------------------------------------------------------
1858        public function appendNum($bits, $num)
1859        {
1860            if ($bits == 0)
1861                return 0;
1862
1863            $b = QRbitstream::newFromNum($bits, $num);
1864
1865            if(is_null($b))
1866                return -1;
1867
1868            $ret = $this->append($b);
1869            unset($b);
1870
1871            return $ret;
1872        }
1873
1874        //----------------------------------------------------------------------
1875        public function appendBytes($size, $data)
1876        {
1877            if ($size == 0)
1878                return 0;
1879
1880            $b = QRbitstream::newFromBytes($size, $data);
1881
1882            if(is_null($b))
1883                return -1;
1884
1885            $ret = $this->append($b);
1886            unset($b);
1887
1888            return $ret;
1889        }
1890
1891        //----------------------------------------------------------------------
1892        public function toByte()
1893        {
1894
1895            $size = $this->size();
1896
1897            if($size == 0) {
1898                return array();
1899            }
1900
1901            $data = array_fill(0, (int)(($size + 7) / 8), 0);
1902            $bytes = (int)($size / 8);
1903
1904            $p = 0;
1905
1906            for($i=0; $i<$bytes; $i++) {
1907                $v = 0;
1908                for($j=0; $j<8; $j++) {
1909                    $v = $v << 1;
1910                    $v |= $this->data[$p];
1911                    $p++;
1912                }
1913                $data[$i] = $v;
1914            }
1915
1916            if($size & 7) {
1917                $v = 0;
1918                for($j=0; $j<($size & 7); $j++) {
1919                    $v = $v << 1;
1920                    $v |= $this->data[$p];
1921                    $p++;
1922                }
1923                $data[$bytes] = $v;
1924            }
1925
1926            return $data;
1927        }
1928
1929    }
1930
1931
1932
1933
1934//---- qrsplit.php -----------------------------
1935
1936
1937
1938
1939/*
1940 * PHP QR Code encoder
1941 *
1942 * Input splitting classes
1943 *
1944 * Based on libqrencode C library distributed under LGPL 2.1
1945 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
1946 *
1947 * PHP QR Code is distributed under LGPL 3
1948 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
1949 *
1950 * The following data / specifications are taken from
1951 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
1952 *  or
1953 * "Automatic identification and data capture techniques --
1954 *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
1955 *
1956 * This library is free software; you can redistribute it and/or
1957 * modify it under the terms of the GNU Lesser General Public
1958 * License as published by the Free Software Foundation; either
1959 * version 3 of the License, or any later version.
1960 *
1961 * This library is distributed in the hope that it will be useful,
1962 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1963 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1964 * Lesser General Public License for more details.
1965 *
1966 * You should have received a copy of the GNU Lesser General Public
1967 * License along with this library; if not, write to the Free Software
1968 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1969 */
1970    class QRsplit {
1971
1972        public $dataStr = '';
1973        public $input;
1974        public $modeHint;
1975
1976        //----------------------------------------------------------------------
1977        public function __construct($dataStr, $input, $modeHint)
1978        {
1979            $this->dataStr  = $dataStr;
1980            $this->input    = $input;
1981            $this->modeHint = $modeHint;
1982        }
1983
1984        //----------------------------------------------------------------------
1985        public static function isdigitat($str, $pos)
1986        {
1987            if ($pos >= strlen($str))
1988                return false;
1989
1990            return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
1991        }
1992
1993        //----------------------------------------------------------------------
1994        public static function isalnumat($str, $pos)
1995        {
1996            if ($pos >= strlen($str))
1997                return false;
1998
1999            return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
2000        }
2001
2002        //----------------------------------------------------------------------
2003        public function identifyMode($pos)
2004        {
2005            if ($pos >= strlen($this->dataStr))
2006                return QR_MODE_NUL;
2007
2008            $c = $this->dataStr[$pos];
2009
2010            if(self::isdigitat($this->dataStr, $pos)) {
2011                return QR_MODE_NUM;
2012            } else if(self::isalnumat($this->dataStr, $pos)) {
2013                return QR_MODE_AN;
2014            } else if($this->modeHint == QR_MODE_KANJI) {
2015
2016                if ($pos+1 < strlen($this->dataStr))
2017                {
2018                    $d = $this->dataStr[$pos+1];
2019                    $word = (ord($c) << 8) | ord($d);
2020                    if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
2021                        return QR_MODE_KANJI;
2022                    }
2023                }
2024            }
2025
2026            return QR_MODE_8;
2027        }
2028
2029        //----------------------------------------------------------------------
2030        public function eatNum()
2031        {
2032            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
2033
2034            $p = 0;
2035            while(self::isdigitat($this->dataStr, $p)) {
2036                $p++;
2037            }
2038
2039            $run = $p;
2040            $mode = $this->identifyMode($p);
2041
2042            if($mode == QR_MODE_8) {
2043                $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
2044                     + QRinput::estimateBitsMode8(1)         // + 4 + l8
2045                     - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
2046                if($dif > 0) {
2047                    return $this->eat8();
2048                }
2049            }
2050            if($mode == QR_MODE_AN) {
2051                $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
2052                     + QRinput::estimateBitsModeAn(1)        // + 4 + la
2053                     - QRinput::estimateBitsModeAn($run + 1);// - 4 - la
2054                if($dif > 0) {
2055                    return $this->eatAn();
2056                }
2057            }
2058
2059            $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
2060            if($ret < 0)
2061                return -1;
2062
2063            return $run;
2064        }
2065
2066        //----------------------------------------------------------------------
2067        public function eatAn()
2068        {
2069            $la = QRspec::lengthIndicator(QR_MODE_AN,  $this->input->getVersion());
2070            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
2071
2072            $p = 0;
2073
2074            while(self::isalnumat($this->dataStr, $p)) {
2075                if(self::isdigitat($this->dataStr, $p)) {
2076                    $q = $p;
2077                    while(self::isdigitat($this->dataStr, $q)) {
2078                        $q++;
2079                    }
2080
2081                    $dif = QRinput::estimateBitsModeAn($p) // + 4 + la
2082                         + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
2083                         - QRinput::estimateBitsModeAn($q); // - 4 - la
2084
2085                    if($dif < 0) {
2086                        break;
2087                    } else {
2088                        $p = $q;
2089                    }
2090                } else {
2091                    $p++;
2092                }
2093            }
2094
2095            $run = $p;
2096
2097            if(!self::isalnumat($this->dataStr, $p)) {
2098                $dif = QRinput::estimateBitsModeAn($run) + 4 + $la
2099                     + QRinput::estimateBitsMode8(1) // + 4 + l8
2100                      - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
2101                if($dif > 0) {
2102                    return $this->eat8();
2103                }
2104            }
2105
2106            $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
2107            if($ret < 0)
2108                return -1;
2109
2110            return $run;
2111        }
2112
2113        //----------------------------------------------------------------------
2114        public function eatKanji()
2115        {
2116            $p = 0;
2117
2118            while($this->identifyMode($p) == QR_MODE_KANJI) {
2119                $p += 2;
2120            }
2121
2122            $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
2123            if($ret < 0)
2124                return -1;
2125
2126            return $run;
2127        }
2128
2129        //----------------------------------------------------------------------
2130        public function eat8()
2131        {
2132            $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
2133            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
2134
2135            $p = 1;
2136            $dataStrLen = strlen($this->dataStr);
2137
2138            while($p < $dataStrLen) {
2139
2140                $mode = $this->identifyMode($p);
2141                if($mode == QR_MODE_KANJI) {
2142                    break;
2143                }
2144                if($mode == QR_MODE_NUM) {
2145                    $q = $p;
2146                    while(self::isdigitat($this->dataStr, $q)) {
2147                        $q++;
2148                    }
2149                    $dif = QRinput::estimateBitsMode8($p) // + 4 + l8
2150                         + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
2151                         - QRinput::estimateBitsMode8($q); // - 4 - l8
2152                    if($dif < 0) {
2153                        break;
2154                    } else {
2155                        $p = $q;
2156                    }
2157                } else if($mode == QR_MODE_AN) {
2158                    $q = $p;
2159                    while(self::isalnumat($this->dataStr, $q)) {
2160                        $q++;
2161                    }
2162                    $dif = QRinput::estimateBitsMode8($p)  // + 4 + l8
2163                         + QRinput::estimateBitsModeAn($q - $p) + 4 + $la
2164                         - QRinput::estimateBitsMode8($q); // - 4 - l8
2165                    if($dif < 0) {
2166                        break;
2167                    } else {
2168                        $p = $q;
2169                    }
2170                } else {
2171                    $p++;
2172                }
2173            }
2174
2175            $run = $p;
2176            $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
2177
2178            if($ret < 0)
2179                return -1;
2180
2181            return $run;
2182        }
2183
2184        //----------------------------------------------------------------------
2185        public function splitString()
2186        {
2187            while (strlen($this->dataStr) > 0)
2188            {
2189                if($this->dataStr == '')
2190                    return 0;
2191
2192                $mode = $this->identifyMode(0);
2193
2194                switch ($mode) {
2195                    case QR_MODE_NUM: $length = $this->eatNum(); break;
2196                    case QR_MODE_AN:  $length = $this->eatAn(); break;
2197                    case QR_MODE_KANJI:
2198                        if ($hint == QR_MODE_KANJI)
2199                                $length = $this->eatKanji();
2200                        else    $length = $this->eat8();
2201                        break;
2202                    default: $length = $this->eat8(); break;
2203
2204                }
2205
2206                if($length == 0) return 0;
2207                if($length < 0)  return -1;
2208
2209                $this->dataStr = substr($this->dataStr, $length);
2210            }
2211        }
2212
2213        //----------------------------------------------------------------------
2214        public function toUpper()
2215        {
2216            $stringLen = strlen($this->dataStr);
2217            $p = 0;
2218
2219            while ($p<$stringLen) {
2220                $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
2221                if($mode == QR_MODE_KANJI) {
2222                    $p += 2;
2223                } else {
2224                    if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
2225                        $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
2226                    }
2227                    $p++;
2228                }
2229            }
2230
2231            return $this->dataStr;
2232        }
2233
2234        //----------------------------------------------------------------------
2235        public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
2236        {
2237            if(is_null($string) || $string == '\0' || $string == '') {
2238                throw new Exception('empty string!!!');
2239            }
2240
2241            $split = new QRsplit($string, $input, $modeHint);
2242
2243            if(!$casesensitive)
2244                $split->toUpper();
2245
2246            return $split->splitString();
2247        }
2248    }
2249
2250
2251
2252//---- qrrscode.php -----------------------------
2253
2254
2255
2256
2257/*
2258 * PHP QR Code encoder
2259 *
2260 * Reed-Solomon error correction support
2261 *
2262 * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
2263 * (libfec is released under the GNU Lesser General Public License.)
2264 *
2265 * Based on libqrencode C library distributed under LGPL 2.1
2266 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
2267 *
2268 * PHP QR Code is distributed under LGPL 3
2269 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
2270 *
2271 * This library is free software; you can redistribute it and/or
2272 * modify it under the terms of the GNU Lesser General Public
2273 * License as published by the Free Software Foundation; either
2274 * version 3 of the License, or any later version.
2275 *
2276 * This library is distributed in the hope that it will be useful,
2277 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2278 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2279 * Lesser General Public License for more details.
2280 *
2281 * You should have received a copy of the GNU Lesser General Public
2282 * License along with this library; if not, write to the Free Software
2283 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2284 */
2285
2286    class QRrsItem {
2287
2288        public $mm;                  // Bits per symbol
2289        public $nn;                  // Symbols per block (= (1<<mm)-1)
2290        public $alpha_to = array();  // log lookup table
2291        public $index_of = array();  // Antilog lookup table
2292        public $genpoly = array();   // Generator polynomial
2293        public $nroots;              // Number of generator roots = number of parity symbols
2294        public $fcr;                 // First consecutive root, index form
2295        public $prim;                // Primitive element, index form
2296        public $iprim;               // prim-th root of 1, index form
2297        public $pad;                 // Padding bytes in shortened block
2298        public $gfpoly;
2299
2300        //----------------------------------------------------------------------
2301        public function modnn($x)
2302        {
2303            while ($x >= $this->nn) {
2304                $x -= $this->nn;
2305                $x = ($x >> $this->mm) + ($x & $this->nn);
2306            }
2307
2308            return $x;
2309        }
2310
2311        //----------------------------------------------------------------------
2312        public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
2313        {
2314            // Common code for intializing a Reed-Solomon control block (char or int symbols)
2315            // Copyright 2004 Phil Karn, KA9Q
2316            // May be used under the terms of the GNU Lesser General Public License (LGPL)
2317
2318            $rs = null;
2319
2320            // Check parameter ranges
2321            if($symsize < 0 || $symsize > 8)                     return $rs;
2322            if($fcr < 0 || $fcr >= (1<<$symsize))                return $rs;
2323            if($prim <= 0 || $prim >= (1<<$symsize))             return $rs;
2324            if($nroots < 0 || $nroots >= (1<<$symsize))          return $rs; // Can't have more roots than symbol values!
2325            if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding
2326
2327            $rs = new QRrsItem();
2328            $rs->mm = $symsize;
2329            $rs->nn = (1<<$symsize)-1;
2330            $rs->pad = $pad;
2331
2332            $rs->alpha_to = array_fill(0, $rs->nn+1, 0);
2333            $rs->index_of = array_fill(0, $rs->nn+1, 0);
2334
2335            // PHP style macro replacement ;)
2336            $NN =& $rs->nn;
2337            $A0 =& $NN;
2338
2339            // Generate Galois field lookup tables
2340            $rs->index_of[0] = $A0; // log(zero) = -inf
2341            $rs->alpha_to[$A0] = 0; // alpha**-inf = 0
2342            $sr = 1;
2343
2344            for($i=0; $i<$rs->nn; $i++) {
2345                $rs->index_of[$sr] = $i;
2346                $rs->alpha_to[$i] = $sr;
2347                $sr <<= 1;
2348                if($sr & (1<<$symsize)) {
2349                    $sr ^= $gfpoly;
2350                }
2351                $sr &= $rs->nn;
2352            }
2353
2354            if($sr != 1){
2355                // field generator polynomial is not primitive!
2356                $rs = NULL;
2357                return $rs;
2358            }
2359
2360            /* Form RS code generator polynomial from its roots */
2361            $rs->genpoly = array_fill(0, $nroots+1, 0);
2362
2363            $rs->fcr = $fcr;
2364            $rs->prim = $prim;
2365            $rs->nroots = $nroots;
2366            $rs->gfpoly = $gfpoly;
2367
2368            /* Find prim-th root of 1, used in decoding */
2369            for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)
2370            ; // intentional empty-body loop!
2371
2372            $rs->iprim = (int)($iprim / $prim);
2373            $rs->genpoly[0] = 1;
2374
2375            for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
2376                $rs->genpoly[$i+1] = 1;
2377
2378                // Multiply rs->genpoly[] by  @**(root + x)
2379                for ($j = $i; $j > 0; $j--) {
2380                    if ($rs->genpoly[$j] != 0) {
2381                        $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];
2382                    } else {
2383                        $rs->genpoly[$j] = $rs->genpoly[$j-1];
2384                    }
2385                }
2386                // rs->genpoly[0] can never be zero
2387                $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
2388            }
2389
2390            // convert rs->genpoly[] to index form for quicker encoding
2391            for ($i = 0; $i <= $nroots; $i++)
2392                $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
2393
2394            return $rs;
2395        }
2396
2397        //----------------------------------------------------------------------
2398        public function encode_rs_char($data, &$parity)
2399        {
2400            $MM       =& $this->mm;
2401            $NN       =& $this->nn;
2402            $ALPHA_TO =& $this->alpha_to;
2403            $INDEX_OF =& $this->index_of;
2404            $GENPOLY  =& $this->genpoly;
2405            $NROOTS   =& $this->nroots;
2406            $FCR      =& $this->fcr;
2407            $PRIM     =& $this->prim;
2408            $IPRIM    =& $this->iprim;
2409            $PAD      =& $this->pad;
2410            $A0       =& $NN;
2411
2412            $parity = array_fill(0, $NROOTS, 0);
2413
2414            for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) {
2415
2416                $feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
2417                if($feedback != $A0) {
2418                    // feedback term is non-zero
2419
2420                    // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
2421                    // always be for the polynomials constructed by init_rs()
2422                    $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);
2423
2424                    for($j=1;$j<$NROOTS;$j++) {
2425                        $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])];
2426                    }
2427                }
2428
2429                // Shift
2430                array_shift($parity);
2431                if($feedback != $A0) {
2432                    array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);
2433                } else {
2434                    array_push($parity, 0);
2435                }
2436            }
2437        }
2438    }
2439
2440    //##########################################################################
2441
2442    class QRrs {
2443
2444        public static $items = array();
2445
2446        //----------------------------------------------------------------------
2447        public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
2448        {
2449            foreach(self::$items as $rs) {
2450                if($rs->pad != $pad)       continue;
2451                if($rs->nroots != $nroots) continue;
2452                if($rs->mm != $symsize)    continue;
2453                if($rs->gfpoly != $gfpoly) continue;
2454                if($rs->fcr != $fcr)       continue;
2455                if($rs->prim != $prim)     continue;
2456
2457                return $rs;
2458            }
2459
2460            $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
2461            array_unshift(self::$items, $rs);
2462
2463            return $rs;
2464        }
2465    }
2466
2467
2468
2469//---- qrmask.php -----------------------------
2470
2471
2472
2473
2474/*
2475 * PHP QR Code encoder
2476 *
2477 * Masking
2478 *
2479 * Based on libqrencode C library distributed under LGPL 2.1
2480 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
2481 *
2482 * PHP QR Code is distributed under LGPL 3
2483 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
2484 *
2485 * This library is free software; you can redistribute it and/or
2486 * modify it under the terms of the GNU Lesser General Public
2487 * License as published by the Free Software Foundation; either
2488 * version 3 of the License, or any later version.
2489 *
2490 * This library is distributed in the hope that it will be useful,
2491 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2492 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2493 * Lesser General Public License for more details.
2494 *
2495 * You should have received a copy of the GNU Lesser General Public
2496 * License along with this library; if not, write to the Free Software
2497 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2498 */
2499
2500	define('N1', 3);
2501	define('N2', 3);
2502	define('N3', 40);
2503	define('N4', 10);
2504
2505	class QRmask {
2506
2507		public $runLength = array();
2508
2509		//----------------------------------------------------------------------
2510		public function __construct()
2511        {
2512            $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
2513        }
2514
2515        //----------------------------------------------------------------------
2516        public function writeFormatInformation($width, &$frame, $mask, $level)
2517        {
2518            $blacks = 0;
2519            $format =  QRspec::getFormatInfo($mask, $level);
2520
2521            for($i=0; $i<8; $i++) {
2522                if($format & 1) {
2523                    $blacks += 2;
2524                    $v = 0x85;
2525                } else {
2526                    $v = 0x84;
2527                }
2528
2529                $frame[8][$width - 1 - $i] = chr($v);
2530                if($i < 6) {
2531                    $frame[$i][8] = chr($v);
2532                } else {
2533                    $frame[$i + 1][8] = chr($v);
2534                }
2535                $format = $format >> 1;
2536            }
2537
2538            for($i=0; $i<7; $i++) {
2539                if($format & 1) {
2540                    $blacks += 2;
2541                    $v = 0x85;
2542                } else {
2543                    $v = 0x84;
2544                }
2545
2546                $frame[$width - 7 + $i][8] = chr($v);
2547                if($i == 0) {
2548                    $frame[8][7] = chr($v);
2549                } else {
2550                    $frame[8][6 - $i] = chr($v);
2551                }
2552
2553                $format = $format >> 1;
2554            }
2555
2556            return $blacks;
2557        }
2558
2559        //----------------------------------------------------------------------
2560        public function mask0($x, $y) { return ($x+$y)&1;                       }
2561        public function mask1($x, $y) { return ($y&1);                          }
2562        public function mask2($x, $y) { return ($x%3);                          }
2563        public function mask3($x, $y) { return ($x+$y)%3;                       }
2564        public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; }
2565        public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3;           }
2566        public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1;       }
2567        public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1;     }
2568
2569        //----------------------------------------------------------------------
2570        private function generateMaskNo($maskNo, $width, $frame)
2571        {
2572            $bitMask = array_fill(0, $width, array_fill(0, $width, 0));
2573
2574            for($y=0; $y<$width; $y++) {
2575                for($x=0; $x<$width; $x++) {
2576                    if(ord($frame[$y][$x]) & 0x80) {
2577                        $bitMask[$y][$x] = 0;
2578                    } else {
2579                        $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y);
2580                        $bitMask[$y][$x] = ($maskFunc == 0)?1:0;
2581                    }
2582
2583                }
2584            }
2585
2586            return $bitMask;
2587        }
2588
2589        //----------------------------------------------------------------------
2590        public static function serial($bitFrame)
2591        {
2592            $codeArr = array();
2593
2594            foreach ($bitFrame as $line)
2595                $codeArr[] = join('', $line);
2596
2597            return gzcompress(join("\n", $codeArr), 9);
2598        }
2599
2600        //----------------------------------------------------------------------
2601        public static function unserial($code)
2602        {
2603            $codeArr = array();
2604
2605            $codeLines = explode("\n", gzuncompress($code));
2606            foreach ($codeLines as $line)
2607                $codeArr[] = str_split($line);
2608
2609            return $codeArr;
2610        }
2611
2612        //----------------------------------------------------------------------
2613        public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false)
2614        {
2615            $b = 0;
2616            $bitMask = array();
2617
2618            $fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat';
2619
2620            if (QR_CACHEABLE) {
2621                if (file_exists($fileName)) {
2622                    $bitMask = self::unserial(file_get_contents($fileName));
2623                } else {
2624                    $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
2625                    if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo))
2626                        mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
2627                    file_put_contents($fileName, self::serial($bitMask));
2628                }
2629            } else {
2630                $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
2631            }
2632
2633            if ($maskGenOnly)
2634                return;
2635
2636            $d = $s;
2637
2638            for($y=0; $y<$width; $y++) {
2639                for($x=0; $x<$width; $x++) {
2640                    if($bitMask[$y][$x] == 1) {
2641                        $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]);
2642                    }
2643                    $b += (int)(ord($d[$y][$x]) & 1);
2644                }
2645            }
2646
2647            return $b;
2648        }
2649
2650        //----------------------------------------------------------------------
2651        public function makeMask($width, $frame, $maskNo, $level)
2652        {
2653            $masked = array_fill(0, $width, str_repeat("\0", $width));
2654            $this->makeMaskNo($maskNo, $width, $frame, $masked);
2655            $this->writeFormatInformation($width, $masked, $maskNo, $level);
2656
2657            return $masked;
2658        }
2659
2660        //----------------------------------------------------------------------
2661        public function calcN1N3($length)
2662        {
2663            $demerit = 0;
2664
2665            for($i=0; $i<$length; $i++) {
2666
2667                if($this->runLength[$i] >= 5) {
2668                    $demerit += (N1 + ($this->runLength[$i] - 5));
2669                }
2670                if($i & 1) {
2671                    if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) {
2672                        $fact = (int)($this->runLength[$i] / 3);
2673                        if(($this->runLength[$i-2] == $fact) &&
2674                           ($this->runLength[$i-1] == $fact) &&
2675                           ($this->runLength[$i+1] == $fact) &&
2676                           ($this->runLength[$i+2] == $fact)) {
2677                            if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) {
2678                                $demerit += N3;
2679                            } else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) {
2680                                $demerit += N3;
2681                            }
2682                        }
2683                    }
2684                }
2685            }
2686            return $demerit;
2687        }
2688
2689        //----------------------------------------------------------------------
2690        public function evaluateSymbol($width, $frame)
2691        {
2692            $head = 0;
2693            $demerit = 0;
2694
2695            for($y=0; $y<$width; $y++) {
2696                $head = 0;
2697                $this->runLength[0] = 1;
2698
2699                $frameY = $frame[$y];
2700
2701                if ($y>0)
2702                    $frameYM = $frame[$y-1];
2703
2704                for($x=0; $x<$width; $x++) {
2705                    if(($x > 0) && ($y > 0)) {
2706                        $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
2707                        $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
2708
2709                        if(($b22 | ($w22 ^ 1))&1) {
2710                            $demerit += N2;
2711                        }
2712                    }
2713                    if(($x == 0) && (ord($frameY[$x]) & 1)) {
2714                        $this->runLength[0] = -1;
2715                        $head = 1;
2716                        $this->runLength[$head] = 1;
2717                    } else if($x > 0) {
2718                        if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
2719                            $head++;
2720                            $this->runLength[$head] = 1;
2721                        } else {
2722                            $this->runLength[$head]++;
2723                        }
2724                    }
2725                }
2726
2727                $demerit += $this->calcN1N3($head+1);
2728            }
2729
2730            for($x=0; $x<$width; $x++) {
2731                $head = 0;
2732                $this->runLength[0] = 1;
2733
2734                for($y=0; $y<$width; $y++) {
2735                    if($y == 0 && (ord($frame[$y][$x]) & 1)) {
2736                        $this->runLength[0] = -1;
2737                        $head = 1;
2738                        $this->runLength[$head] = 1;
2739                    } else if($y > 0) {
2740                        if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
2741                            $head++;
2742                            $this->runLength[$head] = 1;
2743                        } else {
2744                            $this->runLength[$head]++;
2745                        }
2746                    }
2747                }
2748
2749                $demerit += $this->calcN1N3($head+1);
2750            }
2751
2752            return $demerit;
2753        }
2754
2755
2756        //----------------------------------------------------------------------
2757        public function mask($width, $frame, $level)
2758        {
2759            $minDemerit = PHP_INT_MAX;
2760            $bestMaskNum = 0;
2761            $bestMask = array();
2762
2763            $checked_masks = array(0,1,2,3,4,5,6,7);
2764
2765            if (QR_FIND_FROM_RANDOM !== false) {
2766
2767                $howManuOut = 8-(QR_FIND_FROM_RANDOM % 9);
2768                for ($i = 0; $i <  $howManuOut; $i++) {
2769                    $remPos = rand (0, count($checked_masks)-1);
2770                    unset($checked_masks[$remPos]);
2771                    $checked_masks = array_values($checked_masks);
2772                }
2773
2774            }
2775
2776            $bestMask = $frame;
2777
2778            foreach($checked_masks as $i) {
2779                $mask = array_fill(0, $width, str_repeat("\0", $width));
2780
2781                $demerit = 0;
2782                $blacks = 0;
2783                $blacks  = $this->makeMaskNo($i, $width, $frame, $mask);
2784                $blacks += $this->writeFormatInformation($width, $mask, $i, $level);
2785                $blacks  = (int)(100 * $blacks / ($width * $width));
2786                $demerit = (int)((int)(abs($blacks - 50) / 5) * N4);
2787                $demerit += $this->evaluateSymbol($width, $mask);
2788
2789                if($demerit < $minDemerit) {
2790                    $minDemerit = $demerit;
2791                    $bestMask = $mask;
2792                    $bestMaskNum = $i;
2793                }
2794            }
2795
2796            return $bestMask;
2797        }
2798
2799        //----------------------------------------------------------------------
2800    }
2801
2802
2803
2804
2805//---- qrencode.php -----------------------------
2806
2807
2808
2809
2810/*
2811 * PHP QR Code encoder
2812 *
2813 * Main encoder classes.
2814 *
2815 * Based on libqrencode C library distributed under LGPL 2.1
2816 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
2817 *
2818 * PHP QR Code is distributed under LGPL 3
2819 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
2820 *
2821 * This library is free software; you can redistribute it and/or
2822 * modify it under the terms of the GNU Lesser General Public
2823 * License as published by the Free Software Foundation; either
2824 * version 3 of the License, or any later version.
2825 *
2826 * This library is distributed in the hope that it will be useful,
2827 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2828 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2829 * Lesser General Public License for more details.
2830 *
2831 * You should have received a copy of the GNU Lesser General Public
2832 * License along with this library; if not, write to the Free Software
2833 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2834 */
2835
2836    class QRrsblock {
2837        public $dataLength;
2838        public $data = array();
2839        public $eccLength;
2840        public $ecc = array();
2841
2842        public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs)
2843        {
2844            $rs->encode_rs_char($data, $ecc);
2845
2846            $this->dataLength = $dl;
2847            $this->data = $data;
2848            $this->eccLength = $el;
2849            $this->ecc = $ecc;
2850        }
2851    };
2852
2853    //##########################################################################
2854
2855    class QRrawcode {
2856        public $version;
2857        public $datacode = array();
2858        public $ecccode = array();
2859        public $blocks;
2860        public $rsblocks = array(); //of RSblock
2861        public $count;
2862        public $dataLength;
2863        public $eccLength;
2864        public $b1;
2865
2866        //----------------------------------------------------------------------
2867        public function __construct(QRinput $input)
2868        {
2869            $spec = array(0,0,0,0,0);
2870
2871            $this->datacode = $input->getByteStream();
2872            if(is_null($this->datacode)) {
2873                throw new Exception('null imput string');
2874            }
2875
2876            QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec);
2877
2878            $this->version = $input->getVersion();
2879            $this->b1 = QRspec::rsBlockNum1($spec);
2880            $this->dataLength = QRspec::rsDataLength($spec);
2881            $this->eccLength = QRspec::rsEccLength($spec);
2882            $this->ecccode = array_fill(0, $this->eccLength, 0);
2883            $this->blocks = QRspec::rsBlockNum($spec);
2884
2885            $ret = $this->init($spec);
2886            if($ret < 0) {
2887                throw new Exception('block alloc error');
2888                return null;
2889            }
2890
2891            $this->count = 0;
2892        }
2893
2894        //----------------------------------------------------------------------
2895        public function init(array $spec)
2896        {
2897            $dl = QRspec::rsDataCodes1($spec);
2898            $el = QRspec::rsEccCodes1($spec);
2899            $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
2900
2901
2902            $blockNo = 0;
2903            $dataPos = 0;
2904            $eccPos = 0;
2905            for($i=0; $i<QRspec::rsBlockNum1($spec); $i++) {
2906                $ecc = array_slice($this->ecccode,$eccPos);
2907                $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el,  $ecc, $rs);
2908                $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
2909
2910                $dataPos += $dl;
2911                $eccPos += $el;
2912                $blockNo++;
2913            }
2914
2915            if(QRspec::rsBlockNum2($spec) == 0)
2916                return 0;
2917
2918            $dl = QRspec::rsDataCodes2($spec);
2919            $el = QRspec::rsEccCodes2($spec);
2920            $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
2921
2922            if($rs == NULL) return -1;
2923
2924            for($i=0; $i<QRspec::rsBlockNum2($spec); $i++) {
2925                $ecc = array_slice($this->ecccode,$eccPos);
2926                $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
2927                $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
2928
2929                $dataPos += $dl;
2930                $eccPos += $el;
2931                $blockNo++;
2932            }
2933
2934            return 0;
2935        }
2936
2937        //----------------------------------------------------------------------
2938        public function getCode()
2939        {
2940            $ret;
2941
2942            if($this->count < $this->dataLength) {
2943                $row = $this->count % $this->blocks;
2944                $col = $this->count / $this->blocks;
2945                if($col >= $this->rsblocks[0]->dataLength) {
2946                    $row += $this->b1;
2947                }
2948                $ret = $this->rsblocks[$row]->data[$col];
2949            } else if($this->count < $this->dataLength + $this->eccLength) {
2950                $row = ($this->count - $this->dataLength) % $this->blocks;
2951                $col = ($this->count - $this->dataLength) / $this->blocks;
2952                $ret = $this->rsblocks[$row]->ecc[$col];
2953            } else {
2954                return 0;
2955            }
2956            $this->count++;
2957
2958            return $ret;
2959        }
2960    }
2961
2962    //##########################################################################
2963
2964    class QRcode {
2965
2966        public $version;
2967        public $width;
2968        public $data;
2969
2970        //----------------------------------------------------------------------
2971        public function encodeMask(QRinput $input, $mask)
2972        {
2973            if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) {
2974                throw new Exception('wrong version');
2975            }
2976            if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) {
2977                throw new Exception('wrong level');
2978            }
2979
2980            $raw = new QRrawcode($input);
2981
2982            QRtools::markTime('after_raw');
2983
2984            $version = $raw->version;
2985            $width = QRspec::getWidth($version);
2986            $frame = QRspec::newFrame($version);
2987
2988            $filler = new FrameFiller($width, $frame);
2989            if(is_null($filler)) {
2990                return NULL;
2991            }
2992
2993            // inteleaved data and ecc codes
2994            for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) {
2995                $code = $raw->getCode();
2996                $bit = 0x80;
2997                for($j=0; $j<8; $j++) {
2998                    $addr = $filler->next();
2999                    $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
3000                    $bit = $bit >> 1;
3001                }
3002            }
3003
3004            QRtools::markTime('after_filler');
3005
3006            unset($raw);
3007
3008            // remainder bits
3009            $j = QRspec::getRemainder($version);
3010            for($i=0; $i<$j; $i++) {
3011                $addr = $filler->next();
3012                $filler->setFrameAt($addr, 0x02);
3013            }
3014
3015            $frame = $filler->frame;
3016            unset($filler);
3017
3018
3019            // masking
3020            $maskObj = new QRmask();
3021            if($mask < 0) {
3022
3023                if (QR_FIND_BEST_MASK) {
3024                    $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel());
3025                } else {
3026                    $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel());
3027                }
3028            } else {
3029                $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel());
3030            }
3031
3032            if($masked == NULL) {
3033                return NULL;
3034            }
3035
3036            QRtools::markTime('after_mask');
3037
3038            $this->version = $version;
3039            $this->width = $width;
3040            $this->data = $masked;
3041
3042            return $this;
3043        }
3044
3045        //----------------------------------------------------------------------
3046        public function encodeInput(QRinput $input)
3047        {
3048            return $this->encodeMask($input, -1);
3049        }
3050
3051        //----------------------------------------------------------------------
3052        public function encodeString8bit($string, $version, $level)
3053        {
3054            if(string == NULL) {
3055                throw new Exception('empty string!');
3056                return NULL;
3057            }
3058
3059            $input = new QRinput($version, $level);
3060            if($input == NULL) return NULL;
3061
3062            $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string));
3063            if($ret < 0) {
3064                unset($input);
3065                return NULL;
3066            }
3067            return $this->encodeInput($input);
3068        }
3069
3070        //----------------------------------------------------------------------
3071        public function encodeString($string, $version, $level, $hint, $casesensitive)
3072        {
3073
3074            if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) {
3075                throw new Exception('bad hint');
3076                return NULL;
3077            }
3078
3079            $input = new QRinput($version, $level);
3080            if($input == NULL) return NULL;
3081
3082            $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive);
3083            if($ret < 0) {
3084                return NULL;
3085            }
3086
3087            return $this->encodeInput($input);
3088        }
3089
3090        //----------------------------------------------------------------------
3091        public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false)
3092        {
3093            $enc = QRencode::factory($level, $size, $margin);
3094            return $enc->encodePNG($text, $outfile, $saveandprint=false);
3095        }
3096
3097        //----------------------------------------------------------------------
3098        public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
3099        {
3100            $enc = QRencode::factory($level, $size, $margin);
3101            return $enc->encode($text, $outfile);
3102        }
3103
3104        //----------------------------------------------------------------------
3105        public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
3106        {
3107            $enc = QRencode::factory($level, $size, $margin);
3108            return $enc->encodeRAW($text, $outfile);
3109        }
3110    }
3111
3112    //##########################################################################
3113
3114    class FrameFiller {
3115
3116        public $width;
3117        public $frame;
3118        public $x;
3119        public $y;
3120        public $dir;
3121        public $bit;
3122
3123        //----------------------------------------------------------------------
3124        public function __construct($width, &$frame)
3125        {
3126            $this->width = $width;
3127            $this->frame = $frame;
3128            $this->x = $width - 1;
3129            $this->y = $width - 1;
3130            $this->dir = -1;
3131            $this->bit = -1;
3132        }
3133
3134        //----------------------------------------------------------------------
3135        public function setFrameAt($at, $val)
3136        {
3137            $this->frame[$at['y']][$at['x']] = chr($val);
3138        }
3139
3140        //----------------------------------------------------------------------
3141        public function getFrameAt($at)
3142        {
3143            return ord($this->frame[$at['y']][$at['x']]);
3144        }
3145
3146        //----------------------------------------------------------------------
3147        public function next()
3148        {
3149            do {
3150
3151                if($this->bit == -1) {
3152                    $this->bit = 0;
3153                    return array('x'=>$this->x, 'y'=>$this->y);
3154                }
3155
3156                $x = $this->x;
3157                $y = $this->y;
3158                $w = $this->width;
3159
3160                if($this->bit == 0) {
3161                    $x--;
3162                    $this->bit++;
3163                } else {
3164                    $x++;
3165                    $y += $this->dir;
3166                    $this->bit--;
3167                }
3168
3169                if($this->dir < 0) {
3170                    if($y < 0) {
3171                        $y = 0;
3172                        $x -= 2;
3173                        $this->dir = 1;
3174                        if($x == 6) {
3175                            $x--;
3176                            $y = 9;
3177                        }
3178                    }
3179                } else {
3180                    if($y == $w) {
3181                        $y = $w - 1;
3182                        $x -= 2;
3183                        $this->dir = -1;
3184                        if($x == 6) {
3185                            $x--;
3186                            $y -= 8;
3187                        }
3188                    }
3189                }
3190                if($x < 0 || $y < 0) return null;
3191
3192                $this->x = $x;
3193                $this->y = $y;
3194
3195            } while(ord($this->frame[$y][$x]) & 0x80);
3196
3197            return array('x'=>$x, 'y'=>$y);
3198        }
3199
3200    } ;
3201
3202    //##########################################################################
3203
3204    class QRencode {
3205
3206        public $casesensitive = true;
3207        public $eightbit = false;
3208
3209        public $version = 0;
3210        public $size = 3;
3211        public $margin = 4;
3212
3213        public $structured = 0; // not supported yet
3214
3215        public $level = QR_ECLEVEL_L;
3216        public $hint = QR_MODE_8;
3217
3218        //----------------------------------------------------------------------
3219        public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4)
3220        {
3221            $enc = new QRencode();
3222            $enc->size = $size;
3223            $enc->margin = $margin;
3224
3225            switch ($level.'') {
3226                case '0':
3227                case '1':
3228                case '2':
3229                case '3':
3230                        $enc->level = $level;
3231                    break;
3232                case 'l':
3233                case 'L':
3234                        $enc->level = QR_ECLEVEL_L;
3235                    break;
3236                case 'm':
3237                case 'M':
3238                        $enc->level = QR_ECLEVEL_M;
3239                    break;
3240                case 'q':
3241                case 'Q':
3242                        $enc->level = QR_ECLEVEL_Q;
3243                    break;
3244                case 'h':
3245                case 'H':
3246                        $enc->level = QR_ECLEVEL_H;
3247                    break;
3248            }
3249
3250            return $enc;
3251        }
3252
3253        //----------------------------------------------------------------------
3254        public function encodeRAW($intext, $outfile = false)
3255        {
3256            $code = new QRcode();
3257
3258            if($this->eightbit) {
3259                $code->encodeString8bit($intext, $this->version, $this->level);
3260            } else {
3261                $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
3262            }
3263
3264            return $code->data;
3265        }
3266
3267        //----------------------------------------------------------------------
3268        public function encode($intext, $outfile = false)
3269        {
3270            $code = new QRcode();
3271
3272            if($this->eightbit) {
3273                $code->encodeString8bit($intext, $this->version, $this->level);
3274            } else {
3275                $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
3276            }
3277
3278            QRtools::markTime('after_encode');
3279
3280            if ($outfile!== false) {
3281                file_put_contents($outfile, join("\n", QRtools::binarize($code->data)));
3282            } else {
3283                return QRtools::binarize($code->data);
3284            }
3285        }
3286
3287        //----------------------------------------------------------------------
3288        public function encodePNG($intext, $outfile = false,$saveandprint=false)
3289        {
3290            try {
3291
3292                ob_start();
3293                $tab = $this->encode($intext);
3294                $err = ob_get_contents();
3295                ob_end_clean();
3296
3297                if ($err != '')
3298                    QRtools::log($outfile, $err);
3299
3300                $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin));
3301
3302                QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint);
3303
3304            } catch (Exception $e) {
3305
3306                QRtools::log($outfile, $e->getMessage());
3307
3308            }
3309        }
3310    }
3311
3312
3313