]>
Raphaƫl G. Git Repositories - cdn/blob - vendor/phpqrcode/qrspec.php
   5  * QR Code specifications 
   7  * Based on libqrencode C library distributed under LGPL 2.1 
   8  * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 
  10  * PHP QR Code is distributed under LGPL 3 
  11  * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 
  13  * The following data / specifications are taken from 
  14  * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) 
  16  * "Automatic identification and data capture techniques --  
  17  *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) 
  19  * This library is free software; you can redistribute it and/or 
  20  * modify it under the terms of the GNU Lesser General Public 
  21  * License as published by the Free Software Foundation; either 
  22  * version 3 of the License, or any later version. 
  24  * This library is distributed in the hope that it will be useful, 
  25  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
  27  * Lesser General Public License for more details. 
  29  * You should have received a copy of the GNU Lesser General Public 
  30  * License along with this library; if not, write to the Free Software 
  31  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 
  34     define('QRSPEC_VERSION_MAX', 40); 
  35     define('QRSPEC_WIDTH_MAX',   177); 
  37     define('QRCAP_WIDTH',        0); 
  38     define('QRCAP_WORDS',        1); 
  39     define('QRCAP_REMINDER',     2); 
  40     define('QRCAP_EC',           3); 
  44         public static $capacity = array( 
  45             array(  0,    0, 0, array(   0,    0,    0,    0)), 
  46             array( 21,   26, 0, array(   7,   10,   13,   17)), // 1 
  47             array( 25,   44, 7, array(  10,   16,   22,   28)), 
  48             array( 29,   70, 7, array(  15,   26,   36,   44)), 
  49             array( 33,  100, 7, array(  20,   36,   52,   64)), 
  50             array( 37,  134, 7, array(  26,   48,   72,   88)), // 5 
  51             array( 41,  172, 7, array(  36,   64,   96,  112)), 
  52             array( 45,  196, 0, array(  40,   72,  108,  130)), 
  53             array( 49,  242, 0, array(  48,   88,  132,  156)), 
  54             array( 53,  292, 0, array(  60,  110,  160,  192)), 
  55             array( 57,  346, 0, array(  72,  130,  192,  224)), //10 
  56             array( 61,  404, 0, array(  80,  150,  224,  264)), 
  57             array( 65,  466, 0, array(  96,  176,  260,  308)), 
  58             array( 69,  532, 0, array( 104,  198,  288,  352)), 
  59             array( 73,  581, 3, array( 120,  216,  320,  384)), 
  60             array( 77,  655, 3, array( 132,  240,  360,  432)), //15 
  61             array( 81,  733, 3, array( 144,  280,  408,  480)), 
  62             array( 85,  815, 3, array( 168,  308,  448,  532)), 
  63             array( 89,  901, 3, array( 180,  338,  504,  588)), 
  64             array( 93,  991, 3, array( 196,  364,  546,  650)), 
  65             array( 97, 1085, 3, array( 224,  416,  600,  700)), //20 
  66             array(101, 1156, 4, array( 224,  442,  644,  750)), 
  67             array(105, 1258, 4, array( 252,  476,  690,  816)), 
  68             array(109, 1364, 4, array( 270,  504,  750,  900)), 
  69             array(113, 1474, 4, array( 300,  560,  810,  960)), 
  70             array(117, 1588, 4, array( 312,  588,  870, 1050)), //25 
  71             array(121, 1706, 4, array( 336,  644,  952, 1110)), 
  72             array(125, 1828, 4, array( 360,  700, 1020, 1200)), 
  73             array(129, 1921, 3, array( 390,  728, 1050, 1260)), 
  74             array(133, 2051, 3, array( 420,  784, 1140, 1350)), 
  75             array(137, 2185, 3, array( 450,  812, 1200, 1440)), //30 
  76             array(141, 2323, 3, array( 480,  868, 1290, 1530)), 
  77             array(145, 2465, 3, array( 510,  924, 1350, 1620)), 
  78             array(149, 2611, 3, array( 540,  980, 1440, 1710)), 
  79             array(153, 2761, 3, array( 570, 1036, 1530, 1800)), 
  80             array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35 
  81             array(161, 3034, 0, array( 600, 1120, 1680, 1980)), 
  82             array(165, 3196, 0, array( 630, 1204, 1770, 2100)), 
  83             array(169, 3362, 0, array( 660, 1260, 1860, 2220)), 
  84             array(173, 3532, 0, array( 720, 1316, 1950, 2310)), 
  85             array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40 
  88         //---------------------------------------------------------------------- 
  89         public static function getDataLength($version, $level) 
  91             return self
::$capacity[$version][QRCAP_WORDS
] - self
::$capacity[$version][QRCAP_EC
][$level]; 
  94         //---------------------------------------------------------------------- 
  95         public static function getECCLength($version, $level) 
  97             return self
::$capacity[$version][QRCAP_EC
][$level]; 
 100         //---------------------------------------------------------------------- 
 101         public static function getWidth($version) 
 103             return self
::$capacity[$version][QRCAP_WIDTH
]; 
 106         //---------------------------------------------------------------------- 
 107         public static function getRemainder($version) 
 109             return self
::$capacity[$version][QRCAP_REMINDER
]; 
 112         //---------------------------------------------------------------------- 
 113         public static function getMinimumVersion($size, $level) 
 116             for($i=1; $i<= QRSPEC_VERSION_MAX
; $i++
) { 
 117                 $words  = self
::$capacity[$i][QRCAP_WORDS
] - self
::$capacity[$i][QRCAP_EC
][$level]; 
 125         //###################################################################### 
 127         public static $lengthTableBits = array( 
 134         //---------------------------------------------------------------------- 
 135         public static function lengthIndicator($mode, $version) 
 137             if ($mode == QR_MODE_STRUCTURE
) 
 142             } else if ($version <= 26) { 
 148             return self
::$lengthTableBits[$mode][$l]; 
 151         //---------------------------------------------------------------------- 
 152         public static function maximumWords($mode, $version) 
 154             if($mode == QR_MODE_STRUCTURE
)  
 159             } else if($version <= 26) { 
 165             $bits = self
::$lengthTableBits[$mode][$l]; 
 166             $words = (1 << $bits) - 1; 
 168             if($mode == QR_MODE_KANJI
) { 
 169                 $words *= 2; // the number of bytes is required 
 175         // Error correction code ----------------------------------------------- 
 176         // Table of the error correction code (Reed-Solomon block) 
 177         // See Table 12-16 (pp.30-36), JIS X0510:2004. 
 179         public static $eccTable = array( 
 180             array(array( 0,  0), array( 0,  0), array( 0,  0), array( 0,  0)), 
 181             array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)), // 1 
 182             array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)), 
 183             array(array( 1,  0), array( 1,  0), array( 2,  0), array( 2,  0)), 
 184             array(array( 1,  0), array( 2,  0), array( 2,  0), array( 4,  0)), 
 185             array(array( 1,  0), array( 2,  0), array( 2,  2), array( 2,  2)), // 5 
 186             array(array( 2,  0), array( 4,  0), array( 4,  0), array( 4,  0)), 
 187             array(array( 2,  0), array( 4,  0), array( 2,  4), array( 4,  1)), 
 188             array(array( 2,  0), array( 2,  2), array( 4,  2), array( 4,  2)), 
 189             array(array( 2,  0), array( 3,  2), array( 4,  4), array( 4,  4)), 
 190             array(array( 2,  2), array( 4,  1), array( 6,  2), array( 6,  2)), //10 
 191             array(array( 4,  0), array( 1,  4), array( 4,  4), array( 3,  8)), 
 192             array(array( 2,  2), array( 6,  2), array( 4,  6), array( 7,  4)), 
 193             array(array( 4,  0), array( 8,  1), array( 8,  4), array(12,  4)), 
 194             array(array( 3,  1), array( 4,  5), array(11,  5), array(11,  5)), 
 195             array(array( 5,  1), array( 5,  5), array( 5,  7), array(11,  7)), //15 
 196             array(array( 5,  1), array( 7,  3), array(15,  2), array( 3, 13)), 
 197             array(array( 1,  5), array(10,  1), array( 1, 15), array( 2, 17)), 
 198             array(array( 5,  1), array( 9,  4), array(17,  1), array( 2, 19)), 
 199             array(array( 3,  4), array( 3, 11), array(17,  4), array( 9, 16)), 
 200             array(array( 3,  5), array( 3, 13), array(15,  5), array(15, 10)), //20 
 201             array(array( 4,  4), array(17,  0), array(17,  6), array(19,  6)), 
 202             array(array( 2,  7), array(17,  0), array( 7, 16), array(34,  0)), 
 203             array(array( 4,  5), array( 4, 14), array(11, 14), array(16, 14)), 
 204             array(array( 6,  4), array( 6, 14), array(11, 16), array(30,  2)), 
 205             array(array( 8,  4), array( 8, 13), array( 7, 22), array(22, 13)), //25 
 206             array(array(10,  2), array(19,  4), array(28,  6), array(33,  4)), 
 207             array(array( 8,  4), array(22,  3), array( 8, 26), array(12, 28)), 
 208             array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)), 
 209             array(array( 7,  7), array(21,  7), array( 1, 37), array(19, 26)), 
 210             array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30 
 211             array(array(13,  3), array( 2, 29), array(42,  1), array(23, 28)), 
 212             array(array(17,  0), array(10, 23), array(10, 35), array(19, 35)), 
 213             array(array(17,  1), array(14, 21), array(29, 19), array(11, 46)), 
 214             array(array(13,  6), array(14, 23), array(44,  7), array(59,  1)), 
 215             array(array(12,  7), array(12, 26), array(39, 14), array(22, 41)), //35 
 216             array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)), 
 217             array(array(17,  4), array(29, 14), array(49, 10), array(24, 46)), 
 218             array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)), 
 219             array(array(20,  4), array(40,  7), array(43, 22), array(10, 67)), 
 220             array(array(19,  6), array(18, 31), array(34, 34), array(20, 61)),//40 
 223         //---------------------------------------------------------------------- 
 226         public static function getEccSpec($version, $level, array &$spec) 
 228             if (count($spec) < 5) { 
 229                 $spec = array(0,0,0,0,0); 
 232             $b1   = self
::$eccTable[$version][$level][0]; 
 233             $b2   = self
::$eccTable[$version][$level][1]; 
 234             $data = self
::getDataLength($version, $level); 
 235             $ecc  = self
::getECCLength($version, $level); 
 239                 $spec[1] = (int)($data / $b1); 
 240                 $spec[2] = (int)($ecc / $b1); 
 245                 $spec[1] = (int)($data / ($b1 + 
$b2)); 
 246                 $spec[2] = (int)($ecc  / ($b1 + 
$b2)); 
 248                 $spec[4] = $spec[1] + 
1; 
 252         // Alignment pattern --------------------------------------------------- 
 254         // Positions of alignment patterns. 
 255         // This array includes only the second and the third position of the  
 256         // alignment patterns. Rest of them can be calculated from the distance  
 259         // See Table 1 in Appendix E (pp.71) of JIS X0510:2004. 
 261         public static $alignmentPattern = array(       
 263             array( 0,  0), array(18,  0), array(22,  0), array(26,  0), array(30,  0), // 1- 5 
 264             array(34,  0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10 
 265             array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15 
 266             array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20 
 267             array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25 
 268             array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30 
 269             array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35 
 270             array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40 
 274         /** -------------------------------------------------------------------- 
 275          * Put an alignment marker. 
 278          * @param ox,oy center coordinate of the pattern 
 280         public static function putAlignmentMarker(array &$frame, $ox, $oy) 
 283                 "\xa1\xa1\xa1\xa1\xa1", 
 284                 "\xa1\xa0\xa0\xa0\xa1", 
 285                 "\xa1\xa0\xa1\xa0\xa1", 
 286                 "\xa1\xa0\xa0\xa0\xa1", 
 287                 "\xa1\xa1\xa1\xa1\xa1" 
 293             for($y=0; $y<5; $y++
) { 
 294                 QRstr
::set($frame, $xStart, $yStart+
$y, $finder[$y]); 
 298         //---------------------------------------------------------------------- 
 299         public static function putAlignmentPattern($version, &$frame, $width) 
 304             $d = self
::$alignmentPattern[$version][1] - self
::$alignmentPattern[$version][0]; 
 308                 $w = (int)(($width - self
::$alignmentPattern[$version][0]) / $d + 
2); 
 311             if($w * $w - 3 == 1) { 
 312                 $x = self
::$alignmentPattern[$version][0]; 
 313                 $y = self
::$alignmentPattern[$version][0]; 
 314                 self
::putAlignmentMarker($frame, $x, $y); 
 318             $cx = self
::$alignmentPattern[$version][0]; 
 319             for($x=1; $x<$w - 1; $x++
) { 
 320                 self
::putAlignmentMarker($frame, 6, $cx); 
 321                 self
::putAlignmentMarker($frame, $cx,  6); 
 325             $cy = self
::$alignmentPattern[$version][0]; 
 326             for($y=0; $y<$w-1; $y++
) { 
 327                 $cx = self
::$alignmentPattern[$version][0]; 
 328                 for($x=0; $x<$w-1; $x++
) { 
 329                     self
::putAlignmentMarker($frame, $cx, $cy); 
 336         // Version information pattern ----------------------------------------- 
 338                 // Version information pattern (BCH coded). 
 339         // See Table 1 in Appendix D (pp.68) of JIS X0510:2004. 
 341                 // size: [QRSPEC_VERSION_MAX - 6] 
 343         public static $versionPattern = array( 
 344             0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, 
 345             0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, 
 346             0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, 
 347             0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, 
 351         //---------------------------------------------------------------------- 
 352         public static function getVersionPattern($version) 
 354             if($version < 7 || $version > QRSPEC_VERSION_MAX
) 
 357             return self
::$versionPattern[$version -7]; 
 360         // Format information -------------------------------------------------- 
 361         // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib) 
 363         public static $formatInfo = array( 
 364             array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), 
 365             array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0), 
 366             array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed), 
 367             array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b) 
 370         public static function getFormatInfo($mask, $level) 
 372             if($mask < 0 || $mask > 7) 
 375             if($level < 0 || $level > 3) 
 378             return self
::$formatInfo[$level][$mask]; 
 381         // Frame --------------------------------------------------------------- 
 382         // Cache of initial frames. 
 384         public static $frames = array(); 
 386         /** -------------------------------------------------------------------- 
 387          * Put a finder pattern. 
 390          * @param ox,oy upper-left coordinate of the pattern 
 392         public static function putFinderPattern(&$frame, $ox, $oy) 
 395                 "\xc1\xc1\xc1\xc1\xc1\xc1\xc1", 
 396                 "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", 
 397                 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", 
 398                 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", 
 399                 "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", 
 400                 "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", 
 401                 "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" 
 404             for($y=0; $y<7; $y++
) { 
 405                 QRstr
::set($frame, $ox, $oy+
$y, $finder[$y]); 
 409         //---------------------------------------------------------------------- 
 410         public static function createFrame($version) 
 412             $width = self
::$capacity[$version][QRCAP_WIDTH
]; 
 413             $frameLine = str_repeat ("\0", $width); 
 414             $frame = array_fill(0, $width, $frameLine); 
 417             self
::putFinderPattern($frame, 0, 0); 
 418             self
::putFinderPattern($frame, $width - 7, 0); 
 419             self
::putFinderPattern($frame, 0, $width - 7); 
 422             $yOffset = $width - 7; 
 424             for($y=0; $y<7; $y++
) { 
 425                 $frame[$y][7] = "\xc0"; 
 426                 $frame[$y][$width - 8] = "\xc0"; 
 427                 $frame[$yOffset][7] = "\xc0"; 
 431             $setPattern = str_repeat("\xc0", 8); 
 433             QRstr
::set($frame, 0, 7, $setPattern); 
 434             QRstr
::set($frame, $width-8, 7, $setPattern); 
 435             QRstr
::set($frame, 0, $width - 8, $setPattern); 
 438             $setPattern = str_repeat("\x84", 9); 
 439             QRstr
::set($frame, 0, 8, $setPattern); 
 440             QRstr
::set($frame, $width - 8, 8, $setPattern, 8); 
 442             $yOffset = $width - 8; 
 444             for($y=0; $y<8; $y++
,$yOffset++
) { 
 445                 $frame[$y][8] = "\x84"; 
 446                 $frame[$yOffset][8] = "\x84"; 
 451             for($i=1; $i<$width-15; $i++
) { 
 452                 $frame[6][7+
$i] = chr(0x90 | ($i & 1)); 
 453                 $frame[7+
$i][6] = chr(0x90 | ($i & 1)); 
 457             self
::putAlignmentPattern($version, $frame, $width); 
 459             // Version information  
 461                 $vinf = self
::getVersionPattern($version); 
 465                 for($x=0; $x<6; $x++
) { 
 466                     for($y=0; $y<3; $y++
) { 
 467                         $frame[($width - 11)+
$y][$x] = chr(0x88 | ($v & 1)); 
 473                 for($y=0; $y<6; $y++
) { 
 474                     for($x=0; $x<3; $x++
) { 
 475                         $frame[$y][$x+
($width - 11)] = chr(0x88 | ($v & 1)); 
 481             // and a little bit...   
 482             $frame[$width - 8][8] = "\x81"; 
 487         //---------------------------------------------------------------------- 
 488         public static function debug($frame, $binary_mode = false) 
 492                     foreach ($frame as &$frameLine) { 
 493                         $frameLine = join('<span class="m">  </span>', explode('0', $frameLine)); 
 494                         $frameLine = join('██', explode('1', $frameLine)); 
 499                     .m { background
-color
: white
; } 
 502                     echo '<pre><tt><br/ ><br/ ><br/ >        '; 
 503                     echo join("<br/ >        ", $frame); 
 504                     echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >'; 
 508                 foreach ($frame as &$frameLine) { 
 509                     $frameLine = join('<span class="m"> </span>',  explode("\xc0", $frameLine)); 
 510                     $frameLine = join('<span class="m">▒</span>', explode("\xc1", $frameLine)); 
 511                     $frameLine = join('<span class="p"> </span>',  explode("\xa0", $frameLine)); 
 512                     $frameLine = join('<span class="p">▒</span>', explode("\xa1", $frameLine)); 
 513                     $frameLine = join('<span class="s">◇</span>', explode("\x84", $frameLine)); //format 0 
 514                     $frameLine = join('<span class="s">◆</span>', explode("\x85", $frameLine)); //format 1 
 515                     $frameLine = join('<span class="x">☢</span>', explode("\x81", $frameLine)); //special bit 
 516                     $frameLine = join('<span class="c"> </span>',  explode("\x90", $frameLine)); //clock 0 
 517                     $frameLine = join('<span class="c">◷</span>', explode("\x91", $frameLine)); //clock 1 
 518                     $frameLine = join('<span class="f"> </span>',  explode("\x88", $frameLine)); //version 
 519                     $frameLine = join('<span class="f">▒</span>', explode("\x89", $frameLine)); //version 
 520                     $frameLine = join('♦', explode("\x01", $frameLine)); 
 521                     $frameLine = join('⋅', explode("\0", $frameLine)); 
 526                     .p { background
-color
: yellow
; } 
 527                     .m { background
-color
: #00FF00; } 
 528                     .s { background
-color
: #FF0000; } 
 529                     .c { background
-color
: aqua
; } 
 530                     .x { background
-color
: pink
; } 
 531                     .f { background
-color
: gold
; } 
 535                 echo join("<br/ >", $frame); 
 541         //---------------------------------------------------------------------- 
 542         public static function serial($frame) 
 544             return gzcompress(join("\n", $frame), 9); 
 547         //---------------------------------------------------------------------- 
 548         public static function unserial($code) 
 550             return explode("\n", gzuncompress($code)); 
 553         //---------------------------------------------------------------------- 
 554         public static function newFrame($version) 
 556             if($version < 1 || $version > QRSPEC_VERSION_MAX
)  
 559             if(!isset(self
::$frames[$version])) { 
 561                 $fileName = QR_CACHE_DIR
.'frame_'.$version.'.dat'; 
 564                     if (file_exists($fileName)) { 
 565                         self
::$frames[$version] = self
::unserial(file_get_contents($fileName)); 
 567                         self
::$frames[$version] = self
::createFrame($version); 
 568                         file_put_contents($fileName, self
::serial(self
::$frames[$version])); 
 571                     self
::$frames[$version] = self
::createFrame($version); 
 575             if(is_null(self
::$frames[$version])) 
 578             return self
::$frames[$version]; 
 581         //---------------------------------------------------------------------- 
 582         public static function rsBlockNum($spec)     { return $spec
[0] + $spec
[3]; } 
 583         public static function rsBlockNum1($spec)    { return $spec
[0]; } 
 584         public static function rsDataCodes1($spec)   { return $spec
[1]; } 
 585         public static function rsEccCodes1($spec)    { return $spec
[2]; } 
 586         public static function rsBlockNum2($spec)    { return $spec
[3]; } 
 587         public static function rsDataCodes2($spec)   { return $spec
[4]; } 
 588         public static function rsEccCodes2($spec)    { return $spec
[2]; } 
 589         public static function rsDataLength($spec)   { return ($spec
[0] * $spec
[1]) + 
($spec
[3] * $spec
[4]);    } 
 590         public static function rsEccLength($spec)    { return ($spec
[0] + $spec
[3]) * $spec
[2]; }