PluginProbe
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin / trunk
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin vtrunk
trunk 1.5 1.6 1.7 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 All 71 releases
pdf-print / includes / qr_code / qr_code.php

qr_code.php in PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin trunk, at includes/qr_code/qr_code.php

1,734 lines 47.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 //---------------------------------------------------------------
4 // QRCode for PHP5
5 //
6 // Copyright (c) 2009 Kazuhiko Arase
7 //
8 // URL: http://www.d-project.com/
9 //
10 // Licensed under the MIT license:
11 // http://www.opensource.org/licenses/mit-license.php
12 //
13 // The word "QR Code" is registered trademark of
14 // DENSO WAVE INCORPORATED
15 // http://www.denso-wave.com/qrcode/faqpatent-e.html
16 //
17 //---------------------------------------------------------------------
18
19 //---------------------------------------------------------------
20 // QRCode
21 //---------------------------------------------------------------
22
23 define("QR_PAD0", 0xEC);
24 define("QR_PAD1", 0x11);
25
26 class QRCode {
27
28 var $typeNumber;
29
30 var $modules;
31
32 var $moduleCount;
33
34 var $errorCorrectLevel;
35
36 var $qrDataList;
37
38 function __construct() {
39 $this->typeNumber = 1;
40 $this->errorCorrectLevel = QR_ERROR_CORRECT_LEVEL_H;
41 $this->qrDataList = array();
42 }
43
44 function getTypeNumber() {
45 return $this->typeNumber;
46 }
47
48 function setTypeNumber($typeNumber) {
49 $this->typeNumber = $typeNumber;
50 }
51
52 function getErrorCorrectLevel() {
53 return $this->errorCorrectLevel;
54 }
55
56 function setErrorCorrectLevel($errorCorrectLevel) {
57 $this->errorCorrectLevel = $errorCorrectLevel;
58 }
59
60 function addData($data, $mode = 0) {
61
62 if ($mode == 0) {
63 $mode = QRUtil::getMode($data);
64 }
65
66 switch($mode) {
67
68 case QR_MODE_NUMBER :
69 $this->addDataImpl(new QRNumber($data) );
70 break;
71
72 case QR_MODE_ALPHA_NUM :
73 $this->addDataImpl(new QRAlphaNum($data) );
74 break;
75
76 case QR_MODE_8BIT_BYTE :
77 $this->addDataImpl(new QR8BitByte($data) );
78 break;
79
80 case QR_MODE_KANJI :
81 $this->addDataImpl(new QRKanji($data) );
82 break;
83
84 default :
85 trigger_error("mode:$mode", E_USER_ERROR);
86 }
87 }
88
89 function clearData() {
90 $this->qrDataList = array();
91 }
92
93 function addDataImpl($qrData) {
94 $this->qrDataList[] = $qrData;
95 }
96
97 function getDataCount() {
98 return count($this->qrDataList);
99 }
100
101 function getData($index) {
102 return $this->qrDataList[$index];
103 }
104
105 function isDark($row, $col) {
106 if ($this->modules[$row][$col] !== null) {
107 return $this->modules[$row][$col];
108 } else {
109 return false;
110 }
111 }
112
113 function getModuleCount() {
114 return $this->moduleCount;
115 }
116
117 // used for converting fg/bg colors (e.g. #0000ff = 0x0000FF)
118 // added 2015.07.27 ~ DoktorJ
119 function hex2rgb($hex = 0x0) {
120 return array(
121 'r' => floor($hex / 65536),
122 'g' => floor($hex / 256) % 256,
123 'b' => $hex % 256
124 );
125 }
126
127 function make() {
128 $this->makeImpl(false, $this->getBestMaskPattern() );
129 }
130
131 function getBestMaskPattern() {
132
133 $minLostPoint = 0;
134 $pattern = 0;
135
136 for ($i = 0; $i < 8; $i++) {
137
138 $this->makeImpl(true, $i);
139
140 $lostPoint = QRUtil::getLostPoint($this);
141
142 if ($i == 0 || $minLostPoint > $lostPoint) {
143 $minLostPoint = $lostPoint;
144 $pattern = $i;
145 }
146 }
147
148 return $pattern;
149 }
150
151 function createNullArray($length) {
152 $nullArray = array();
153 for ($i = 0; $i < $length; $i++) {
154 $nullArray[] = null;
155 }
156 return $nullArray;
157 }
158
159 function makeImpl($test, $maskPattern) {
160
161 $this->moduleCount = $this->typeNumber * 4 + 17;
162
163 $this->modules = array();
164 for ($i = 0; $i < $this->moduleCount; $i++) {
165 $this->modules[] = QRCode::createNullArray($this->moduleCount);
166 }
167
168 $this->setupPositionProbePattern(0, 0);
169 $this->setupPositionProbePattern($this->moduleCount - 7, 0);
170 $this->setupPositionProbePattern(0, $this->moduleCount - 7);
171
172 $this->setupPositionAdjustPattern();
173 $this->setupTimingPattern();
174
175 $this->setupTypeInfo($test, $maskPattern);
176
177 if ($this->typeNumber >= 7) {
178 $this->setupTypeNumber($test);
179 }
180
181 $dataArray = $this->qrDataList;
182
183 $data = QRCode::createData($this->typeNumber, $this->errorCorrectLevel, $dataArray);
184
185 $this->mapData($data, $maskPattern);
186 }
187
188 function mapData(&$data, $maskPattern) {
189
190 $inc = -1;
191 $row = $this->moduleCount - 1;
192 $bitIndex = 7;
193 $byteIndex = 0;
194
195 for ($col = $this->moduleCount - 1; $col > 0; $col -= 2) {
196
197 if ($col == 6) $col--;
198
199 while (true) {
200
201 for ($c = 0; $c < 2; $c++) {
202
203 if ($this->modules[$row][$col - $c] === null) {
204
205 $dark = false;
206
207 if ($byteIndex < count($data) ) {
208 $dark = ( ( ($data[$byteIndex] >> $bitIndex) & 1) == 1);
209 }
210
211 if (QRUtil::getMask($maskPattern, $row, $col - $c)) {
212 $dark = !$dark;
213 }
214
215 $this->modules[$row][$col - $c] = $dark;
216 $bitIndex--;
217
218 if ($bitIndex == -1) {
219 $byteIndex++;
220 $bitIndex = 7;
221 }
222 }
223 }
224
225 $row += $inc;
226
227 if ($row < 0 || $this->moduleCount <= $row) {
228 $row -= $inc;
229 $inc = -$inc;
230 break;
231 }
232 }
233 }
234 }
235
236 function setupPositionAdjustPattern() {
237
238 $pos = QRUtil::getPatternPosition($this->typeNumber);
239
240 for ($i = 0; $i < count($pos); $i++) {
241
242 for ($j = 0; $j < count($pos); $j++) {
243
244 $row = $pos[$i];
245 $col = $pos[$j];
246
247 if ($this->modules[$row][$col] !== null) {
248 continue;
249 }
250
251 for ($r = -2; $r <= 2; $r++) {
252
253 for ($c = -2; $c <= 2; $c++) {
254 $this->modules[$row + $r][$col + $c] =
255 $r == -2 || $r == 2 || $c == -2 || $c == 2 || ($r == 0 && $c == 0);
256 }
257 }
258 }
259 }
260 }
261
262 function setupPositionProbePattern($row, $col) {
263
264 for ($r = -1; $r <= 7; $r++) {
265
266 for ($c = -1; $c <= 7; $c++) {
267
268 if ($row + $r <= -1 || $this->moduleCount <= $row + $r
269 || $col + $c <= -1 || $this->moduleCount <= $col + $c) {
270 continue;
271 }
272
273 $this->modules[$row + $r][$col + $c] =
274 (0 <= $r && $r <= 6 && ($c == 0 || $c == 6) )
275 || (0 <= $c && $c <= 6 && ($r == 0 || $r == 6) )
276 || (2 <= $r && $r <= 4 && 2 <= $c && $c <= 4);
277 }
278 }
279 }
280
281 function setupTimingPattern() {
282
283 for ($i = 8; $i < $this->moduleCount - 8; $i++) {
284
285 if ($this->modules[$i][6] !== null || $this->modules[6][$i] !== null) {
286 continue;
287 }
288
289 $this->modules[$i][6] = ($i % 2 == 0);
290 $this->modules[6][$i] = ($i % 2 == 0);
291 }
292 }
293
294 function setupTypeNumber($test) {
295
296 $bits = QRUtil::getBCHTypeNumber($this->typeNumber);
297
298 for ($i = 0; $i < 18; $i++) {
299 $mod = (!$test && ( ($bits >> $i) & 1) == 1);
300 $this->modules[(int)floor($i / 3)][$i % 3 + $this->moduleCount - 8 - 3] = $mod;
301 $this->modules[$i % 3 + $this->moduleCount - 8 - 3][floor($i / 3)] = $mod;
302 }
303 }
304
305 function setupTypeInfo($test, $maskPattern) {
306
307 $data = ($this->errorCorrectLevel << 3) | $maskPattern;
308 $bits = QRUtil::getBCHTypeInfo($data);
309
310 for ($i = 0; $i < 15; $i++) {
311
312 $mod = (!$test && ( ($bits >> $i) & 1) == 1);
313
314 if ($i < 6) {
315 $this->modules[$i][8] = $mod;
316 } else if ($i < 8) {
317 $this->modules[$i + 1][8] = $mod;
318 } else {
319 $this->modules[$this->moduleCount - 15 + $i][8] = $mod;
320 }
321
322 if ($i < 8) {
323 $this->modules[8][$this->moduleCount - $i - 1] = $mod;
324 } else if ($i < 9) {
325 $this->modules[8][15 - $i - 1 + 1] = $mod;
326 } else {
327 $this->modules[8][15 - $i - 1] = $mod;
328 }
329 }
330
331 $this->modules[$this->moduleCount - 8][8] = !$test;
332 }
333
334 function createData($typeNumber, $errorCorrectLevel, $dataArray) {
335
336 $rsBlocks = QRRSBlock::getRSBlocks($typeNumber, $errorCorrectLevel);
337
338 $buffer = new QRBitBuffer();
339
340 for ($i = 0; $i < count($dataArray); $i++) {
341 /** @var \QRData $data */
342 $data = $dataArray[$i];
343 $buffer->put($data->getMode(), 4);
344 $buffer->put($data->getLength(), $data->getLengthInBits($typeNumber) );
345 $data->write($buffer);
346 }
347
348 $totalDataCount = 0;
349 for ($i = 0; $i < count($rsBlocks); $i++) {
350 $totalDataCount += $rsBlocks[$i]->getDataCount();
351 }
352
353 if ($buffer->getLengthInBits() > $totalDataCount * 8) {
354 trigger_error("code length overflow. ("
355 . $buffer->getLengthInBits()
356 . ">"
357 . $totalDataCount * 8
358 . ")", E_USER_ERROR);
359 }
360
361 // end code.
362 if ($buffer->getLengthInBits() + 4 <= $totalDataCount * 8) {
363 $buffer->put(0, 4);
364 }
365
366 // padding
367 while ($buffer->getLengthInBits() % 8 != 0) {
368 $buffer->putBit(false);
369 }
370
371 // padding
372 while (true) {
373
374 if ($buffer->getLengthInBits() >= $totalDataCount * 8) {
375 break;
376 }
377 $buffer->put(QR_PAD0, 8);
378
379 if ($buffer->getLengthInBits() >= $totalDataCount * 8) {
380 break;
381 }
382 $buffer->put(QR_PAD1, 8);
383 }
384
385 return QRCode::createBytes($buffer, $rsBlocks);
386 }
387
388 /**
389 * @param \QRBitBuffer $buffer
390 * @param \QRRSBlock[] $rsBlocks
391 *
392 * @return array
393 */
394 function createBytes(&$buffer, &$rsBlocks) {
395
396 $offset = 0;
397
398 $maxDcCount = 0;
399 $maxEcCount = 0;
400
401 $dcdata = QRCode::createNullArray(count($rsBlocks) );
402 $ecdata = QRCode::createNullArray(count($rsBlocks) );
403
404 $rsBlockCount = count($rsBlocks);
405 for ($r = 0; $r < $rsBlockCount; $r++) {
406
407 $dcCount = $rsBlocks[$r]->getDataCount();
408 $ecCount = $rsBlocks[$r]->getTotalCount() - $dcCount;
409
410 $maxDcCount = max($maxDcCount, $dcCount);
411 $maxEcCount = max($maxEcCount, $ecCount);
412
413 $dcdata[$r] = QRCode::createNullArray($dcCount);
414 $dcDataCount = count($dcdata[$r]);
415 for ($i = 0; $i < $dcDataCount; $i++) {
416 $bdata = $buffer->getBuffer();
417 $dcdata[$r][$i] = 0xff & $bdata[$i + $offset];
418 }
419 $offset += $dcCount;
420
421 $rsPoly = QRUtil::getErrorCorrectPolynomial($ecCount);
422 $rawPoly = new QRPolynomial($dcdata[$r], $rsPoly->getLength() - 1);
423
424 $modPoly = $rawPoly->mod($rsPoly);
425 $ecdata[$r] = QRCode::createNullArray($rsPoly->getLength() - 1);
426
427 $ecDataCount = count($ecdata[$r]);
428 for ($i = 0; $i < $ecDataCount; $i++) {
429 $modIndex = $i + $modPoly->getLength() - count($ecdata[$r]);
430 $ecdata[$r][$i] = ($modIndex >= 0)? $modPoly->get($modIndex) : 0;
431 }
432 }
433
434 $totalCodeCount = 0;
435 for ($i = 0; $i < $rsBlockCount; $i++) {
436 $totalCodeCount += $rsBlocks[$i]->getTotalCount();
437 }
438
439 $data = QRCode::createNullArray($totalCodeCount);
440
441 $index = 0;
442
443 for ($i = 0; $i < $maxDcCount; $i++) {
444 for ($r = 0; $r < $rsBlockCount; $r++) {
445 if ($i < count($dcdata[$r]) ) {
446 $data[$index++] = $dcdata[$r][$i];
447 }
448 }
449 }
450
451 for ($i = 0; $i < $maxEcCount; $i++) {
452 for ($r = 0; $r < $rsBlockCount; $r++) {
453 if ($i < count($ecdata[$r]) ) {
454 $data[$index++] = $ecdata[$r][$i];
455 }
456 }
457 }
458
459 return $data;
460 }
461
462 static function getMinimumQRCode($data, $errorCorrectLevel) {
463
464 $mode = QRUtil::getMode($data);
465
466 $qr = new QRCode();
467 $qr->setErrorCorrectLevel($errorCorrectLevel);
468 $qr->addData($data, $mode);
469
470 $qrData = $qr->getData(0);
471 $length = $qrData->getLength();
472
473 for ($typeNumber = 1; $typeNumber <= 40; $typeNumber++) {
474 if ($length <= QRUtil::getMaxLength($typeNumber, $mode, $errorCorrectLevel) ) {
475 $qr->setTypeNumber($typeNumber);
476 break;
477 }
478 }
479
480 $qr->make();
481
482 return $qr;
483 }
484
485 // added $fg (foreground), $bg (background), and $bgtrans (use transparent bg) parameters
486 // also added some simple error checking on parameters
487 // updated 2015.07.27 ~ DoktorJ
488 function createImage($size = 2, $margin = 2, $fg = 0x000000, $bg = 0xFFFFFF, $bgtrans = false) {
489
490 // size/margin EC
491 if (!is_numeric($size)) $size = 2;
492 if (!is_numeric($margin)) $margin = 2;
493 if ($size < 1) $size = 1;
494 if ($margin < 0) $margin = 0;
495
496 $image_size = $this->getModuleCount() * $size + $margin * 2;
497
498 $image = imagecreatetruecolor($image_size, $image_size);
499
500 // fg/bg EC
501 if ($fg < 0 || $fg > 0xFFFFFF) $fg = 0x0;
502 if ($bg < 0 || $bg > 0xFFFFFF) $bg = 0xFFFFFF;
503
504 // convert hexadecimal RGB to arrays for imagecolorallocate
505 $fgrgb = $this->hex2rgb($fg);
506 $bgrgb = $this->hex2rgb($bg);
507
508 // replace $black and $white with $fgc and $bgc
509 $fgc = imagecolorallocate($image, $fgrgb['r'], $fgrgb['g'], $fgrgb['b']);
510 $bgc = imagecolorallocate($image, $bgrgb['r'], $bgrgb['g'], $bgrgb['b']);
511 if ($bgtrans) imagecolortransparent($image, $bgc);
512
513 // update $white to $bgc
514 imagefilledrectangle($image, 0, 0, $image_size, $image_size, $bgc);
515
516 for ($r = 0; $r < $this->getModuleCount(); $r++) {
517 for ($c = 0; $c < $this->getModuleCount(); $c++) {
518 if ($this->isDark($r, $c) ) {
519
520 // update $black to $fgc
521 imagefilledrectangle($image,
522 $margin + $c * $size,
523 $margin + $r * $size,
524 $margin + ($c + 1) * $size - 1,
525 $margin + ($r + 1) * $size - 1,
526 $fgc);
527 }
528 }
529 }
530
531 return $image;
532 }
533
534 function printHTML($size = "2px") {
535
536 $style = "border-style:none;border-collapse:collapse;margin:0px;padding:0px;";
537
538 print("<table style='$style'>");
539
540 for ($r = 0; $r < $this->getModuleCount(); $r++) {
541
542 print("<tr style='$style'>");
543
544 for ($c = 0; $c < $this->getModuleCount(); $c++) {
545 $color = $this->isDark($r, $c)? "#000000" : "#ffffff";
546 print("<td style='$style;width:$size;height:$size;background-color:$color'></td>");
547 }
548
549 print("</tr>");
550 }
551
552 print("</table>");
553 }
554
555 public function printSVG($size = 2)
556 {
557 $width = $this->getModuleCount() * $size;
558 $height = $width;
559 print('<svg width="' . $width . '" height="' . $height . '" viewBox="0 0 ' . $width . ' ' . $height . '" xmlns="http://www.w3.org/2000/svg">');
560
561 for ($r = 0; $r < $this->getModuleCount(); $r++) {
562 for ($c = 0; $c < $this->getModuleCount(); $c++) {
563 $color = $this->isDark($r, $c) ? "#000000" : "#ffffff";
564 print('<rect x="' . ($c * $size) . '" y="' . ($r * $size) . '" width="' . $size . '" height="' . $size . '" fill="' . $color . '" shape-rendering="crispEdges"/>');
565 }
566 }
567
568 print("</svg>");
569 }
570 }
571
572 //---------------------------------------------------------------
573 // QRUtil
574 //---------------------------------------------------------------
575
576 define("QR_G15", (1 << 10) | (1 << 8) | (1 << 5)
577 | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0) );
578
579 define("QR_G18", (1 << 12) | (1 << 11) | (1 << 10)
580 | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0) );
581
582 define("QR_G15_MASK", (1 << 14) | (1 << 12) | (1 << 10)
583 | (1 << 4) | (1 << 1) );
584
585 class QRUtil {
586
587 static $QR_MAX_LENGTH = array(
588 array( array(41, 25, 17, 10), array(34, 20, 14, 8), array(27, 16, 11, 7), array(17, 10, 7, 4) ),
589 array( array(77, 47, 32, 20), array(63, 38, 26, 16), array(48, 29, 20, 12), array(34, 20, 14, 8) ),
590 array( array(127, 77, 53, 32), array(101, 61, 42, 26), array(77, 47, 32, 20), array(58, 35, 24, 15) ),
591 array( array(187, 114, 78, 48), array(149, 90, 62, 38), array(111, 67, 46, 28), array(82, 50, 34, 21) ),
592 array( array(255, 154, 106, 65), array(202, 122, 84, 52), array(144, 87, 60, 37), array(106, 64, 44, 27) ),
593 array( array(322, 195, 134, 82), array(255, 154, 106, 65), array(178, 108, 74, 45), array(139, 84, 58, 36) ),
594 array( array(370, 224, 154, 95), array(293, 178, 122, 75), array(207, 125, 86, 53), array(154, 93, 64, 39) ),
595 array( array(461, 279, 192, 118), array(365, 221, 152, 93), array(259, 157, 108, 66), array(202, 122, 84, 52) ),
596 array( array(552, 335, 230, 141), array(432, 262, 180, 111), array(312, 189, 130, 80), array(235, 143, 98, 60) ),
597 array( array(652, 395, 271, 167), array(513, 311, 213, 131), array(364, 221, 151, 93), array(288, 174, 119, 74) )
598 );
599
600 static $QR_PATTERN_POSITION_TABLE = array(
601 array(),
602 array(6, 18),
603 array(6, 22),
604 array(6, 26),
605 array(6, 30),
606 array(6, 34),
607 array(6, 22, 38),
608 array(6, 24, 42),
609 array(6, 26, 46),
610 array(6, 28, 50),
611 array(6, 30, 54),
612 array(6, 32, 58),
613 array(6, 34, 62),
614 array(6, 26, 46, 66),
615 array(6, 26, 48, 70),
616 array(6, 26, 50, 74),
617 array(6, 30, 54, 78),
618 array(6, 30, 56, 82),
619 array(6, 30, 58, 86),
620 array(6, 34, 62, 90),
621 array(6, 28, 50, 72, 94),
622 array(6, 26, 50, 74, 98),
623 array(6, 30, 54, 78, 102),
624 array(6, 28, 54, 80, 106),
625 array(6, 32, 58, 84, 110),
626 array(6, 30, 58, 86, 114),
627 array(6, 34, 62, 90, 118),
628 array(6, 26, 50, 74, 98, 122),
629 array(6, 30, 54, 78, 102, 126),
630 array(6, 26, 52, 78, 104, 130),
631 array(6, 30, 56, 82, 108, 134),
632 array(6, 34, 60, 86, 112, 138),
633 array(6, 30, 58, 86, 114, 142),
634 array(6, 34, 62, 90, 118, 146),
635 array(6, 30, 54, 78, 102, 126, 150),
636 array(6, 24, 50, 76, 102, 128, 154),
637 array(6, 28, 54, 80, 106, 132, 158),
638 array(6, 32, 58, 84, 110, 136, 162),
639 array(6, 26, 54, 82, 110, 138, 166),
640 array(6, 30, 58, 86, 114, 142, 170)
641 );
642
643 static function getPatternPosition($typeNumber) {
644 return self::$QR_PATTERN_POSITION_TABLE[$typeNumber - 1];
645 }
646
647 static function getMaxLength($typeNumber, $mode, $errorCorrectLevel) {
648
649 $t = $typeNumber - 1;
650 $e = 0;
651 $m = 0;
652
653 switch($errorCorrectLevel) {
654 case QR_ERROR_CORRECT_LEVEL_L : $e = 0; break;
655 case QR_ERROR_CORRECT_LEVEL_M : $e = 1; break;
656 case QR_ERROR_CORRECT_LEVEL_Q : $e = 2; break;
657 case QR_ERROR_CORRECT_LEVEL_H : $e = 3; break;
658 default :
659 trigger_error("e:$errorCorrectLevel", E_USER_ERROR);
660 }
661
662 switch($mode) {
663 case QR_MODE_NUMBER : $m = 0; break;
664 case QR_MODE_ALPHA_NUM : $m = 1; break;
665 case QR_MODE_8BIT_BYTE : $m = 2; break;
666 case QR_MODE_KANJI : $m = 3; break;
667 default :
668 trigger_error("m:$mode", E_USER_ERROR);
669 }
670
671 return self::$QR_MAX_LENGTH[$t][$e][$m];
672 }
673
674 static function getErrorCorrectPolynomial($errorCorrectLength) {
675
676 $a = new QRPolynomial(array(1) );
677
678 for ($i = 0; $i < $errorCorrectLength; $i++) {
679 $a = $a->multiply(new QRPolynomial(array(1, QRMath::gexp($i) ) ) );
680 }
681
682 return $a;
683 }
684
685 static function getMask($maskPattern, $i, $j) {
686
687 switch ($maskPattern) {
688
689 case QR_MASK_PATTERN000 : return ($i + $j) % 2 == 0;
690 case QR_MASK_PATTERN001 : return $i % 2 == 0;
691 case QR_MASK_PATTERN010 : return $j % 3 == 0;
692 case QR_MASK_PATTERN011 : return ($i + $j) % 3 == 0;
693 case QR_MASK_PATTERN100 : return (floor($i / 2) + floor($j / 3) ) % 2 == 0;
694 case QR_MASK_PATTERN101 : return ($i * $j) % 2 + ($i * $j) % 3 == 0;
695 case QR_MASK_PATTERN110 : return ( ($i * $j) % 2 + ($i * $j) % 3) % 2 == 0;
696 case QR_MASK_PATTERN111 : return ( ($i * $j) % 3 + ($i + $j) % 2) % 2 == 0;
697
698 default :
699 trigger_error("mask:$maskPattern", E_USER_ERROR);
700 }
701 }
702
703 /**
704 * @param \QRCode $qrCode
705 *
706 * @return float|int
707 */
708 static function getLostPoint($qrCode) {
709
710 $moduleCount = $qrCode->getModuleCount();
711
712 $lostPoint = 0;
713
714
715 // LEVEL1
716
717 for ($row = 0; $row < $moduleCount; $row++) {
718
719 for ($col = 0; $col < $moduleCount; $col++) {
720
721 $sameCount = 0;
722 $dark = $qrCode->isDark($row, $col);
723
724 for ($r = -1; $r <= 1; $r++) {
725
726 if ($row + $r < 0 || $moduleCount <= $row + $r) {
727 continue;
728 }
729
730 for ($c = -1; $c <= 1; $c++) {
731
732 if (($col + $c < 0 || $moduleCount <= $col + $c) || ($r == 0 && $c == 0)) {
733 continue;
734 }
735
736 if ($dark == $qrCode->isDark($row + $r, $col + $c) ) {
737 $sameCount++;
738 }
739 }
740 }
741
742 if ($sameCount > 5) {
743 $lostPoint += (3 + $sameCount - 5);
744 }
745 }
746 }
747
748 // LEVEL2
749
750 for ($row = 0; $row < $moduleCount - 1; $row++) {
751 for ($col = 0; $col < $moduleCount - 1; $col++) {
752 $count = 0;
753 if ($qrCode->isDark($row, $col ) ) $count++;
754 if ($qrCode->isDark($row + 1, $col ) ) $count++;
755 if ($qrCode->isDark($row, $col + 1) ) $count++;
756 if ($qrCode->isDark($row + 1, $col + 1) ) $count++;
757 if ($count == 0 || $count == 4) {
758 $lostPoint += 3;
759 }
760 }
761 }
762
763 // LEVEL3
764
765 for ($row = 0; $row < $moduleCount; $row++) {
766 for ($col = 0; $col < $moduleCount - 6; $col++) {
767 if ($qrCode->isDark($row, $col)
768 && !$qrCode->isDark($row, $col + 1)
769 && $qrCode->isDark($row, $col + 2)
770 && $qrCode->isDark($row, $col + 3)
771 && $qrCode->isDark($row, $col + 4)
772 && !$qrCode->isDark($row, $col + 5)
773 && $qrCode->isDark($row, $col + 6) ) {
774 $lostPoint += 40;
775 }
776 }
777 }
778
779 for ($col = 0; $col < $moduleCount; $col++) {
780 for ($row = 0; $row < $moduleCount - 6; $row++) {
781 if ($qrCode->isDark($row, $col)
782 && !$qrCode->isDark($row + 1, $col)
783 && $qrCode->isDark($row + 2, $col)
784 && $qrCode->isDark($row + 3, $col)
785 && $qrCode->isDark($row + 4, $col)
786 && !$qrCode->isDark($row + 5, $col)
787 && $qrCode->isDark($row + 6, $col) ) {
788 $lostPoint += 40;
789 }
790 }
791 }
792
793 // LEVEL4
794
795 $darkCount = 0;
796
797 for ($col = 0; $col < $moduleCount; $col++) {
798 for ($row = 0; $row < $moduleCount; $row++) {
799 if ($qrCode->isDark($row, $col) ) {
800 $darkCount++;
801 }
802 }
803 }
804
805 $ratio = abs(100 * $darkCount / $moduleCount / $moduleCount - 50) / 5;
806 $lostPoint += $ratio * 10;
807
808 return $lostPoint;
809 }
810
811 static function getMode($s) {
812 if (QRUtil::isAlphaNum($s) ) {
813 if (QRUtil::isNumber($s) ) {
814 return QR_MODE_NUMBER;
815 }
816 return QR_MODE_ALPHA_NUM;
817 } else if (QRUtil::isKanji($s) ) {
818 return QR_MODE_KANJI;
819 } else {
820 return QR_MODE_8BIT_BYTE;
821 }
822 }
823
824 static function isNumber($s) {
825 for ($i = 0; $i < strlen($s); $i++) {
826 $c = ord($s[$i]);
827 if (!(QRUtil::toCharCode('0') <= $c && $c <= QRUtil::toCharCode('9') ) ) {
828 return false;
829 }
830 }
831 return true;
832 }
833
834 static function isAlphaNum($s) {
835 for ($i = 0; $i < strlen($s); $i++) {
836 $c = ord($s[$i]);
837 if (!(QRUtil::toCharCode('0') <= $c && $c <= QRUtil::toCharCode('9') )
838 && !(QRUtil::toCharCode('A') <= $c && $c <= QRUtil::toCharCode('Z') )
839 && strpos(" $%*+-./:", $s[$i]) === false) {
840 return false;
841 }
842 }
843 return true;
844 }
845
846 static function isKanji($s) {
847
848 $data = $s;
849
850 $i = 0;
851
852 while ($i + 1 < strlen($data) ) {
853
854 $c = ( (0xff & ord($data[$i]) ) << 8) | (0xff & ord($data[$i + 1]) );
855
856 if (!(0x8140 <= $c && $c <= 0x9FFC) && !(0xE040 <= $c && $c <= 0xEBBF) ) {
857 return false;
858 }
859
860 $i += 2;
861 }
862
863 if ($i < strlen($data) ) {
864 return false;
865 }
866
867 return true;
868 }
869
870 static function toCharCode($s) {
871 return ord($s[0]);
872 }
873
874 static function getBCHTypeInfo($data) {
875 $d = $data << 10;
876 while (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G15) >= 0) {
877 $d ^= (QR_G15 << (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G15) ) );
878 }
879 return ( ($data << 10) | $d) ^ QR_G15_MASK;
880 }
881
882 static function getBCHTypeNumber($data) {
883 $d = $data << 12;
884 while (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G18) >= 0) {
885 $d ^= (QR_G18 << (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G18) ) );
886 }
887 return ($data << 12) | $d;
888 }
889
890 static function getBCHDigit($data) {
891
892 $digit = 0;
893
894 while ($data != 0) {
895 $digit++;
896 $data >>= 1;
897 }
898
899 return $digit;
900 }
901 }
902
903 //---------------------------------------------------------------
904 // QRRSBlock
905 //---------------------------------------------------------------
906
907 class QRRSBlock {
908
909 var $totalCount;
910 var $dataCount;
911
912 static $QR_RS_BLOCK_TABLE = array(
913
914 // L
915 // M
916 // Q
917 // H
918
919 // 1
920 array(1, 26, 19),
921 array(1, 26, 16),
922 array(1, 26, 13),
923 array(1, 26, 9),
924
925 // 2
926 array(1, 44, 34),
927 array(1, 44, 28),
928 array(1, 44, 22),
929 array(1, 44, 16),
930
931 // 3
932 array(1, 70, 55),
933 array(1, 70, 44),
934 array(2, 35, 17),
935 array(2, 35, 13),
936
937 // 4
938 array(1, 100, 80),
939 array(2, 50, 32),
940 array(2, 50, 24),
941 array(4, 25, 9),
942
943 // 5
944 array(1, 134, 108),
945 array(2, 67, 43),
946 array(2, 33, 15, 2, 34, 16),
947 array(2, 33, 11, 2, 34, 12),
948
949 // 6
950 array(2, 86, 68),
951 array(4, 43, 27),
952 array(4, 43, 19),
953 array(4, 43, 15),
954
955 // 7
956 array(2, 98, 78),
957 array(4, 49, 31),
958 array(2, 32, 14, 4, 33, 15),
959 array(4, 39, 13, 1, 40, 14),
960
961 // 8
962 array(2, 121, 97),
963 array(2, 60, 38, 2, 61, 39),
964 array(4, 40, 18, 2, 41, 19),
965 array(4, 40, 14, 2, 41, 15),
966
967 // 9
968 array(2, 146, 116),
969 array(3, 58, 36, 2, 59, 37),
970 array(4, 36, 16, 4, 37, 17),
971 array(4, 36, 12, 4, 37, 13),
972
973 // 10
974 array(2, 86, 68, 2, 87, 69),
975 array(4, 69, 43, 1, 70, 44),
976 array(6, 43, 19, 2, 44, 20),
977 array(6, 43, 15, 2, 44, 16),
978
979 // 11
980 array(4, 101, 81),
981 array(1, 80, 50, 4, 81, 51),
982 array(4, 50, 22, 4, 51, 23),
983 array(3, 36, 12, 8, 37, 13),
984
985 // 12
986 array(2, 116, 92, 2, 117, 93),
987 array(6, 58, 36, 2, 59, 37),
988 array(4, 46, 20, 6, 47, 21),
989 array(7, 42, 14, 4, 43, 15),
990
991 // 13
992 array(4, 133, 107),
993 array(8, 59, 37, 1, 60, 38),
994 array(8, 44, 20, 4, 45, 21),
995 array(12, 33, 11, 4, 34, 12),
996
997 // 14
998 array(3, 145, 115, 1, 146, 116),
999 array(4, 64, 40, 5, 65, 41),
1000 array(11, 36, 16, 5, 37, 17),
1001 array(11, 36, 12, 5, 37, 13),
1002
1003 // 15
1004 array(5, 109, 87, 1, 110, 88),
1005 array(5, 65, 41, 5, 66, 42),
1006 array(5, 54, 24, 7, 55, 25),
1007 array(11, 36, 12, 7, 37, 13),
1008
1009 // 16
1010 array(5, 122, 98, 1, 123, 99),
1011 array(7, 73, 45, 3, 74, 46),
1012 array(15, 43, 19, 2, 44, 20),
1013 array(3, 45, 15, 13, 46, 16),
1014
1015 // 17
1016 array(1, 135, 107, 5, 136, 108),
1017 array(10, 74, 46, 1, 75, 47),
1018 array(1, 50, 22, 15, 51, 23),
1019 array(2, 42, 14, 17, 43, 15),
1020
1021 // 18
1022 array(5, 150, 120, 1, 151, 121),
1023 array(9, 69, 43, 4, 70, 44),
1024 array(17, 50, 22, 1, 51, 23),
1025 array(2, 42, 14, 19, 43, 15),
1026
1027 // 19
1028 array(3, 141, 113, 4, 142, 114),
1029 array(3, 70, 44, 11, 71, 45),
1030 array(17, 47, 21, 4, 48, 22),
1031 array(9, 39, 13, 16, 40, 14),
1032
1033 // 20
1034 array(3, 135, 107, 5, 136, 108),
1035 array(3, 67, 41, 13, 68, 42),
1036 array(15, 54, 24, 5, 55, 25),
1037 array(15, 43, 15, 10, 44, 16),
1038
1039 // 21
1040 array(4, 144, 116, 4, 145, 117),
1041 array(17, 68, 42),
1042 array(17, 50, 22, 6, 51, 23),
1043 array(19, 46, 16, 6, 47, 17),
1044
1045 // 22
1046 array(2, 139, 111, 7, 140, 112),
1047 array(17, 74, 46),
1048 array(7, 54, 24, 16, 55, 25),
1049 array(34, 37, 13),
1050
1051 // 23
1052 array(4, 151, 121, 5, 152, 122),
1053 array(4, 75, 47, 14, 76, 48),
1054 array(11, 54, 24, 14, 55, 25),
1055 array(16, 45, 15, 14, 46, 16),
1056
1057 // 24
1058 array(6, 147, 117, 4, 148, 118),
1059 array(6, 73, 45, 14, 74, 46),
1060 array(11, 54, 24, 16, 55, 25),
1061 array(30, 46, 16, 2, 47, 17),
1062
1063 // 25
1064 array(8, 132, 106, 4, 133, 107),
1065 array(8, 75, 47, 13, 76, 48),
1066 array(7, 54, 24, 22, 55, 25),
1067 array(22, 45, 15, 13, 46, 16),
1068
1069 // 26
1070 array(10, 142, 114, 2, 143, 115),
1071 array(19, 74, 46, 4, 75, 47),
1072 array(28, 50, 22, 6, 51, 23),
1073 array(33, 46, 16, 4, 47, 17),
1074
1075 // 27
1076 array(8, 152, 122, 4, 153, 123),
1077 array(22, 73, 45, 3, 74, 46),
1078 array(8, 53, 23, 26, 54, 24),
1079 array(12, 45, 15, 28, 46, 16),
1080
1081 // 28
1082 array(3, 147, 117, 10, 148, 118),
1083 array(3, 73, 45, 23, 74, 46),
1084 array(4, 54, 24, 31, 55, 25),
1085 array(11, 45, 15, 31, 46, 16),
1086
1087 // 29
1088 array(7, 146, 116, 7, 147, 117),
1089 array(21, 73, 45, 7, 74, 46),
1090 array(1, 53, 23, 37, 54, 24),
1091 array(19, 45, 15, 26, 46, 16),
1092
1093 // 30
1094 array(5, 145, 115, 10, 146, 116),
1095 array(19, 75, 47, 10, 76, 48),
1096 array(15, 54, 24, 25, 55, 25),
1097 array(23, 45, 15, 25, 46, 16),
1098
1099 // 31
1100 array(13, 145, 115, 3, 146, 116),
1101 array(2, 74, 46, 29, 75, 47),
1102 array(42, 54, 24, 1, 55, 25),
1103 array(23, 45, 15, 28, 46, 16),
1104
1105 // 32
1106 array(17, 145, 115),
1107 array(10, 74, 46, 23, 75, 47),
1108 array(10, 54, 24, 35, 55, 25),
1109 array(19, 45, 15, 35, 46, 16),
1110
1111 // 33
1112 array(17, 145, 115, 1, 146, 116),
1113 array(14, 74, 46, 21, 75, 47),
1114 array(29, 54, 24, 19, 55, 25),
1115 array(11, 45, 15, 46, 46, 16),
1116
1117 // 34
1118 array(13, 145, 115, 6, 146, 116),
1119 array(14, 74, 46, 23, 75, 47),
1120 array(44, 54, 24, 7, 55, 25),
1121 array(59, 46, 16, 1, 47, 17),
1122
1123 // 35
1124 array(12, 151, 121, 7, 152, 122),
1125 array(12, 75, 47, 26, 76, 48),
1126 array(39, 54, 24, 14, 55, 25),
1127 array(22, 45, 15, 41, 46, 16),
1128
1129 // 36
1130 array(6, 151, 121, 14, 152, 122),
1131 array(6, 75, 47, 34, 76, 48),
1132 array(46, 54, 24, 10, 55, 25),
1133 array(2, 45, 15, 64, 46, 16),
1134
1135 // 37
1136 array(17, 152, 122, 4, 153, 123),
1137 array(29, 74, 46, 14, 75, 47),
1138 array(49, 54, 24, 10, 55, 25),
1139 array(24, 45, 15, 46, 46, 16),
1140
1141 // 38
1142 array(4, 152, 122, 18, 153, 123),
1143 array(13, 74, 46, 32, 75, 47),
1144 array(48, 54, 24, 14, 55, 25),
1145 array(42, 45, 15, 32, 46, 16),
1146
1147 // 39
1148 array(20, 147, 117, 4, 148, 118),
1149 array(40, 75, 47, 7, 76, 48),
1150 array(43, 54, 24, 22, 55, 25),
1151 array(10, 45, 15, 67, 46, 16),
1152
1153 // 40
1154 array(19, 148, 118, 6, 149, 119),
1155 array(18, 75, 47, 31, 76, 48),
1156 array(34, 54, 24, 34, 55, 25),
1157 array(20, 45, 15, 61, 46, 16)
1158
1159 );
1160
1161 function __construct($totalCount, $dataCount) {
1162 $this->totalCount = $totalCount;
1163 $this->dataCount = $dataCount;
1164 }
1165
1166 function getDataCount() {
1167 return $this->dataCount;
1168 }
1169
1170 function getTotalCount() {
1171 return $this->totalCount;
1172 }
1173
1174 static function getRSBlocks($typeNumber, $errorCorrectLevel) {
1175
1176 $rsBlock = QRRSBlock::getRsBlockTable($typeNumber, $errorCorrectLevel);
1177 $length = count($rsBlock) / 3;
1178
1179 $list = array();
1180
1181 for ($i = 0; $i < $length; $i++) {
1182
1183 $count = $rsBlock[$i * 3 + 0];
1184 $totalCount = $rsBlock[$i * 3 + 1];
1185 $dataCount = $rsBlock[$i * 3 + 2];
1186
1187 for ($j = 0; $j < $count; $j++) {
1188 $list[] = new QRRSBlock($totalCount, $dataCount);
1189 }
1190 }
1191
1192 return $list;
1193 }
1194
1195 static function getRsBlockTable($typeNumber, $errorCorrectLevel) {
1196
1197 switch($errorCorrectLevel) {
1198 case QR_ERROR_CORRECT_LEVEL_L :
1199 return self::$QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 0];
1200 case QR_ERROR_CORRECT_LEVEL_M :
1201 return self::$QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 1];
1202 case QR_ERROR_CORRECT_LEVEL_Q :
1203 return self::$QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 2];
1204 case QR_ERROR_CORRECT_LEVEL_H :
1205 return self::$QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 3];
1206 default :
1207 trigger_error("tn:$typeNumber/ecl:$errorCorrectLevel", E_USER_ERROR);
1208 }
1209 }
1210 }
1211
1212 //---------------------------------------------------------------
1213 // QRNumber
1214 //---------------------------------------------------------------
1215
1216 class QRNumber extends QRData {
1217
1218 function __construct($data) {
1219 parent::__construct(QR_MODE_NUMBER, $data);
1220 }
1221
1222 function write(&$buffer) {
1223
1224 $data = $this->getData();
1225
1226 $i = 0;
1227
1228 while ($i + 2 < strlen($data) ) {
1229 $num = QRNumber::parseInt(substr($data, $i, 3) );
1230 $buffer->put($num, 10);
1231 $i += 3;
1232 }
1233
1234 if ($i < strlen($data) ) {
1235
1236 if (strlen($data) - $i == 1) {
1237 $num = QRNumber::parseInt(substr($data, $i, $i + 1) );
1238 $buffer->put($num, 4);
1239 } else if (strlen($data) - $i == 2) {
1240 $num = QRNumber::parseInt(substr($data, $i, $i + 2) );
1241 $buffer->put($num, 7);
1242 }
1243 }
1244 }
1245
1246 static function parseInt($s) {
1247
1248 $num = 0;
1249 for ($i = 0; $i < strlen($s); $i++) {
1250 $num = $num * 10 + QRNumber::parseIntAt(ord($s[$i]) );
1251 }
1252 return $num;
1253 }
1254
1255 static function parseIntAt($c) {
1256
1257 if (QRUtil::toCharCode('0') <= $c && $c <= QRUtil::toCharCode('9') ) {
1258 return $c - QRUtil::toCharCode('0');
1259 }
1260
1261 trigger_error("illegal char : $c", E_USER_ERROR);
1262 }
1263 }
1264
1265 //---------------------------------------------------------------
1266 // QRKanji
1267 //---------------------------------------------------------------
1268
1269 class QRKanji extends QRData {
1270
1271 function __construct($data) {
1272 parent::__construct(QR_MODE_KANJI, $data);
1273 }
1274
1275 function write(&$buffer) {
1276
1277 $data = $this->getData();
1278
1279 $i = 0;
1280
1281 while ($i + 1 < strlen($data) ) {
1282
1283 $c = ( (0xff & ord($data[$i]) ) << 8) | (0xff & ord($data[$i + 1]) );
1284
1285 if (0x8140 <= $c && $c <= 0x9FFC) {
1286 $c -= 0x8140;
1287 } else if (0xE040 <= $c && $c <= 0xEBBF) {
1288 $c -= 0xC140;
1289 } else {
1290 trigger_error("illegal char at " . ($i + 1) . "/$c", E_USER_ERROR);
1291 }
1292
1293 $c = ( ($c >> 8) & 0xff) * 0xC0 + ($c & 0xff);
1294
1295 $buffer->put($c, 13);
1296
1297 $i += 2;
1298 }
1299
1300 if ($i < strlen($data) ) {
1301 trigger_error("illegal char at " . ($i + 1), E_USER_ERROR);
1302 }
1303 }
1304
1305 function getLength() {
1306 return floor(strlen($this->getData() ) / 2);
1307 }
1308 }
1309
1310 //---------------------------------------------------------------
1311 // QRAlphaNum
1312 //---------------------------------------------------------------
1313
1314 class QRAlphaNum extends QRData {
1315
1316 function __construct($data) {
1317 parent::__construct(QR_MODE_ALPHA_NUM, $data);
1318 }
1319
1320 function write(&$buffer) {
1321
1322 $i = 0;
1323 $c = $this->getData();
1324
1325 while ($i + 1 < strlen($c) ) {
1326 $buffer->put(QRAlphaNum::getCode(ord($c[$i]) ) * 45
1327 + QRAlphaNum::getCode(ord($c[$i + 1]) ), 11);
1328 $i += 2;
1329 }
1330
1331 if ($i < strlen($c) ) {
1332 $buffer->put(QRAlphaNum::getCode(ord($c[$i])), 6);
1333 }
1334 }
1335
1336 static function getCode($c) {
1337
1338 if (QRUtil::toCharCode('0') <= $c
1339 && $c <= QRUtil::toCharCode('9') ) {
1340 return $c - QRUtil::toCharCode('0');
1341 } else if (QRUtil::toCharCode('A') <= $c
1342 && $c <= QRUtil::toCharCode('Z') ) {
1343 return $c - QRUtil::toCharCode('A') + 10;
1344 } else {
1345 switch ($c) {
1346 case QRUtil::toCharCode(' ') : return 36;
1347 case QRUtil::toCharCode('$') : return 37;
1348 case QRUtil::toCharCode('%') : return 38;
1349 case QRUtil::toCharCode('*') : return 39;
1350 case QRUtil::toCharCode('+') : return 40;
1351 case QRUtil::toCharCode('-') : return 41;
1352 case QRUtil::toCharCode('.') : return 42;
1353 case QRUtil::toCharCode('/') : return 43;
1354 case QRUtil::toCharCode(':') : return 44;
1355 default :
1356 trigger_error("illegal char : $c", E_USER_ERROR);
1357 }
1358 }
1359
1360 }
1361 }
1362
1363 //---------------------------------------------------------------
1364 // QR8BitByte
1365 //---------------------------------------------------------------
1366
1367 class QR8BitByte extends QRData {
1368
1369 function __construct($data) {
1370 parent::__construct(QR_MODE_8BIT_BYTE, $data);
1371 }
1372
1373 function write(&$buffer) {
1374
1375 $data = $this->getData();
1376 for ($i = 0; $i < strlen($data); $i++) {
1377 $buffer->put(ord($data[$i]), 8);
1378 }
1379 }
1380
1381 }
1382
1383 //---------------------------------------------------------------
1384 // QRData
1385 //---------------------------------------------------------------
1386
1387 abstract class QRData {
1388
1389 var $mode;
1390
1391 var $data;
1392
1393 function __construct($mode, $data) {
1394 $this->mode = $mode;
1395 $this->data = $data;
1396 }
1397
1398 function getMode() {
1399 return $this->mode;
1400 }
1401
1402 function getData() {
1403 return $this->data;
1404 }
1405
1406 /**
1407 * @return int
1408 */
1409 function getLength() {
1410 return strlen($this->getData() );
1411 }
1412
1413 /**
1414 * @param \QRBitBuffer $buffer
1415 */
1416 abstract function write(&$buffer);
1417
1418 function getLengthInBits($type) {
1419
1420 if (1 <= $type && $type < 10) {
1421
1422 // 1 - 9
1423
1424 switch($this->mode) {
1425 case QR_MODE_NUMBER : return 10;
1426 case QR_MODE_ALPHA_NUM : return 9;
1427 case QR_MODE_8BIT_BYTE : return 8;
1428 case QR_MODE_KANJI : return 8;
1429 default :
1430 trigger_error("mode:$this->mode", E_USER_ERROR);
1431 }
1432
1433 } else if ($type < 27) {
1434
1435 // 10 - 26
1436
1437 switch($this->mode) {
1438 case QR_MODE_NUMBER : return 12;
1439 case QR_MODE_ALPHA_NUM : return 11;
1440 case QR_MODE_8BIT_BYTE : return 16;
1441 case QR_MODE_KANJI : return 10;
1442 default :
1443 trigger_error("mode:$this->mode", E_USER_ERROR);
1444 }
1445
1446 } else if ($type < 41) {
1447
1448 // 27 - 40
1449
1450 switch($this->mode) {
1451 case QR_MODE_NUMBER : return 14;
1452 case QR_MODE_ALPHA_NUM : return 13;
1453 case QR_MODE_8BIT_BYTE : return 16;
1454 case QR_MODE_KANJI : return 12;
1455 default :
1456 trigger_error("mode:$this->mode", E_USER_ERROR);
1457 }
1458
1459 } else {
1460 trigger_error("mode:$this->mode", E_USER_ERROR);
1461 }
1462 }
1463
1464 }
1465
1466 //---------------------------------------------------------------
1467 // QRMath
1468 //---------------------------------------------------------------
1469
1470 class QRMath {
1471
1472 static $QR_MATH_EXP_TABLE = null;
1473 static $QR_MATH_LOG_TABLE = null;
1474
1475 static function init() {
1476
1477 self::$QR_MATH_EXP_TABLE = QRMath::createNumArray(256);
1478
1479 for ($i = 0; $i < 8; $i++) {
1480 self::$QR_MATH_EXP_TABLE[$i] = 1 << $i;
1481 }
1482
1483 for ($i = 8; $i < 256; $i++) {
1484 self::$QR_MATH_EXP_TABLE[$i] = self::$QR_MATH_EXP_TABLE[$i - 4]
1485 ^ self::$QR_MATH_EXP_TABLE[$i - 5]
1486 ^ self::$QR_MATH_EXP_TABLE[$i - 6]
1487 ^ self::$QR_MATH_EXP_TABLE[$i - 8];
1488 }
1489
1490 self::$QR_MATH_LOG_TABLE = QRMath::createNumArray(256);
1491
1492 for ($i = 0; $i < 255; $i++) {
1493 self::$QR_MATH_LOG_TABLE[self::$QR_MATH_EXP_TABLE[$i] ] = $i;
1494 }
1495 }
1496
1497 static function createNumArray($length) {
1498 $num_array = array();
1499 for ($i = 0; $i < $length; $i++) {
1500 $num_array[] = 0;
1501 }
1502 return $num_array;
1503 }
1504
1505 static function glog($n) {
1506
1507 if ($n < 1) {
1508 trigger_error("log($n)", E_USER_ERROR);
1509 }
1510
1511 return self::$QR_MATH_LOG_TABLE[$n];
1512 }
1513
1514 static function gexp($n) {
1515
1516 while ($n < 0) {
1517 $n += 255;
1518 }
1519
1520 while ($n >= 256) {
1521 $n -= 255;
1522 }
1523
1524 return self::$QR_MATH_EXP_TABLE[$n];
1525 }
1526 }
1527
1528 // init static table
1529 QRMath::init();
1530
1531 //---------------------------------------------------------------
1532 // QRPolynomial
1533 //---------------------------------------------------------------
1534
1535 class QRPolynomial {
1536
1537 var $num;
1538
1539 function __construct($num, $shift = 0) {
1540
1541 $offset = 0;
1542
1543 while ($offset < count($num) && $num[$offset] == 0) {
1544 $offset++;
1545 }
1546
1547 $this->num = QRMath::createNumArray(count($num) - $offset + $shift);
1548 for ($i = 0; $i < count($num) - $offset; $i++) {
1549 $this->num[$i] = $num[$i + $offset];
1550 }
1551 }
1552
1553 function get($index) {
1554 return $this->num[$index];
1555 }
1556
1557 function getLength() {
1558 return count($this->num);
1559 }
1560
1561 // PHP5
1562 function __toString() {
1563 return $this->toString();
1564 }
1565
1566 function toString() {
1567
1568 $buffer = "";
1569
1570 for ($i = 0; $i < $this->getLength(); $i++) {
1571 if ($i > 0) {
1572 $buffer .= ",";
1573 }
1574 $buffer .= $this->get($i);
1575 }
1576
1577 return $buffer;
1578 }
1579
1580 function toLogString() {
1581
1582 $buffer = "";
1583
1584 for ($i = 0; $i < $this->getLength(); $i++) {
1585 if ($i > 0) {
1586 $buffer .= ",";
1587 }
1588 $buffer .= QRMath::glog($this->get($i) );
1589 }
1590
1591 return $buffer;
1592 }
1593
1594 /**
1595 * @param \QRPolynomial $e
1596 *
1597 * @return \QRPolynomial
1598 */
1599 function multiply($e) {
1600
1601 $num = QRMath::createNumArray($this->getLength() + $e->getLength() - 1);
1602
1603 for ($i = 0; $i < $this->getLength(); $i++) {
1604 $vi = QRMath::glog($this->get($i) );
1605
1606 for ($j = 0; $j < $e->getLength(); $j++) {
1607 $num[$i + $j] ^= QRMath::gexp($vi + QRMath::glog($e->get($j) ) );
1608 }
1609 }
1610
1611 return new QRPolynomial($num);
1612 }
1613
1614 /**
1615 * @param \QRPolynomial $e
1616 *
1617 * @return $this|\QRPolynomial
1618 */
1619 function mod($e) {
1620
1621 if ($this->getLength() - $e->getLength() < 0) {
1622 return $this;
1623 }
1624
1625 $ratio = QRMath::glog($this->get(0) ) - QRMath::glog($e->get(0) );
1626
1627 $num = QRMath::createNumArray($this->getLength() );
1628 for ($i = 0; $i < $this->getLength(); $i++) {
1629 $num[$i] = $this->get($i);
1630 }
1631
1632 for ($i = 0; $i < $e->getLength(); $i++) {
1633 $num[$i] ^= QRMath::gexp(QRMath::glog($e->get($i) ) + $ratio);
1634 }
1635
1636 $newPolynomial = new QRPolynomial($num);
1637 return $newPolynomial->mod($e);
1638 }
1639 }
1640
1641 //---------------------------------------------------------------
1642 // Mode
1643 //---------------------------------------------------------------
1644
1645 define("QR_MODE_NUMBER", 1 << 0);
1646 define("QR_MODE_ALPHA_NUM", 1 << 1);
1647 define("QR_MODE_8BIT_BYTE", 1 << 2);
1648 define("QR_MODE_KANJI", 1 << 3);
1649
1650 //---------------------------------------------------------------
1651 // MaskPattern
1652 //---------------------------------------------------------------
1653
1654 define("QR_MASK_PATTERN000", 0);
1655 define("QR_MASK_PATTERN001", 1);
1656 define("QR_MASK_PATTERN010", 2);
1657 define("QR_MASK_PATTERN011", 3);
1658 define("QR_MASK_PATTERN100", 4);
1659 define("QR_MASK_PATTERN101", 5);
1660 define("QR_MASK_PATTERN110", 6);
1661 define("QR_MASK_PATTERN111", 7);
1662
1663 //---------------------------------------------------------------
1664 // ErrorCorrectLevel
1665
1666 // 7%.
1667 define("QR_ERROR_CORRECT_LEVEL_L", 1);
1668 // 15%.
1669 define("QR_ERROR_CORRECT_LEVEL_M", 0);
1670 // 25%.
1671 define("QR_ERROR_CORRECT_LEVEL_Q", 3);
1672 // 30%.
1673 define("QR_ERROR_CORRECT_LEVEL_H", 2);
1674
1675
1676 //---------------------------------------------------------------
1677 // QRBitBuffer
1678 //---------------------------------------------------------------
1679
1680 class QRBitBuffer {
1681
1682 var $buffer;
1683 var $length;
1684
1685 function __construct() {
1686 $this->buffer = array();
1687 $this->length = 0;
1688 }
1689
1690 function getBuffer() {
1691 return $this->buffer;
1692 }
1693
1694 function getLengthInBits() {
1695 return $this->length;
1696 }
1697
1698 function __toString() {
1699 $buffer = "";
1700 for ($i = 0; $i < $this->getLengthInBits(); $i++) {
1701 $buffer .= $this->get($i)? '1' : '0';
1702 }
1703 return $buffer;
1704 }
1705
1706 function get($index) {
1707 $bufIndex = (int)floor($index / 8);
1708 return ( ($this->buffer[$bufIndex] >> (7 - $index % 8) ) & 1) == 1;
1709 }
1710
1711 function put($num, $length) {
1712
1713 for ($i = 0; $i < $length; $i++) {
1714 $this->putBit( ( ($num >> ($length - $i - 1) ) & 1) == 1);
1715 }
1716 }
1717
1718 function putBit($bit) {
1719
1720 $bufIndex = (int)floor($this->length / 8);
1721 if (count($this->buffer) <= $bufIndex) {
1722 $this->buffer[] = 0;
1723 }
1724
1725 if ($bit) {
1726 $this->buffer[$bufIndex] |= (0x80 >> ($this->length % 8) );
1727 }
1728
1729 $this->length++;
1730 }
1731 }
1732
1733 ?>
1734