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