• 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 Kentaro Fukuchi <fukuchi@megaui.net>
      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, Inc., 51 Franklin St, Fifth Floor, Boston, 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(&$srctab, $x, $y, $repl, $replLen = false) {
     100             $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($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, Inc., 51 Franklin St, Fifth Floor, Boston, 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, $width, 0));
     229                 for ($maskNo=0; $maskNo<8; $maskNo++)
     230                     $mask->makeMaskNo($maskNo, $width, $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', date('Y-m-d H:i:s').': '.$err, 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, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
     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, Inc., 51 Franklin St, Fifth Floor, Boston, 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,    0, 0, array(   0,    0,    0,    0)),
     362             array( 21,   26, 0, array(   7,   10,   13,   17)), // 1
     363             array( 25,   44, 7, array(  10,   16,   22,   28)),
     364             array( 29,   70, 7, array(  15,   26,   36,   44)),
     365             array( 33,  100, 7, array(  20,   36,   52,   64)),
     366             array( 37,  134, 7, array(  26,   48,   72,   88)), // 5
     367             array( 41,  172, 7, array(  36,   64,   96,  112)),
     368             array( 45,  196, 0, array(  40,   72,  108,  130)),
     369             array( 49,  242, 0, array(  48,   88,  132,  156)),
     370             array( 53,  292, 0, array(  60,  110,  160,  192)),
     371             array( 57,  346, 0, array(  72,  130,  192,  224)), //10
     372             array( 61,  404, 0, array(  80,  150,  224,  264)),
     373             array( 65,  466, 0, array(  96,  176,  260,  308)),
     374             array( 69,  532, 0, array( 104,  198,  288,  352)),
     375             array( 73,  581, 3, array( 120,  216,  320,  384)),
     376             array( 77,  655, 3, array( 132,  240,  360,  432)), //15
     377             array( 81,  733, 3, array( 144,  280,  408,  480)),
     378             array( 85,  815, 3, array( 168,  308,  448,  532)),
     379             array( 89,  901, 3, array( 180,  338,  504,  588)),
     380             array( 93,  991, 3, array( 196,  364,  546,  650)),
     381             array( 97, 1085, 3, array( 224,  416,  600,  700)), //20
     382             array(101, 1156, 4, array( 224,  442,  644,  750)),
     383             array(105, 1258, 4, array( 252,  476,  690,  816)),
     384             array(109, 1364, 4, array( 270,  504,  750,  900)),
     385             array(113, 1474, 4, array( 300,  560,  810,  960)),
     386             array(117, 1588, 4, array( 312,  588,  870, 1050)), //25
     387             array(121, 1706, 4, array( 336,  644,  952, 1110)),
     388             array(125, 1828, 4, array( 360,  700, 1020, 1200)),
     389             array(129, 1921, 3, array( 390,  728, 1050, 1260)),
     390             array(133, 2051, 3, array( 420,  784, 1140, 1350)),
     391             array(137, 2185, 3, array( 450,  812, 1200, 1440)), //30
     392             array(141, 2323, 3, array( 480,  868, 1290, 1530)),
     393             array(145, 2465, 3, array( 510,  924, 1350, 1620)),
     394             array(149, 2611, 3, array( 540,  980, 1440, 1710)),
     395             array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
     396             array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35
     397             array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
     398             array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
     399             array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
     400             array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
     401             array(177, 3706, 0, 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, 16),
     447             array( 8, 10, 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,  0), array( 0,  0), array( 0,  0)),
     497             array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)), // 1
     498             array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)),
     499             array(array( 1,  0), array( 1,  0), array( 2,  0), array( 2,  0)),
     500             array(array( 1,  0), array( 2,  0), array( 2,  0), array( 4,  0)),
     501             array(array( 1,  0), array( 2,  0), array( 2,  2), array( 2,  2)), // 5
     502             array(array( 2,  0), array( 4,  0), array( 4,  0), array( 4,  0)),
     503             array(array( 2,  0), array( 4,  0), array( 2,  4), array( 4,  1)),
     504             array(array( 2,  0), array( 2,  2), array( 4,  2), array( 4,  2)),
     505             array(array( 2,  0), array( 3,  2), array( 4,  4), array( 4,  4)),
     506             array(array( 2,  2), array( 4,  1), array( 6,  2), array( 6,  2)), //10
     507             array(array( 4,  0), array( 1,  4), array( 4,  4), array( 3,  8)),
     508             array(array( 2,  2), array( 6,  2), array( 4,  6), array( 7,  4)),
     509             array(array( 4,  0), array( 8,  1), array( 8,  4), array(12,  4)),
     510             array(array( 3,  1), array( 4,  5), array(11,  5), array(11,  5)),
     511             array(array( 5,  1), array( 5,  5), array( 5,  7), array(11,  7)), //15
     512             array(array( 5,  1), array( 7,  3), array(15,  2), array( 3, 13)),
     513             array(array( 1,  5), array(10,  1), array( 1, 15), array( 2, 17)),
     514             array(array( 5,  1), array( 9,  4), array(17,  1), array( 2, 19)),
     515             array(array( 3,  4), array( 3, 11), array(17,  4), array( 9, 16)),
     516             array(array( 3,  5), array( 3, 13), array(15,  5), array(15, 10)), //20
     517             array(array( 4,  4), array(17,  0), array(17,  6), array(19,  6)),
     518             array(array( 2,  7), array(17,  0), array( 7, 16), array(34,  0)),
     519             array(array( 4,  5), array( 4, 14), array(11, 14), array(16, 14)),
     520             array(array( 6,  4), array( 6, 14), array(11, 16), array(30,  2)),
     521             array(array( 8,  4), array( 8, 13), array( 7, 22), array(22, 13)), //25
     522             array(array(10,  2), array(19,  4), array(28,  6), array(33,  4)),
     523             array(array( 8,  4), array(22,  3), array( 8, 26), array(12, 28)),
     524             array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)),
     525             array(array( 7,  7), array(21,  7), array( 1, 37), array(19, 26)),
     526             array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30
     527             array(array(13,  3), array( 2, 29), array(42,  1), array(23, 28)),
     528             array(array(17,  0), array(10, 23), array(10, 35), array(19, 35)),
     529             array(array(17,  1), array(14, 21), array(29, 19), array(11, 46)),
     530             array(array(13,  6), array(14, 23), array(44,  7), array(59,  1)),
     531             array(array(12,  7), array(12, 26), array(39, 14), array(22, 41)), //35
     532             array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
     533             array(array(17,  4), array(29, 14), array(49, 10), array(24, 46)),
     534             array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)),
     535             array(array(20,  4), array(40,  7), array(43, 22), array(10, 67)),
     536             array(array(19,  6), array(18, 31), array(34, 34), 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,0,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,  0),
     579             array( 0,  0), array(18,  0), array(22,  0), array(26,  0), array(30,  0), // 1- 5
     580             array(34,  0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10
     581             array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15
     582             array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20
     583             array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25
     584             array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30
     585             array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35
     586             array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //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                 "xa1xa1xa1xa1xa1",
     600                 "xa1xa0xa0xa0xa1",
     601                 "xa1xa0xa1xa0xa1",
     602                 "xa1xa0xa0xa0xa1",
     603                 "xa1xa1xa1xa1xa1"
     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, $x, $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, $cx, $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, $ox, $oy)
     709         {
     710             $finder = array(
     711                 "xc1xc1xc1xc1xc1xc1xc1",
     712                 "xc1xc0xc0xc0xc0xc0xc1",
     713                 "xc1xc0xc1xc1xc1xc0xc1",
     714                 "xc1xc0xc1xc1xc1xc0xc1",
     715                 "xc1xc0xc1xc1xc1xc0xc1",
     716                 "xc1xc0xc0xc0xc0xc0xc1",
     717                 "xc1xc1xc1xc1xc1xc1xc1"
     718             );                            
     719             
     720             for($y=0; $y<7; $y++) {
     721                 QRstr::set($frame, $ox, $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 ("", $width);
     730             $frame = array_fill(0, $width, $frameLine);
     731 
     732             // Finder pattern
     733             self::putFinderPattern($frame, 0, 0);
     734             self::putFinderPattern($frame, $width - 7, 0);
     735             self::putFinderPattern($frame, 0, $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, 0, 7, $setPattern);
     750             QRstr::set($frame, $width-8, 7, $setPattern);
     751             QRstr::set($frame, 0, $width - 8, $setPattern);
     752         
     753             // Format info
     754             $setPattern = str_repeat("x84", 9);
     755             QRstr::set($frame, 0, 8, $setPattern);
     756             QRstr::set($frame, $width - 8, 8, $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, $frame, $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("", $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("
    ", $frame), 9);
     861         }
     862         
     863         //----------------------------------------------------------------------
     864         public static function unserial($code)
     865         {
     866             return explode("
    ", 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, Inc., 51 Franklin St, Fifth Floor, Boston, 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, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85) 
     968         {
     969             $image = self::image($frame, $pixelPerPoint, $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, $pixelPerPoint = 4, $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,255);
     993             $col[1] = ImageColorAllocate($base_image,0,0,0);
     994 
     995             imagefill($base_image, 0, 0, $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, 0, 0, 0, 0, $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, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
    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, Inc., 51 Franklin St, Fifth Floor, Boston, 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, 0, $size);
    1060             
    1061             if (count($setData) < $size) {
    1062                 $setData = array_merge($setData, array_fill(0,$size-count($setData),0));
    1063             }
    1064         
    1065             if(!QRinput::check($mode, $size, $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, $version), $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, $version), $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, $version), (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, $size, $data)
    1358         {
    1359             try {
    1360                 $entry = new QRinputItem($mode, $size, $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, $index, $parity);
    1381             
    1382             try {
    1383                 $entry = new QRinputItem(QR_MODE_STRUCTURE, 3, 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, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    1442             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    1443             36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
    1444              0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 44, -1, -1, -1, -1, -1,
    1445             -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
    1446             25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
    1447             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    1448             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -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, $size, $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, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
    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, Inc., 51 Franklin St, Fifth Floor, Boston, 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, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
    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, Inc., 51 Franklin St, Fifth Floor, Boston, 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, $run, 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, $run, 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 == '' || $string == '') {
    2246                 throw new Exception('empty string!!!');
    2247             }
    2248 
    2249             $split = new QRsplit($string, $input, $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, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
    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, Inc., 51 Franklin St, Fifth Floor, Boston, 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, $rs->nn+1, 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, $gfpoly, $fcr, $prim, $nroots, $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, $gfpoly, $fcr, $prim, $nroots, $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, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
    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, Inc., 51 Franklin St, Fifth Floor, Boston, 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, &$frame, $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, $width, $frame)
    2581         {
    2582             $bitMask = array_fill(0, $width, array_fill(0, $width, 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), $x, $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("
    ", $codeArr), 9);
    2608         }
    2609         
    2610         //----------------------------------------------------------------------
    2611         public static function unserial($code)
    2612         {
    2613             $codeArr = array();
    2614             
    2615             $codeLines = explode("
    ", gzuncompress($code));
    2616             foreach ($codeLines as $line)
    2617                 $codeArr[] = str_split($line);
    2618             
    2619             return $codeArr;
    2620         }
    2621         
    2622         //----------------------------------------------------------------------
    2623         public function makeMaskNo($maskNo, $width, $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, $width, $s, $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, $width, $s, $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, $frame, $maskNo, $level)
    2662         {
    2663             $masked = array_fill(0, $width, str_repeat("", $width));
    2664             $this->makeMaskNo($maskNo, $width, $frame, $masked);
    2665             $this->writeFormatInformation($width, $masked, $maskNo, $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, $frame, $level)
    2768         {
    2769             $minDemerit = PHP_INT_MAX;
    2770             $bestMaskNum = 0;
    2771             $bestMask = array();
    2772             
    2773             $checked_masks = array(0,1,2,3,4,5,6,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, str_repeat("", $width));
    2790 
    2791                 $demerit = 0;
    2792                 $blacks = 0;
    2793                 $blacks  = $this->makeMaskNo($i, $width, $frame, $mask);
    2794                 $blacks += $this->writeFormatInformation($width, $mask, $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, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
    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, Inc., 51 Franklin St, Fifth Floor, Boston, 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, $data, $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,0,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, 0, 1, $el, 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), $el,  $ecc, $rs);
    2919                 $this->ecccode = array_merge(array_slice($this->ecccode,0, $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, 0x11d, 0, 1, $el, 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, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
    2938                 $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $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, $frame, $input->getErrorCorrectionLevel());
    3036                 } else {
    3037                     $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel());
    3038                 }
    3039             } else {
    3040                 $masked = $maskObj->makeMask($width, $frame, $mask, $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, $version, $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, $version, $level, $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, $input, $hint, $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, $size, $margin);
    3105             return $enc->encodePNG($text, $outfile, $saveandprint=false);
    3106         }
    3107 
    3108         //----------------------------------------------------------------------
    3109         public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) 
    3110         {
    3111             $enc = QRencode::factory($level, $size, $margin);
    3112             return $enc->encode($text, $outfile);
    3113         }
    3114 
    3115         //----------------------------------------------------------------------
    3116         public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) 
    3117         {
    3118             $enc = QRencode::factory($level, $size, $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, $size = 3, $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->version, $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->version, $this->level);
    3285             } else {
    3286                 $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
    3287             }
    3288             
    3289             QRtools::markTime('after_encode');
    3290             
    3291             if ($outfile!== false) {
    3292                 file_put_contents($outfile, join("
    ", QRtools::binarize($code->data)));
    3293             } else {
    3294                 return QRtools::binarize($code->data);
    3295             }
    3296         }
    3297         
    3298         //----------------------------------------------------------------------
    3299         public function encodePNG($intext, $outfile = false,$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, $outfile, 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);
  • 相关阅读:
    pycharm运行程序,总是出现IPthony界面(IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help. PyDev console: using IPython 6.2.1)
    《剑指offer》第十一题:旋转数组的最小数字
    《剑指offer》第十题:斐波那契数列
    《剑指offer》第九题:用两个栈实现队列
    《剑指offer》第八题:二叉树的下一个节点
    《剑指offer》第七题:重建二叉树
    《剑指offer》第六题:从尾到头打印链表
    《剑指offer》第五题:替换空格
    《剑指offer》第四题:二维数组中的查找
    《剑指offer》第三题II:不修改数组找出重复的数字
  • 原文地址:https://www.cnblogs.com/ziyandeyanhuo/p/11386731.html
Copyright © 2020-2023  润新知