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