PluginProbe
PDF for WPForms + Drag and Drop Template Builder / trunk
PDF for WPForms + Drag and Drop Template Builder vtrunk
7.2.0 7.1.0 trunk 2.5.0 3.0.0 6.2.1 6.3.1 6.5.0 6.5.1 6.5.2
pdf-for-wpforms / libs / phpqrcode.php

phpqrcode.php in PDF for WPForms + Drag and Drop Template Builder trunk, at libs/phpqrcode.php

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