php 生成二维码

发布时间:2022-04-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了php 生成二维码脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

生成二维码的类:

php 生成二维码

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

使用方法

import(‘qrcode/qrcode‘, EXTEND_PATH);
            $code = new \QRencode();
            $timess = time() . $ids;
            $imgurl = YM . ‘/uploads/qrcode/‘ . $timess . ‘.png‘;
            $code->encodePNG(YM . ‘/index/index/order/type/1/id/‘ . $ids . ‘.html‘,‘./uploads/qrcode/‘ . $timess . ‘.png‘);
            return $this->responed(true,$imgurl);

脚本宝典总结

以上是脚本宝典为你收集整理的php 生成二维码全部内容,希望文章能够帮你解决php 生成二维码所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。