PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 3.1.0
Defender Security – Malware Scanner, Login Security & Firewall v3.1.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / src / extra / phpqrcode / phpqrcode.php

phpqrcode.php in Defender Security – Malware Scanner, Login Security & Firewall 3.1.0, at src/extra/phpqrcode/phpqrcode.php

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