[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/externals/phpqrcode/ -> phpqrcode.php (source)

   1  <?php
   2  
   3  /*

   4   * PHP QR Code encoder

   5   *

   6   * This file contains MERGED version of PHP QR Code library.

   7   * It was auto-generated from full version for your convenience.

   8   *

   9   * This merged version was configured to not requre any external files,

  10   * with disabled cache, error loging and weker but faster mask matching.

  11   * If you need tune it up please use non-merged version.

  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   * This library is free software; you can redistribute it and/or

  22   * modify it under the terms of the GNU Lesser General Public

  23   * License as published by the Free Software Foundation; either

  24   * version 3 of the License, or any later version.

  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   * Common constants

  55   *

  56   * Based on libqrencode C library distributed under LGPL 2.1

  57   * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>

  58   *

  59   * PHP QR Code is distributed under 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   *

 114   * Config file, tuned-up for merged verion

 115   */
 116       
 117      define('QR_CACHEABLE', false);       // use cache - more disk reads but less CPU power, masks and format templates are stored there

 118      define('QR_CACHE_DIR', false);       // used when QR_CACHEABLE === true

 119      define('QR_LOG_DIR', false);         // default error logs dir   

 120      
 121      define('QR_FIND_BEST_MASK', true);                                                          // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code

 122      define('QR_FIND_FROM_RANDOM', 2);                                                       // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly

 123      define('QR_DEFAULT_MASK', 2);                                                               // when QR_FIND_BEST_MASK === false

 124                                                    
 125      define('QR_PNG_MAXIMUM_SIZE',  1024);                                                       // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images

 126                                                    
 127  
 128  
 129  
 130  //---- qrtools.php -----------------------------
 131  
 132  
 133  
 134  
 135  /*

 136   * PHP QR Code encoder

 137   *

 138   * Toolset, handy and debug utilites.

 139   *

 140   * PHP QR Code is distributed under LGPL 3

 141   * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>

 142   *

 143   * This library is free software; you can redistribute it and/or

 144   * modify it under the terms of the GNU Lesser General Public

 145   * License as published by the Free Software Foundation; either

 146   * version 3 of the License, or any later version.

 147   *

 148   * This library is distributed in the hope that it will be useful,

 149   * but WITHOUT ANY WARRANTY; without even the implied warranty of

 150   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

 151   * Lesser General Public License for more details.

 152   *

 153   * You should have received a copy of the GNU Lesser General Public

 154   * License along with this library; if not, write to the Free Software

 155   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

 156   */
 157  
 158      class QRtools {
 159      
 160          //----------------------------------------------------------------------

 161          public static function binarize($frame)
 162          {
 163              $len = count($frame);
 164              foreach ($frame as &$frameLine) {
 165                  
 166                  for($i=0; $i<$len; $i++) {
 167                      $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
 168                  }
 169              }
 170              
 171              return $frame;
 172          }
 173          
 174          //----------------------------------------------------------------------

 175          public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037')
 176          {
 177              $barcode_array = array();
 178              
 179              if (!is_array($mode))
 180                  $mode = explode(',', $mode);
 181                  
 182              $eccLevel = 'L';
 183                  
 184              if (count($mode) > 1) {
 185                  $eccLevel = $mode[1];
 186              }
 187                  
 188              $qrTab = QRcode::text($code, false, $eccLevel);
 189              $size = count($qrTab);
 190                  
 191              $barcode_array['num_rows'] = $size;
 192              $barcode_array['num_cols'] = $size;
 193              $barcode_array['bcode'] = array();
 194                  
 195              foreach ($qrTab as $line) {
 196                  $arrAdd = array();
 197                  foreach(str_split($line) as $char)
 198                      $arrAdd[] = ($char=='1')?1:0;
 199                  $barcode_array['bcode'][] = $arrAdd;
 200              }
 201                      
 202              return $barcode_array;
 203          }
 204          
 205          //----------------------------------------------------------------------

 206          public static function clearCache()
 207          {
 208              self::$frames = array();
 209          }
 210          
 211          //----------------------------------------------------------------------

 212          public static function buildCache()
 213          {
 214              QRtools::markTime('before_build_cache');
 215              
 216              $mask = new QRmask();
 217              for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) {
 218                  $frame = QRspec::newFrame($a);
 219                  if (QR_IMAGE) {
 220                      $fileName = QR_CACHE_DIR.'frame_'.$a.'.png';
 221                      QRimage::png(self::binarize($frame), $fileName, 1, 0);
 222                  }
 223                  
 224                  $width = count($frame);
 225                  $bitMask = array_fill(0, $width, array_fill(0, $width, 0));
 226                  for ($maskNo=0; $maskNo<8; $maskNo++)
 227                      $mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true);
 228              }
 229              
 230              QRtools::markTime('after_build_cache');
 231          }
 232  
 233          //----------------------------------------------------------------------

 234          public static function log($outfile, $err)
 235          {
 236              if (QR_LOG_DIR !== false) {
 237                  if ($err != '') {
 238                      if ($outfile !== false) {
 239                          file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
 240                      } else {
 241                          file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
 242                      }
 243                  }    
 244              }
 245          }
 246          
 247          //----------------------------------------------------------------------

 248          public static function dumpMask($frame) 
 249          {
 250              $width = count($frame);
 251              for($y=0;$y<$width;$y++) {
 252                  for($x=0;$x<$width;$x++) {
 253                      echo ord($frame[$y][$x]).',';
 254                  }
 255              }
 256          }
 257          
 258          //----------------------------------------------------------------------

 259          public static function markTime($markerId)
 260          {
 261              list($usec, $sec) = explode(" ", microtime());
 262              $time = ((float)$usec + (float)$sec);
 263              
 264              if (!isset($GLOBALS['qr_time_bench']))
 265                  $GLOBALS['qr_time_bench'] = array();
 266              
 267              $GLOBALS['qr_time_bench'][$markerId] = $time;
 268          }
 269          
 270          //----------------------------------------------------------------------

 271          public static function timeBenchmark()
 272          {
 273              self::markTime('finish');
 274          
 275              $lastTime = 0;
 276              $startTime = 0;
 277              $p = 0;
 278  
 279              echo '<table cellpadding="3" cellspacing="1">
 280                      <thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead>
 281                      <tbody>';
 282  
 283              foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
 284                  if ($p > 0) {
 285                      echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime-$lastTime, 6).'s</td></tr>';
 286                  } else {
 287                      $startTime = $thisTime;
 288                  }
 289                  
 290                  $p++;
 291                  $lastTime = $thisTime;
 292              }
 293              
 294              echo '</tbody><tfoot>
 295                  <tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime-$startTime, 6).'s</td></tr>
 296              </tfoot>
 297              </table>';
 298          }
 299          
 300      }
 301      
 302      //##########################################################################

 303      
 304      QRtools::markTime('start');
 305      
 306  
 307  
 308  
 309  //---- qrspec.php -----------------------------
 310  
 311  
 312  
 313  
 314  /*

 315   * PHP QR Code encoder

 316   *

 317   * QR Code specifications

 318   *

 319   * Based on libqrencode C library distributed under LGPL 2.1

 320   * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>

 321   *

 322   * PHP QR Code is distributed under LGPL 3

 323   * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>

 324   *

 325   * The following data / specifications are taken from

 326   * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)

 327   *  or

 328   * "Automatic identification and data capture techniques -- 

 329   *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)

 330   *

 331   * This library is free software; you can redistribute it and/or

 332   * modify it under the terms of the GNU Lesser General Public

 333   * License as published by the Free Software Foundation; either

 334   * version 3 of the License, or any later version.

 335   *

 336   * This library is distributed in the hope that it will be useful,

 337   * but WITHOUT ANY WARRANTY; without even the implied warranty of

 338   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

 339   * Lesser General Public License for more details.

 340   *

 341   * You should have received a copy of the GNU Lesser General Public

 342   * License along with this library; if not, write to the Free Software

 343   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

 344   */
 345   
 346      define('QRSPEC_VERSION_MAX', 40);
 347      define('QRSPEC_WIDTH_MAX',   177);
 348  
 349      define('QRCAP_WIDTH',        0);
 350      define('QRCAP_WORDS',        1);
 351      define('QRCAP_REMINDER',     2);
 352      define('QRCAP_EC',           3);
 353  
 354      class QRspec {
 355      
 356          public static $capacity = array(
 357              array(  0,    0, 0, array(   0,    0,    0,    0)),
 358              array( 21,   26, 0, array(   7,   10,   13,   17)), // 1
 359              array( 25,   44, 7, array(  10,   16,   22,   28)),
 360              array( 29,   70, 7, array(  15,   26,   36,   44)),
 361              array( 33,  100, 7, array(  20,   36,   52,   64)),
 362              array( 37,  134, 7, array(  26,   48,   72,   88)), // 5
 363              array( 41,  172, 7, array(  36,   64,   96,  112)),
 364              array( 45,  196, 0, array(  40,   72,  108,  130)),
 365              array( 49,  242, 0, array(  48,   88,  132,  156)),
 366              array( 53,  292, 0, array(  60,  110,  160,  192)),
 367              array( 57,  346, 0, array(  72,  130,  192,  224)), //10
 368              array( 61,  404, 0, array(  80,  150,  224,  264)),
 369              array( 65,  466, 0, array(  96,  176,  260,  308)),
 370              array( 69,  532, 0, array( 104,  198,  288,  352)),
 371              array( 73,  581, 3, array( 120,  216,  320,  384)),
 372              array( 77,  655, 3, array( 132,  240,  360,  432)), //15
 373              array( 81,  733, 3, array( 144,  280,  408,  480)),
 374              array( 85,  815, 3, array( 168,  308,  448,  532)),
 375              array( 89,  901, 3, array( 180,  338,  504,  588)),
 376              array( 93,  991, 3, array( 196,  364,  546,  650)),
 377              array( 97, 1085, 3, array( 224,  416,  600,  700)), //20
 378              array(101, 1156, 4, array( 224,  442,  644,  750)),
 379              array(105, 1258, 4, array( 252,  476,  690,  816)),
 380              array(109, 1364, 4, array( 270,  504,  750,  900)),
 381              array(113, 1474, 4, array( 300,  560,  810,  960)),
 382              array(117, 1588, 4, array( 312,  588,  870, 1050)), //25
 383              array(121, 1706, 4, array( 336,  644,  952, 1110)),
 384              array(125, 1828, 4, array( 360,  700, 1020, 1200)),
 385              array(129, 1921, 3, array( 390,  728, 1050, 1260)),
 386              array(133, 2051, 3, array( 420,  784, 1140, 1350)),
 387              array(137, 2185, 3, array( 450,  812, 1200, 1440)), //30
 388              array(141, 2323, 3, array( 480,  868, 1290, 1530)),
 389              array(145, 2465, 3, array( 510,  924, 1350, 1620)),
 390              array(149, 2611, 3, array( 540,  980, 1440, 1710)),
 391              array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
 392              array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35
 393              array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
 394              array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
 395              array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
 396              array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
 397              array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40
 398          );
 399          
 400          //----------------------------------------------------------------------

 401          public static function getDataLength($version, $level)
 402          {
 403              return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level];
 404          }
 405          
 406          //----------------------------------------------------------------------

 407          public static function getECCLength($version, $level)
 408          {
 409              return self::$capacity[$version][QRCAP_EC][$level];
 410          }
 411          
 412          //----------------------------------------------------------------------

 413          public static function getWidth($version)
 414          {
 415              return self::$capacity[$version][QRCAP_WIDTH];
 416          }
 417          
 418          //----------------------------------------------------------------------

 419          public static function getRemainder($version)
 420          {
 421              return self::$capacity[$version][QRCAP_REMINDER];
 422          }
 423          
 424          //----------------------------------------------------------------------

 425          public static function getMinimumVersion($size, $level)
 426          {
 427  
 428              for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) {
 429                  $words  = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level];
 430                  if($words >= $size) 
 431                      return $i;
 432              }
 433  
 434              return -1;
 435          }
 436      
 437          //######################################################################

 438          
 439          public static $lengthTableBits = array(
 440              array(10, 12, 14),
 441              array( 9, 11, 13),
 442              array( 8, 16, 16),
 443              array( 8, 10, 12)
 444          );
 445          
 446          //----------------------------------------------------------------------

 447          public static function lengthIndicator($mode, $version)
 448          {
 449              if ($mode == QR_MODE_STRUCTURE)
 450                  return 0;
 451                  
 452              if ($version <= 9) {
 453                  $l = 0;
 454              } else if ($version <= 26) {
 455                  $l = 1;
 456              } else {
 457                  $l = 2;
 458              }
 459  
 460              return self::$lengthTableBits[$mode][$l];
 461          }
 462          
 463          //----------------------------------------------------------------------

 464          public static function maximumWords($mode, $version)
 465          {
 466              if($mode == QR_MODE_STRUCTURE) 
 467                  return 3;
 468                  
 469              if($version <= 9) {
 470                  $l = 0;
 471              } else if($version <= 26) {
 472                  $l = 1;
 473              } else {
 474                  $l = 2;
 475              }
 476  
 477              $bits = self::$lengthTableBits[$mode][$l];
 478              $words = (1 << $bits) - 1;
 479              
 480              if($mode == QR_MODE_KANJI) {
 481                  $words *= 2; // the number of bytes is required

 482              }
 483  
 484              return $words;
 485          }
 486  
 487          // Error correction code -----------------------------------------------

 488          // Table of the error correction code (Reed-Solomon block)

 489          // See Table 12-16 (pp.30-36), JIS X0510:2004.

 490  
 491          public static $eccTable = array(
 492              array(array( 0,  0), array( 0,  0), array( 0,  0), array( 0,  0)),
 493              array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)), // 1
 494              array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)),
 495              array(array( 1,  0), array( 1,  0), array( 2,  0), array( 2,  0)),
 496              array(array( 1,  0), array( 2,  0), array( 2,  0), array( 4,  0)),
 497              array(array( 1,  0), array( 2,  0), array( 2,  2), array( 2,  2)), // 5
 498              array(array( 2,  0), array( 4,  0), array( 4,  0), array( 4,  0)),
 499              array(array( 2,  0), array( 4,  0), array( 2,  4), array( 4,  1)),
 500              array(array( 2,  0), array( 2,  2), array( 4,  2), array( 4,  2)),
 501              array(array( 2,  0), array( 3,  2), array( 4,  4), array( 4,  4)),
 502              array(array( 2,  2), array( 4,  1), array( 6,  2), array( 6,  2)), //10
 503              array(array( 4,  0), array( 1,  4), array( 4,  4), array( 3,  8)),
 504              array(array( 2,  2), array( 6,  2), array( 4,  6), array( 7,  4)),
 505              array(array( 4,  0), array( 8,  1), array( 8,  4), array(12,  4)),
 506              array(array( 3,  1), array( 4,  5), array(11,  5), array(11,  5)),
 507              array(array( 5,  1), array( 5,  5), array( 5,  7), array(11,  7)), //15
 508              array(array( 5,  1), array( 7,  3), array(15,  2), array( 3, 13)),
 509              array(array( 1,  5), array(10,  1), array( 1, 15), array( 2, 17)),
 510              array(array( 5,  1), array( 9,  4), array(17,  1), array( 2, 19)),
 511              array(array( 3,  4), array( 3, 11), array(17,  4), array( 9, 16)),
 512              array(array( 3,  5), array( 3, 13), array(15,  5), array(15, 10)), //20
 513              array(array( 4,  4), array(17,  0), array(17,  6), array(19,  6)),
 514              array(array( 2,  7), array(17,  0), array( 7, 16), array(34,  0)),
 515              array(array( 4,  5), array( 4, 14), array(11, 14), array(16, 14)),
 516              array(array( 6,  4), array( 6, 14), array(11, 16), array(30,  2)),
 517              array(array( 8,  4), array( 8, 13), array( 7, 22), array(22, 13)), //25
 518              array(array(10,  2), array(19,  4), array(28,  6), array(33,  4)),
 519              array(array( 8,  4), array(22,  3), array( 8, 26), array(12, 28)),
 520              array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)),
 521              array(array( 7,  7), array(21,  7), array( 1, 37), array(19, 26)),
 522              array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30
 523              array(array(13,  3), array( 2, 29), array(42,  1), array(23, 28)),
 524              array(array(17,  0), array(10, 23), array(10, 35), array(19, 35)),
 525              array(array(17,  1), array(14, 21), array(29, 19), array(11, 46)),
 526              array(array(13,  6), array(14, 23), array(44,  7), array(59,  1)),
 527              array(array(12,  7), array(12, 26), array(39, 14), array(22, 41)), //35
 528              array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
 529              array(array(17,  4), array(29, 14), array(49, 10), array(24, 46)),
 530              array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)),
 531              array(array(20,  4), array(40,  7), array(43, 22), array(10, 67)),
 532              array(array(19,  6), array(18, 31), array(34, 34), array(20, 61)),//40
 533          );                                                                       
 534  
 535          //----------------------------------------------------------------------

 536          // CACHEABLE!!!

 537          
 538          public static function getEccSpec($version, $level, array &$spec)
 539          {
 540              if (count($spec) < 5) {
 541                  $spec = array(0,0,0,0,0);
 542              }
 543  
 544              $b1   = self::$eccTable[$version][$level][0];
 545              $b2   = self::$eccTable[$version][$level][1];
 546              $data = self::getDataLength($version, $level);
 547              $ecc  = self::getECCLength($version, $level);
 548  
 549              if($b2 == 0) {
 550                  $spec[0] = $b1;
 551                  $spec[1] = (int)($data / $b1);
 552                  $spec[2] = (int)($ecc / $b1);
 553                  $spec[3] = 0; 
 554                  $spec[4] = 0;
 555              } else {
 556                  $spec[0] = $b1;
 557                  $spec[1] = (int)($data / ($b1 + $b2));
 558                  $spec[2] = (int)($ecc  / ($b1 + $b2));
 559                  $spec[3] = $b2;
 560                  $spec[4] = $spec[1] + 1;
 561              }
 562          }
 563  
 564          // Alignment pattern ---------------------------------------------------

 565  
 566          // Positions of alignment patterns.

 567          // This array includes only the second and the third position of the 

 568          // alignment patterns. Rest of them can be calculated from the distance 

 569          // between them.

 570           
 571          // See Table 1 in Appendix E (pp.71) of JIS X0510:2004.

 572           
 573          public static $alignmentPattern = array(      
 574              array( 0,  0),
 575              array( 0,  0), array(18,  0), array(22,  0), array(26,  0), array(30,  0), // 1- 5
 576              array(34,  0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10
 577              array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15
 578              array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20
 579              array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25
 580              array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30
 581              array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35
 582              array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40
 583          );                                                                                  
 584  
 585          
 586          /** --------------------------------------------------------------------

 587           * Put an alignment marker.

 588           * @param frame

 589           * @param width

 590           * @param ox,oy center coordinate of the pattern

 591           */
 592          public static function putAlignmentMarker(array &$frame, $ox, $oy)
 593          {
 594              $finder = array(
 595                  "\xa1\xa1\xa1\xa1\xa1",
 596                  "\xa1\xa0\xa0\xa0\xa1",
 597                  "\xa1\xa0\xa1\xa0\xa1",
 598                  "\xa1\xa0\xa0\xa0\xa1",
 599                  "\xa1\xa1\xa1\xa1\xa1"
 600              );                        
 601              
 602              $yStart = $oy-2;         
 603              $xStart = $ox-2;
 604              
 605              for($y=0; $y<5; $y++) {
 606                  QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]);
 607              }
 608          }
 609  
 610          //----------------------------------------------------------------------

 611          public static function putAlignmentPattern($version, &$frame, $width)
 612          {
 613              if($version < 2)
 614                  return;
 615  
 616              $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
 617              if($d < 0) {
 618                  $w = 2;
 619              } else {
 620                  $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2);
 621              }
 622  
 623              if($w * $w - 3 == 1) {
 624                  $x = self::$alignmentPattern[$version][0];
 625                  $y = self::$alignmentPattern[$version][0];
 626                  self::putAlignmentMarker($frame, $x, $y);
 627                  return;
 628              }
 629  
 630              $cx = self::$alignmentPattern[$version][0];
 631              for($x=1; $x<$w - 1; $x++) {
 632                  self::putAlignmentMarker($frame, 6, $cx);
 633                  self::putAlignmentMarker($frame, $cx,  6);
 634                  $cx += $d;
 635              }
 636  
 637              $cy = self::$alignmentPattern[$version][0];
 638              for($y=0; $y<$w-1; $y++) {
 639                  $cx = self::$alignmentPattern[$version][0];
 640                  for($x=0; $x<$w-1; $x++) {
 641                      self::putAlignmentMarker($frame, $cx, $cy);
 642                      $cx += $d;
 643                  }
 644                  $cy += $d;
 645              }
 646          }
 647  
 648          // Version information pattern -----------------------------------------

 649  
 650          // Version information pattern (BCH coded).

 651          // See Table 1 in Appendix D (pp.68) of JIS X0510:2004.

 652          
 653          // size: [QRSPEC_VERSION_MAX - 6]

 654          
 655          public static $versionPattern = array(
 656              0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
 657              0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
 658              0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
 659              0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
 660              0x27541, 0x28c69
 661          );
 662  
 663          //----------------------------------------------------------------------

 664          public static function getVersionPattern($version)
 665          {
 666              if($version < 7 || $version > QRSPEC_VERSION_MAX)
 667                  return 0;
 668  
 669              return self::$versionPattern[$version -7];
 670          }
 671  
 672          // Format information --------------------------------------------------

 673          // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib)

 674          
 675          public static $formatInfo = array(
 676              array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
 677              array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
 678              array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed),
 679              array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b)
 680          );
 681  
 682          public static function getFormatInfo($mask, $level)
 683          {
 684              if($mask < 0 || $mask > 7)
 685                  return 0;
 686                  
 687              if($level < 0 || $level > 3)
 688                  return 0;                
 689  
 690              return self::$formatInfo[$level][$mask];
 691          }
 692  
 693          // Frame ---------------------------------------------------------------

 694          // Cache of initial frames.

 695           
 696          public static $frames = array();
 697  
 698          /** --------------------------------------------------------------------

 699           * Put a finder pattern.

 700           * @param frame

 701           * @param width

 702           * @param ox,oy upper-left coordinate of the pattern

 703           */
 704          public static function putFinderPattern(&$frame, $ox, $oy)
 705          {
 706              $finder = array(
 707                  "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
 708                  "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
 709                  "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
 710                  "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
 711                  "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
 712                  "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
 713                  "\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
 714              );                            
 715              
 716              for($y=0; $y<7; $y++) {
 717                  QRstr::set($frame, $ox, $oy+$y, $finder[$y]);
 718              }
 719          }
 720  
 721          //----------------------------------------------------------------------

 722          public static function createFrame($version)
 723          {
 724              $width = self::$capacity[$version][QRCAP_WIDTH];
 725              $frameLine = str_repeat ("\0", $width);
 726              $frame = array_fill(0, $width, $frameLine);
 727  
 728              // Finder pattern

 729              self::putFinderPattern($frame, 0, 0);
 730              self::putFinderPattern($frame, $width - 7, 0);
 731              self::putFinderPattern($frame, 0, $width - 7);
 732              
 733              // Separator

 734              $yOffset = $width - 7;
 735              
 736              for($y=0; $y<7; $y++) {
 737                  $frame[$y][7] = "\xc0";
 738                  $frame[$y][$width - 8] = "\xc0";
 739                  $frame[$yOffset][7] = "\xc0";
 740                  $yOffset++;
 741              }
 742              
 743              $setPattern = str_repeat("\xc0", 8);
 744              
 745              QRstr::set($frame, 0, 7, $setPattern);
 746              QRstr::set($frame, $width-8, 7, $setPattern);
 747              QRstr::set($frame, 0, $width - 8, $setPattern);
 748          
 749              // Format info

 750              $setPattern = str_repeat("\x84", 9);
 751              QRstr::set($frame, 0, 8, $setPattern);
 752              QRstr::set($frame, $width - 8, 8, $setPattern, 8);
 753              
 754              $yOffset = $width - 8;
 755  
 756              for($y=0; $y<8; $y++,$yOffset++) {
 757                  $frame[$y][8] = "\x84";
 758                  $frame[$yOffset][8] = "\x84";
 759              }
 760  
 761              // Timing pattern  

 762              
 763              for($i=1; $i<$width-15; $i++) {
 764                  $frame[6][7+$i] = chr(0x90 | ($i & 1));
 765                  $frame[7+$i][6] = chr(0x90 | ($i & 1));
 766              }
 767              
 768              // Alignment pattern  

 769              self::putAlignmentPattern($version, $frame, $width);
 770              
 771              // Version information 

 772              if($version >= 7) {
 773                  $vinf = self::getVersionPattern($version);
 774  
 775                  $v = $vinf;
 776                  
 777                  for($x=0; $x<6; $x++) {
 778                      for($y=0; $y<3; $y++) {
 779                          $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1));
 780                          $v = $v >> 1;
 781                      }
 782                  }
 783  
 784                  $v = $vinf;
 785                  for($y=0; $y<6; $y++) {
 786                      for($x=0; $x<3; $x++) {
 787                          $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1));
 788                          $v = $v >> 1;
 789                      }
 790                  }
 791              }
 792      
 793              // and a little bit...  

 794              $frame[$width - 8][8] = "\x81";
 795              
 796              return $frame;
 797          }
 798  
 799          //----------------------------------------------------------------------

 800          public static function debug($frame, $binary_mode = false)
 801          {
 802              if ($binary_mode) {
 803              
 804                      foreach ($frame as &$frameLine) {
 805                          $frameLine = join('<span class="m">&nbsp;&nbsp;</span>', explode('0', $frameLine));
 806                          $frameLine = join('&#9608;&#9608;', explode('1', $frameLine));
 807                      }
 808                      
 809                      ?>
 810                  <style>
 811                      .m { background-color: white; }
 812                  </style>
 813                  <?php
 814                      echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
 815                      echo join("<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $frame);
 816                      echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
 817              
 818              } else {
 819              
 820                  foreach ($frame as &$frameLine) {
 821                      $frameLine = join('<span class="m">&nbsp;</span>',  explode("\xc0", $frameLine));
 822                      $frameLine = join('<span class="m">&#9618;</span>', explode("\xc1", $frameLine));
 823                      $frameLine = join('<span class="p">&nbsp;</span>',  explode("\xa0", $frameLine));
 824                      $frameLine = join('<span class="p">&#9618;</span>', explode("\xa1", $frameLine));
 825                      $frameLine = join('<span class="s">&#9671;</span>', explode("\x84", $frameLine)); //format 0

 826                      $frameLine = join('<span class="s">&#9670;</span>', explode("\x85", $frameLine)); //format 1

 827                      $frameLine = join('<span class="x">&#9762;</span>', explode("\x81", $frameLine)); //special bit

 828                      $frameLine = join('<span class="c">&nbsp;</span>',  explode("\x90", $frameLine)); //clock 0

 829                      $frameLine = join('<span class="c">&#9719;</span>', explode("\x91", $frameLine)); //clock 1

 830                      $frameLine = join('<span class="f">&nbsp;</span>',  explode("\x88", $frameLine)); //version

 831                      $frameLine = join('<span class="f">&#9618;</span>', explode("\x89", $frameLine)); //version

 832                      $frameLine = join('&#9830;', explode("\x01", $frameLine));
 833                      $frameLine = join('&#8901;', explode("\0", $frameLine));
 834                  }
 835                  
 836                  ?>
 837                  <style>
 838                      .p { background-color: yellow; }
 839                      .m { background-color: #00FF00; }
 840                      .s { background-color: #FF0000; }
 841                      .c { background-color: aqua; }
 842                      .x { background-color: pink; }
 843                      .f { background-color: gold; }
 844                  </style>
 845                  <?php
 846                  echo "<pre><tt>";
 847                  echo join("<br/ >", $frame);
 848                  echo "</tt></pre>";
 849              
 850              }
 851          }
 852  
 853          //----------------------------------------------------------------------

 854          public static function serial($frame)
 855          {
 856              return gzcompress(join("\n", $frame), 9);
 857          }
 858          
 859          //----------------------------------------------------------------------

 860          public static function unserial($code)
 861          {
 862              return explode("\n", gzuncompress($code));
 863          }
 864          
 865          //----------------------------------------------------------------------

 866          public static function newFrame($version)
 867          {
 868              if($version < 1 || $version > QRSPEC_VERSION_MAX) 
 869                  return null;
 870  
 871              if(!isset(self::$frames[$version])) {
 872                  
 873                  $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat';
 874                  
 875                  if (QR_CACHEABLE) {
 876                      if (file_exists($fileName)) {
 877                          self::$frames[$version] = self::unserial(file_get_contents($fileName));
 878                      } else {
 879                          self::$frames[$version] = self::createFrame($version);
 880                          file_put_contents($fileName, self::serial(self::$frames[$version]));
 881                      }
 882                  } else {
 883                      self::$frames[$version] = self::createFrame($version);
 884                  }
 885              }
 886              
 887              if(is_null(self::$frames[$version]))
 888                  return null;
 889  
 890              return self::$frames[$version];
 891          }
 892  
 893          //----------------------------------------------------------------------

 894          public static function rsBlockNum($spec)     { return $spec[0] + $spec[3]; }
 895          public static function rsBlockNum1($spec)    { return $spec[0]; }
 896          public static function rsDataCodes1($spec)   { return $spec[1]; }
 897          public static function rsEccCodes1($spec)    { return $spec[2]; }
 898          public static function rsBlockNum2($spec)    { return $spec[3]; }
 899          public static function rsDataCodes2($spec)   { return $spec[4]; }
 900          public static function rsEccCodes2($spec)    { return $spec[2]; }
 901          public static function rsDataLength($spec)   { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]);    }
 902          public static function rsEccLength($spec)    { return ($spec[0] + $spec[3]) * $spec[2]; }
 903          
 904      }
 905  
 906  
 907  
 908  //---- qrimage.php -----------------------------
 909  
 910  
 911  
 912  
 913  /*

 914   * PHP QR Code encoder

 915   *

 916   * Image output of code using GD2

 917   *

 918   * PHP QR Code is distributed under LGPL 3

 919   * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>

 920   *

 921   * This library is free software; you can redistribute it and/or

 922   * modify it under the terms of the GNU Lesser General Public

 923   * License as published by the Free Software Foundation; either

 924   * version 3 of the License, or any later version.

 925   *

 926   * This library is distributed in the hope that it will be useful,

 927   * but WITHOUT ANY WARRANTY; without even the implied warranty of

 928   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

 929   * Lesser General Public License for more details.

 930   *

 931   * You should have received a copy of the GNU Lesser General Public

 932   * License along with this library; if not, write to the Free Software

 933   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

 934   */
 935   
 936      define('QR_IMAGE', true);
 937  
 938      class QRimage {
 939      
 940          //----------------------------------------------------------------------

 941          public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE) 
 942          {
 943              $image = self::image($frame, $pixelPerPoint, $outerFrame);
 944              
 945              if ($filename === false) {
 946                  Header("Content-type: image/png");
 947                  ImagePng($image);
 948              } else {
 949                  if($saveandprint===TRUE){
 950                      ImagePng($image, $filename);
 951                      header("Content-type: image/png");
 952                      ImagePng($image);
 953                  }else{
 954                      ImagePng($image, $filename);
 955                  }
 956              }
 957              
 958              ImageDestroy($image);
 959          }
 960      
 961          //----------------------------------------------------------------------

 962          public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85) 
 963          {
 964              $image = self::image($frame, $pixelPerPoint, $outerFrame);
 965              
 966              if ($filename === false) {
 967                  Header("Content-type: image/jpeg");
 968                  ImageJpeg($image, null, $q);
 969              } else {
 970                  ImageJpeg($image, $filename, $q);            
 971              }
 972              
 973              ImageDestroy($image);
 974          }
 975      
 976          //----------------------------------------------------------------------

 977          private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4) 
 978          {
 979              $h = count($frame);
 980              $w = strlen($frame[0]);
 981              
 982              $imgW = $w + 2*$outerFrame;
 983              $imgH = $h + 2*$outerFrame;
 984              
 985              $base_image =ImageCreate($imgW, $imgH);
 986              
 987              $col[0] = ImageColorAllocate($base_image,255,255,255);
 988              $col[1] = ImageColorAllocate($base_image,0,0,0);
 989  
 990              imagefill($base_image, 0, 0, $col[0]);
 991  
 992              for($y=0; $y<$h; $y++) {
 993                  for($x=0; $x<$w; $x++) {
 994                      if ($frame[$y][$x] == '1') {
 995                          ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]); 
 996                      }
 997                  }
 998              }
 999              
1000              $target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint);
1001              ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH);
1002              ImageDestroy($base_image);
1003              
1004              return $target_image;
1005          }
1006      }
1007  
1008  
1009  
1010  //---- qrinput.php -----------------------------
1011  
1012  
1013  
1014  
1015  /*

1016   * PHP QR Code encoder

1017   *

1018   * Input encoding class

1019   *

1020   * Based on libqrencode C library distributed under LGPL 2.1

1021   * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>

1022   *

1023   * PHP QR Code is distributed under LGPL 3

1024   * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>

1025   *

1026   * This library is free software; you can redistribute it and/or

1027   * modify it under the terms of the GNU Lesser General Public

1028   * License as published by the Free Software Foundation; either

1029   * version 3 of the License, or any later version.

1030   *

1031   * This library is distributed in the hope that it will be useful,

1032   * but WITHOUT ANY WARRANTY; without even the implied warranty of

1033   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

1034   * Lesser General Public License for more details.

1035   *

1036   * You should have received a copy of the GNU Lesser General Public

1037   * License along with this library; if not, write to the Free Software

1038   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

1039   */
1040   
1041      define('STRUCTURE_HEADER_BITS',  20);
1042      define('MAX_STRUCTURED_SYMBOLS', 16);
1043  
1044      class QRinputItem {
1045      
1046          public $mode;
1047          public $size;
1048          public $data;
1049          public $bstream;
1050  
1051          public function __construct($mode, $size, $data, $bstream = null) 
1052          {
1053              $setData = array_slice($data, 0, $size);
1054              
1055              if (count($setData) < $size) {
1056                  $setData = array_merge($setData, array_fill(0,$size-count($setData),0));
1057              }
1058          
1059              if(!QRinput::check($mode, $size, $setData)) {
1060                  throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData));
1061                  return null;
1062              }
1063              
1064              $this->mode = $mode;
1065              $this->size = $size;
1066              $this->data = $setData;
1067              $this->bstream = $bstream;
1068          }
1069          
1070          //----------------------------------------------------------------------

1071          public function encodeModeNum($version)
1072          {
1073              try {
1074              
1075                  $words = (int)($this->size / 3);
1076                  $bs = new QRbitstream();
1077                  
1078                  $val = 0x1;
1079                  $bs->appendNum(4, $val);
1080                  $bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size);
1081  
1082                  for($i=0; $i<$words; $i++) {
1083                      $val  = (ord($this->data[$i*3  ]) - ord('0')) * 100;
1084                      $val += (ord($this->data[$i*3+1]) - ord('0')) * 10;
1085                      $val += (ord($this->data[$i*3+2]) - ord('0'));
1086                      $bs->appendNum(10, $val);
1087                  }
1088  
1089                  if($this->size - $words * 3 == 1) {
1090                      $val = ord($this->data[$words*3]) - ord('0');
1091                      $bs->appendNum(4, $val);
1092                  } else if($this->size - $words * 3 == 2) {
1093                      $val  = (ord($this->data[$words*3  ]) - ord('0')) * 10;
1094                      $val += (ord($this->data[$words*3+1]) - ord('0'));
1095                      $bs->appendNum(7, $val);
1096                  }
1097  
1098                  $this->bstream = $bs;
1099                  return 0;
1100                  
1101              } catch (Exception $e) {
1102                  return -1;
1103              }
1104          }
1105          
1106          //----------------------------------------------------------------------

1107          public function encodeModeAn($version)
1108          {
1109              try {
1110                  $words = (int)($this->size / 2);
1111                  $bs = new QRbitstream();
1112                  
1113                  $bs->appendNum(4, 0x02);
1114                  $bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size);
1115  
1116                  for($i=0; $i<$words; $i++) {
1117                      $val  = (int)QRinput::lookAnTable(ord($this->data[$i*2  ])) * 45;
1118                      $val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1]));
1119  
1120                      $bs->appendNum(11, $val);
1121                  }
1122  
1123                  if($this->size & 1) {
1124                      $val = QRinput::lookAnTable(ord($this->data[$words * 2]));
1125                      $bs->appendNum(6, $val);
1126                  }
1127          
1128                  $this->bstream = $bs;
1129                  return 0;
1130              
1131              } catch (Exception $e) {
1132                  return -1;
1133              }
1134          }
1135          
1136          //----------------------------------------------------------------------

1137          public function encodeMode8($version)
1138          {
1139              try {
1140                  $bs = new QRbitstream();
1141  
1142                  $bs->appendNum(4, 0x4);
1143                  $bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size);
1144  
1145                  for($i=0; $i<$this->size; $i++) {
1146                      $bs->appendNum(8, ord($this->data[$i]));
1147                  }
1148  
1149                  $this->bstream = $bs;
1150                  return 0;
1151              
1152              } catch (Exception $e) {
1153                  return -1;
1154              }
1155          }
1156          
1157          //----------------------------------------------------------------------

1158          public function encodeModeKanji($version)
1159          {
1160              try {
1161  
1162                  $bs = new QRbitrtream();
1163                  
1164                  $bs->appendNum(4, 0x8);
1165                  $bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2));
1166  
1167                  for($i=0; $i<$this->size; $i+=2) {
1168                      $val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]);
1169                      if($val <= 0x9ffc) {
1170                          $val -= 0x8140;
1171                      } else {
1172                          $val -= 0xc140;
1173                      }
1174                      
1175                      $h = ($val >> 8) * 0xc0;
1176                      $val = ($val & 0xff) + $h;
1177  
1178                      $bs->appendNum(13, $val);
1179                  }
1180  
1181                  $this->bstream = $bs;
1182                  return 0;
1183              
1184              } catch (Exception $e) {
1185                  return -1;
1186              }
1187          }
1188  
1189          //----------------------------------------------------------------------

1190          public function encodeModeStructure()
1191          {
1192              try {
1193                  $bs =  new QRbitstream();
1194                  
1195                  $bs->appendNum(4, 0x03);
1196                  $bs->appendNum(4, ord($this->data[1]) - 1);
1197                  $bs->appendNum(4, ord($this->data[0]) - 1);
1198                  $bs->appendNum(8, ord($this->data[2]));
1199  
1200                  $this->bstream = $bs;
1201                  return 0;
1202              
1203              } catch (Exception $e) {
1204                  return -1;
1205              }
1206          }
1207          
1208          //----------------------------------------------------------------------

1209          public function estimateBitStreamSizeOfEntry($version)
1210          {
1211              $bits = 0;
1212  
1213              if($version == 0) 
1214                  $version = 1;
1215  
1216              switch($this->mode) {
1217                  case QR_MODE_NUM:        $bits = QRinput::estimateBitsModeNum($this->size);    break;
1218                  case QR_MODE_AN:        $bits = QRinput::estimateBitsModeAn($this->size);    break;
1219                  case QR_MODE_8:            $bits = QRinput::estimateBitsMode8($this->size);    break;
1220                  case QR_MODE_KANJI:        $bits = QRinput::estimateBitsModeKanji($this->size);break;
1221                  case QR_MODE_STRUCTURE:    return STRUCTURE_HEADER_BITS;            
1222                  default:
1223                      return 0;
1224              }
1225  
1226              $l = QRspec::lengthIndicator($this->mode, $version);
1227              $m = 1 << $l;
1228              $num = (int)(($this->size + $m - 1) / $m);
1229  
1230              $bits += $num * (4 + $l);
1231  
1232              return $bits;
1233          }
1234          
1235          //----------------------------------------------------------------------

1236          public function encodeBitStream($version)
1237          {
1238              try {
1239              
1240                  unset($this->bstream);
1241                  $words = QRspec::maximumWords($this->mode, $version);
1242                  
1243                  if($this->size > $words) {
1244                  
1245                      $st1 = new QRinputItem($this->mode, $words, $this->data);
1246                      $st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words));
1247  
1248                      $st1->encodeBitStream($version);
1249                      $st2->encodeBitStream($version);
1250                      
1251                      $this->bstream = new QRbitstream();
1252                      $this->bstream->append($st1->bstream);
1253                      $this->bstream->append($st2->bstream);
1254                      
1255                      unset($st1);
1256                      unset($st2);
1257                      
1258                  } else {
1259                      
1260                      $ret = 0;
1261                      
1262                      switch($this->mode) {
1263                          case QR_MODE_NUM:        $ret = $this->encodeModeNum($version);    break;
1264                          case QR_MODE_AN:        $ret = $this->encodeModeAn($version);    break;
1265                          case QR_MODE_8:            $ret = $this->encodeMode8($version);    break;
1266                          case QR_MODE_KANJI:        $ret = $this->encodeModeKanji($version);break;
1267                          case QR_MODE_STRUCTURE:    $ret = $this->encodeModeStructure();    break;
1268                          
1269                          default:
1270                              break;
1271                      }
1272                      
1273                      if($ret < 0)
1274                          return -1;
1275                  }
1276  
1277                  return $this->bstream->size();
1278              
1279              } catch (Exception $e) {
1280                  return -1;
1281              }
1282          }
1283      };
1284      
1285      //##########################################################################

1286  
1287      class QRinput {
1288  
1289          public $items;
1290          
1291          private $version;
1292          private $level;
1293          
1294          //----------------------------------------------------------------------

1295          public function __construct($version = 0, $level = QR_ECLEVEL_L)
1296          {
1297              if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) {
1298                  throw new Exception('Invalid version no');
1299                  return NULL;
1300              }
1301              
1302              $this->version = $version;
1303              $this->level = $level;
1304          }
1305          
1306          //----------------------------------------------------------------------

1307          public function getVersion()
1308          {
1309              return $this->version;
1310          }
1311          
1312          //----------------------------------------------------------------------

1313          public function setVersion($version)
1314          {
1315              if($version < 0 || $version > QRSPEC_VERSION_MAX) {
1316                  throw new Exception('Invalid version no');
1317                  return -1;
1318              }
1319  
1320              $this->version = $version;
1321  
1322              return 0;
1323          }
1324          
1325          //----------------------------------------------------------------------

1326          public function getErrorCorrectionLevel()
1327          {
1328              return $this->level;
1329          }
1330  
1331          //----------------------------------------------------------------------

1332          public function setErrorCorrectionLevel($level)
1333          {
1334              if($level > QR_ECLEVEL_H) {
1335                  throw new Exception('Invalid ECLEVEL');
1336                  return -1;
1337              }
1338  
1339              $this->level = $level;
1340  
1341              return 0;
1342          }
1343          
1344          //----------------------------------------------------------------------

1345          public function appendEntry(QRinputItem $entry)
1346          {
1347              $this->items[] = $entry;
1348          }
1349          
1350          //----------------------------------------------------------------------

1351          public function append($mode, $size, $data)
1352          {
1353              try {
1354                  $entry = new QRinputItem($mode, $size, $data);
1355                  $this->items[] = $entry;
1356                  return 0;
1357              } catch (Exception $e) {
1358                  return -1;
1359              }
1360          }
1361          
1362          //----------------------------------------------------------------------

1363          
1364          public function insertStructuredAppendHeader($size, $index, $parity)
1365          {
1366              if( $size > MAX_STRUCTURED_SYMBOLS ) {
1367                  throw new Exception('insertStructuredAppendHeader wrong size');
1368              }
1369              
1370              if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) {
1371                  throw new Exception('insertStructuredAppendHeader wrong index');
1372              }
1373  
1374              $buf = array($size, $index, $parity);
1375              
1376              try {
1377                  $entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf);
1378                  array_unshift($this->items, $entry);
1379                  return 0;
1380              } catch (Exception $e) {
1381                  return -1;
1382              }
1383          }
1384  
1385          //----------------------------------------------------------------------

1386          public function calcParity()
1387          {
1388              $parity = 0;
1389              
1390              foreach($this->items as $item) {
1391                  if($item->mode != QR_MODE_STRUCTURE) {
1392                      for($i=$item->size-1; $i>=0; $i--) {
1393                          $parity ^= $item->data[$i];
1394                      }
1395                  }
1396              }
1397  
1398              return $parity;
1399          }
1400          
1401          //----------------------------------------------------------------------

1402          public static function checkModeNum($size, $data)
1403          {
1404              for($i=0; $i<$size; $i++) {
1405                  if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){
1406                      return false;
1407                  }
1408              }
1409  
1410              return true;
1411          }
1412  
1413          //----------------------------------------------------------------------

1414          public static function estimateBitsModeNum($size)
1415          {
1416              $w = (int)$size / 3;
1417              $bits = $w * 10;
1418              
1419              switch($size - $w * 3) {
1420                  case 1:
1421                      $bits += 4;
1422                      break;
1423                  case 2:
1424                      $bits += 7;
1425                      break;
1426                  default:
1427                      break;
1428              }
1429  
1430              return $bits;
1431          }
1432          
1433          //----------------------------------------------------------------------

1434          public static $anTable = array(
1435              -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1436              -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1437              36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
1438               0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 44, -1, -1, -1, -1, -1,
1439              -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1440              25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
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          );
1444          
1445          //----------------------------------------------------------------------

1446          public static function lookAnTable($c)
1447          {
1448              return (($c > 127)?-1:self::$anTable[$c]);
1449          }
1450          
1451          //----------------------------------------------------------------------

1452          public static function checkModeAn($size, $data)
1453          {
1454              for($i=0; $i<$size; $i++) {
1455                  if (self::lookAnTable(ord($data[$i])) == -1) {
1456                      return false;
1457                  }
1458              }
1459  
1460              return true;
1461          }
1462          
1463          //----------------------------------------------------------------------

1464          public static function estimateBitsModeAn($size)
1465          {
1466              $w = (int)($size / 2);
1467              $bits = $w * 11;
1468              
1469              if($size & 1) {
1470                  $bits += 6;
1471              }
1472  
1473              return $bits;
1474          }
1475      
1476          //----------------------------------------------------------------------

1477          public static function estimateBitsMode8($size)
1478          {
1479              return $size * 8;
1480          }
1481          
1482          //----------------------------------------------------------------------

1483          public function estimateBitsModeKanji($size)
1484          {
1485              return (int)(($size / 2) * 13);
1486          }
1487          
1488          //----------------------------------------------------------------------

1489          public static function checkModeKanji($size, $data)
1490          {
1491              if($size & 1)
1492                  return false;
1493  
1494              for($i=0; $i<$size; $i+=2) {
1495                  $val = (ord($data[$i]) << 8) | ord($data[$i+1]);
1496                  if( $val < 0x8140 
1497                  || ($val > 0x9ffc && $val < 0xe040) 
1498                  || $val > 0xebbf) {
1499                      return false;
1500                  }
1501              }
1502  
1503              return true;
1504          }
1505  
1506          /***********************************************************************

1507           * Validation

1508           **********************************************************************/
1509  
1510          public static function check($mode, $size, $data)
1511          {
1512              if($size <= 0) 
1513                  return false;
1514  
1515              switch($mode) {
1516                  case QR_MODE_NUM:       return self::checkModeNum($size, $data);   break;
1517                  case QR_MODE_AN:        return self::checkModeAn($size, $data);    break;
1518                  case QR_MODE_KANJI:     return self::checkModeKanji($size, $data); break;
1519                  case QR_MODE_8:         return true; break;
1520                  case QR_MODE_STRUCTURE: return true; break;
1521                  
1522                  default:
1523                      break;
1524              }
1525  
1526              return false;
1527          }
1528          
1529          
1530          //----------------------------------------------------------------------

1531          public function estimateBitStreamSize($version)
1532          {
1533              $bits = 0;
1534  
1535              foreach($this->items as $item) {
1536                  $bits += $item->estimateBitStreamSizeOfEntry($version);
1537              }
1538  
1539              return $bits;
1540          }
1541          
1542          //----------------------------------------------------------------------

1543          public function estimateVersion()
1544          {
1545              $version = 0;
1546              $prev = 0;
1547              do {
1548                  $prev = $version;
1549                  $bits = $this->estimateBitStreamSize($prev);
1550                  $version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
1551                  if ($version < 0) {
1552                      return -1;
1553                  }
1554              } while ($version > $prev);
1555  
1556              return $version;
1557          }
1558          
1559          //----------------------------------------------------------------------

1560          public static function lengthOfCode($mode, $version, $bits)
1561          {
1562              $payload = $bits - 4 - QRspec::lengthIndicator($mode, $version);
1563              switch($mode) {
1564                  case QR_MODE_NUM:
1565                      $chunks = (int)($payload / 10);
1566                      $remain = $payload - $chunks * 10;
1567                      $size = $chunks * 3;
1568                      if($remain >= 7) {
1569                          $size += 2;
1570                      } else if($remain >= 4) {
1571                          $size += 1;
1572                      }
1573                      break;
1574                  case QR_MODE_AN:
1575                      $chunks = (int)($payload / 11);
1576                      $remain = $payload - $chunks * 11;
1577                      $size = $chunks * 2;
1578                      if($remain >= 6) 
1579                          $size++;
1580                      break;
1581                  case QR_MODE_8:
1582                      $size = (int)($payload / 8);
1583                      break;
1584                  case QR_MODE_KANJI:
1585                      $size = (int)(($payload / 13) * 2);
1586                      break;
1587                  case QR_MODE_STRUCTURE:
1588                      $size = (int)($payload / 8);
1589                      break;
1590                  default:
1591                      $size = 0;
1592                      break;
1593              }
1594              
1595              $maxsize = QRspec::maximumWords($mode, $version);
1596              if($size < 0) $size = 0;
1597              if($size > $maxsize) $size = $maxsize;
1598  
1599              return $size;
1600          }
1601          
1602          //----------------------------------------------------------------------

1603          public function createBitStream()
1604          {
1605              $total = 0;
1606  
1607              foreach($this->items as $item) {
1608                  $bits = $item->encodeBitStream($this->version);
1609                  
1610                  if($bits < 0) 
1611                      return -1;
1612                      
1613                  $total += $bits;
1614              }
1615  
1616              return $total;
1617          }
1618          
1619          //----------------------------------------------------------------------

1620          public function convertData()
1621          {
1622              $ver = $this->estimateVersion();
1623              if($ver > $this->getVersion()) {
1624                  $this->setVersion($ver);
1625              }
1626  
1627              for(;;) {
1628                  $bits = $this->createBitStream();
1629                  
1630                  if($bits < 0) 
1631                      return -1;
1632                      
1633                  $ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
1634                  if($ver < 0) {
1635                      throw new Exception('WRONG VERSION');
1636                      return -1;
1637                  } else if($ver > $this->getVersion()) {
1638                      $this->setVersion($ver);
1639                  } else {
1640                      break;
1641                  }
1642              }
1643  
1644              return 0;
1645          }
1646          
1647          //----------------------------------------------------------------------

1648          public function appendPaddingBit(&$bstream)
1649          {
1650              $bits = $bstream->size();
1651              $maxwords = QRspec::getDataLength($this->version, $this->level);
1652              $maxbits = $maxwords * 8;
1653  
1654              if ($maxbits == $bits) {
1655                  return 0;
1656              }
1657  
1658              if ($maxbits - $bits < 5) {
1659                  return $bstream->appendNum($maxbits - $bits, 0);
1660              }
1661  
1662              $bits += 4;
1663              $words = (int)(($bits + 7) / 8);
1664  
1665              $padding = new QRbitstream();
1666              $ret = $padding->appendNum($words * 8 - $bits + 4, 0);
1667              
1668              if($ret < 0) 
1669                  return $ret;
1670  
1671              $padlen = $maxwords - $words;
1672              
1673              if($padlen > 0) {
1674                  
1675                  $padbuf = array();
1676                  for($i=0; $i<$padlen; $i++) {
1677                      $padbuf[$i] = ($i&1)?0x11:0xec;
1678                  }
1679                  
1680                  $ret = $padding->appendBytes($padlen, $padbuf);
1681                  
1682                  if($ret < 0)
1683                      return $ret;
1684                  
1685              }
1686  
1687              $ret = $bstream->append($padding);
1688              
1689              return $ret;
1690          }
1691  
1692          //----------------------------------------------------------------------

1693          public function mergeBitStream()
1694          {
1695              if($this->convertData() < 0) {
1696                  return null;
1697              }
1698  
1699              $bstream = new QRbitstream();
1700              
1701              foreach($this->items as $item) {
1702                  $ret = $bstream->append($item->bstream);
1703                  if($ret < 0) {
1704                      return null;
1705                  }
1706              }
1707  
1708              return $bstream;
1709          }
1710  
1711          //----------------------------------------------------------------------

1712          public function getBitStream()
1713          {
1714  
1715              $bstream = $this->mergeBitStream();
1716              
1717              if($bstream == null) {
1718                  return null;
1719              }
1720              
1721              $ret = $this->appendPaddingBit($bstream);
1722              if($ret < 0) {
1723                  return null;
1724              }
1725  
1726              return $bstream;
1727          }
1728          
1729          //----------------------------------------------------------------------

1730          public function getByteStream()
1731          {
1732              $bstream = $this->getBitStream();
1733              if($bstream == null) {
1734                  return null;
1735              }
1736              
1737              return $bstream->toByte();
1738          }
1739      }
1740          
1741          
1742      
1743  
1744  
1745  
1746  //---- qrbitstream.php -----------------------------
1747  
1748  
1749  
1750  
1751  /*

1752   * PHP QR Code encoder

1753   *

1754   * Bitstream class

1755   *

1756   * Based on libqrencode C library distributed under LGPL 2.1

1757   * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>

1758   *

1759   * PHP QR Code is distributed under LGPL 3

1760   * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>

1761   *

1762   * This library is free software; you can redistribute it and/or

1763   * modify it under the terms of the GNU Lesser General Public

1764   * License as published by the Free Software Foundation; either

1765   * version 3 of the License, or any later version.

1766   *

1767   * This library is distributed in the hope that it will be useful,

1768   * but WITHOUT ANY WARRANTY; without even the implied warranty of

1769   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

1770   * Lesser General Public License for more details.

1771   *

1772   * You should have received a copy of the GNU Lesser General Public

1773   * License along with this library; if not, write to the Free Software

1774   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

1775   */
1776       
1777      class QRbitstream {
1778      
1779          public $data = array();
1780          
1781          //----------------------------------------------------------------------

1782          public function size()
1783          {
1784              return count($this->data);
1785          }
1786          
1787          //----------------------------------------------------------------------

1788          public function allocate($setLength)
1789          {
1790              $this->data = array_fill(0, $setLength, 0);
1791              return 0;
1792          }
1793      
1794          //----------------------------------------------------------------------

1795          public static function newFromNum($bits, $num)
1796          {
1797              $bstream = new QRbitstream();
1798              $bstream->allocate($bits);
1799              
1800              $mask = 1 << ($bits - 1);
1801              for($i=0; $i<$bits; $i++) {
1802                  if($num & $mask) {
1803                      $bstream->data[$i] = 1;
1804                  } else {
1805                      $bstream->data[$i] = 0;
1806                  }
1807                  $mask = $mask >> 1;
1808              }
1809  
1810              return $bstream;
1811          }
1812          
1813          //----------------------------------------------------------------------

1814          public static function newFromBytes($size, $data)
1815          {
1816              $bstream = new QRbitstream();
1817              $bstream->allocate($size * 8);
1818              $p=0;
1819  
1820              for($i=0; $i<$size; $i++) {
1821                  $mask = 0x80;
1822                  for($j=0; $j<8; $j++) {
1823                      if($data[$i] & $mask) {
1824                          $bstream->data[$p] = 1;
1825                      } else {
1826                          $bstream->data[$p] = 0;
1827                      }
1828                      $p++;
1829                      $mask = $mask >> 1;
1830                  }
1831              }
1832  
1833              return $bstream;
1834          }
1835          
1836          //----------------------------------------------------------------------

1837          public function append(QRbitstream $arg)
1838          {
1839              if (is_null($arg)) {
1840                  return -1;
1841              }
1842              
1843              if($arg->size() == 0) {
1844                  return 0;
1845              }
1846              
1847              if($this->size() == 0) {
1848                  $this->data = $arg->data;
1849                  return 0;
1850              }
1851              
1852              $this->data = array_values(array_merge($this->data, $arg->data));
1853  
1854              return 0;
1855          }
1856          
1857          //----------------------------------------------------------------------

1858          public function appendNum($bits, $num)
1859          {
1860              if ($bits == 0) 
1861                  return 0;
1862  
1863              $b = QRbitstream::newFromNum($bits, $num);
1864              
1865              if(is_null($b))
1866                  return -1;
1867  
1868              $ret = $this->append($b);
1869              unset($b);
1870  
1871              return $ret;
1872          }
1873  
1874          //----------------------------------------------------------------------

1875          public function appendBytes($size, $data)
1876          {
1877              if ($size == 0) 
1878                  return 0;
1879  
1880              $b = QRbitstream::newFromBytes($size, $data);
1881              
1882              if(is_null($b))
1883                  return -1;
1884  
1885              $ret = $this->append($b);
1886              unset($b);
1887  
1888              return $ret;
1889          }
1890          
1891          //----------------------------------------------------------------------

1892          public function toByte()
1893          {
1894          
1895              $size = $this->size();
1896  
1897              if($size == 0) {
1898                  return array();
1899              }
1900              
1901              $data = array_fill(0, (int)(($size + 7) / 8), 0);
1902              $bytes = (int)($size / 8);
1903  
1904              $p = 0;
1905              
1906              for($i=0; $i<$bytes; $i++) {
1907                  $v = 0;
1908                  for($j=0; $j<8; $j++) {
1909                      $v = $v << 1;
1910                      $v |= $this->data[$p];
1911                      $p++;
1912                  }
1913                  $data[$i] = $v;
1914              }
1915              
1916              if($size & 7) {
1917                  $v = 0;
1918                  for($j=0; $j<($size & 7); $j++) {
1919                      $v = $v << 1;
1920                      $v |= $this->data[$p];
1921                      $p++;
1922                  }
1923                  $data[$bytes] = $v;
1924              }
1925  
1926              return $data;
1927          }
1928  
1929      }
1930  
1931  
1932  
1933  
1934  //---- qrsplit.php -----------------------------
1935  
1936  
1937  
1938  
1939  /*

1940   * PHP QR Code encoder

1941   *

1942   * Input splitting classes

1943   *

1944   * Based on libqrencode C library distributed under LGPL 2.1

1945   * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>

1946   *

1947   * PHP QR Code is distributed under LGPL 3

1948   * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>

1949   *

1950   * The following data / specifications are taken from

1951   * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)

1952   *  or

1953   * "Automatic identification and data capture techniques -- 

1954   *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)

1955   *

1956   * This library is free software; you can redistribute it and/or

1957   * modify it under the terms of the GNU Lesser General Public

1958   * License as published by the Free Software Foundation; either

1959   * version 3 of the License, or any later version.

1960   *

1961   * This library is distributed in the hope that it will be useful,

1962   * but WITHOUT ANY WARRANTY; without even the implied warranty of

1963   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

1964   * Lesser General Public License for more details.

1965   *

1966   * You should have received a copy of the GNU Lesser General Public

1967   * License along with this library; if not, write to the Free Software

1968   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

1969   */
1970      class QRsplit {
1971  
1972          public $dataStr = '';
1973          public $input;
1974          public $modeHint;
1975  
1976          //----------------------------------------------------------------------

1977          public function __construct($dataStr, $input, $modeHint) 
1978          {
1979              $this->dataStr  = $dataStr;
1980              $this->input    = $input;
1981              $this->modeHint = $modeHint;
1982          }
1983          
1984          //----------------------------------------------------------------------

1985          public static function isdigitat($str, $pos)
1986          {    
1987              if ($pos >= strlen($str))
1988                  return false;
1989              
1990              return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
1991          }
1992          
1993          //----------------------------------------------------------------------

1994          public static function isalnumat($str, $pos)
1995          {
1996              if ($pos >= strlen($str))
1997                  return false;
1998                  
1999              return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
2000          }
2001  
2002          //----------------------------------------------------------------------

2003          public function identifyMode($pos)
2004          {
2005              if ($pos >= strlen($this->dataStr)) 
2006                  return QR_MODE_NUL;
2007                  
2008              $c = $this->dataStr[$pos];
2009              
2010              if(self::isdigitat($this->dataStr, $pos)) {
2011                  return QR_MODE_NUM;
2012              } else if(self::isalnumat($this->dataStr, $pos)) {
2013                  return QR_MODE_AN;
2014              } else if($this->modeHint == QR_MODE_KANJI) {
2015              
2016                  if ($pos+1 < strlen($this->dataStr)) 
2017                  {
2018                      $d = $this->dataStr[$pos+1];
2019                      $word = (ord($c) << 8) | ord($d);
2020                      if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
2021                          return QR_MODE_KANJI;
2022                      }
2023                  }
2024              }
2025  
2026              return QR_MODE_8;
2027          } 
2028          
2029          //----------------------------------------------------------------------

2030          public function eatNum()
2031          {
2032              $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
2033  
2034              $p = 0;
2035              while(self::isdigitat($this->dataStr, $p)) {
2036                  $p++;
2037              }
2038              
2039              $run = $p;
2040              $mode = $this->identifyMode($p);
2041              
2042              if($mode == QR_MODE_8) {
2043                  $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
2044                       + QRinput::estimateBitsMode8(1)         // + 4 + l8
2045                       - QRinput::estimateBitsMode8($run + 1); // - 4 - l8

2046                  if($dif > 0) {
2047                      return $this->eat8();
2048                  }
2049              }
2050              if($mode == QR_MODE_AN) {
2051                  $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
2052                       + QRinput::estimateBitsModeAn(1)        // + 4 + la
2053                       - QRinput::estimateBitsModeAn($run + 1);// - 4 - la

2054                  if($dif > 0) {
2055                      return $this->eatAn();
2056                  }
2057              }
2058              
2059              $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
2060              if($ret < 0)
2061                  return -1;
2062  
2063              return $run;
2064          }
2065          
2066          //----------------------------------------------------------------------

2067          public function eatAn()
2068          {
2069              $la = QRspec::lengthIndicator(QR_MODE_AN,  $this->input->getVersion());
2070              $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
2071  
2072              $p = 0;
2073              
2074              while(self::isalnumat($this->dataStr, $p)) {
2075                  if(self::isdigitat($this->dataStr, $p)) {
2076                      $q = $p;
2077                      while(self::isdigitat($this->dataStr, $q)) {
2078                          $q++;
2079                      }
2080                      
2081                      $dif = QRinput::estimateBitsModeAn($p) // + 4 + la
2082                           + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
2083                           - QRinput::estimateBitsModeAn($q); // - 4 - la

2084                           
2085                      if($dif < 0) {
2086                          break;
2087                      } else {
2088                          $p = $q;
2089                      }
2090                  } else {
2091                      $p++;
2092                  }
2093              }
2094  
2095              $run = $p;
2096  
2097              if(!self::isalnumat($this->dataStr, $p)) {
2098                  $dif = QRinput::estimateBitsModeAn($run) + 4 + $la
2099                       + QRinput::estimateBitsMode8(1) // + 4 + l8
2100                        - QRinput::estimateBitsMode8($run + 1); // - 4 - l8

2101                  if($dif > 0) {
2102                      return $this->eat8();
2103                  }
2104              }
2105  
2106              $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
2107              if($ret < 0)
2108                  return -1;
2109  
2110              return $run;
2111          }
2112          
2113          //----------------------------------------------------------------------

2114          public function eatKanji()
2115          {
2116              $p = 0;
2117              
2118              while($this->identifyMode($p) == QR_MODE_KANJI) {
2119                  $p += 2;
2120              }
2121              
2122              $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
2123              if($ret < 0)
2124                  return -1;
2125  
2126              return $run;
2127          }
2128  
2129          //----------------------------------------------------------------------

2130          public function eat8()
2131          {
2132              $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
2133              $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
2134  
2135              $p = 1;
2136              $dataStrLen = strlen($this->dataStr);
2137              
2138              while($p < $dataStrLen) {
2139                  
2140                  $mode = $this->identifyMode($p);
2141                  if($mode == QR_MODE_KANJI) {
2142                      break;
2143                  }
2144                  if($mode == QR_MODE_NUM) {
2145                      $q = $p;
2146                      while(self::isdigitat($this->dataStr, $q)) {
2147                          $q++;
2148                      }
2149                      $dif = QRinput::estimateBitsMode8($p) // + 4 + l8
2150                           + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
2151                           - QRinput::estimateBitsMode8($q); // - 4 - l8

2152                      if($dif < 0) {
2153                          break;
2154                      } else {
2155                          $p = $q;
2156                      }
2157                  } else if($mode == QR_MODE_AN) {
2158                      $q = $p;
2159                      while(self::isalnumat($this->dataStr, $q)) {
2160                          $q++;
2161                      }
2162                      $dif = QRinput::estimateBitsMode8($p)  // + 4 + l8
2163                           + QRinput::estimateBitsModeAn($q - $p) + 4 + $la
2164                           - QRinput::estimateBitsMode8($q); // - 4 - l8

2165                      if($dif < 0) {
2166                          break;
2167                      } else {
2168                          $p = $q;
2169                      }
2170                  } else {
2171                      $p++;
2172                  }
2173              }
2174  
2175              $run = $p;
2176              $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
2177              
2178              if($ret < 0)
2179                  return -1;
2180  
2181              return $run;
2182          }
2183  
2184          //----------------------------------------------------------------------

2185          public function splitString()
2186          {
2187              while (strlen($this->dataStr) > 0)
2188              {
2189                  if($this->dataStr == '')
2190                      return 0;
2191  
2192                  $mode = $this->identifyMode(0);
2193                  
2194                  switch ($mode) {
2195                      case QR_MODE_NUM: $length = $this->eatNum(); break;
2196                      case QR_MODE_AN:  $length = $this->eatAn(); break;
2197                      case QR_MODE_KANJI:
2198                          if ($hint == QR_MODE_KANJI)
2199                                  $length = $this->eatKanji();
2200                          else    $length = $this->eat8();
2201                          break;
2202                      default: $length = $this->eat8(); break;
2203                  
2204                  }
2205  
2206                  if($length == 0) return 0;
2207                  if($length < 0)  return -1;
2208                  
2209                  $this->dataStr = substr($this->dataStr, $length);
2210              }
2211          }
2212  
2213          //----------------------------------------------------------------------

2214          public function toUpper()
2215          {
2216              $stringLen = strlen($this->dataStr);
2217              $p = 0;
2218              
2219              while ($p<$stringLen) {
2220                  $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
2221                  if($mode == QR_MODE_KANJI) {
2222                      $p += 2;
2223                  } else {
2224                      if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
2225                          $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
2226                      }
2227                      $p++;
2228                  }
2229              }
2230  
2231              return $this->dataStr;
2232          }
2233  
2234          //----------------------------------------------------------------------

2235          public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
2236          {
2237              if(is_null($string) || $string == '\0' || $string == '') {
2238                  throw new Exception('empty string!!!');
2239              }
2240  
2241              $split = new QRsplit($string, $input, $modeHint);
2242              
2243              if(!$casesensitive)
2244                  $split->toUpper();
2245                  
2246              return $split->splitString();
2247          }
2248      }
2249  
2250  
2251  
2252  //---- qrrscode.php -----------------------------
2253  
2254  
2255  
2256  
2257  /*

2258   * PHP QR Code encoder

2259   *

2260   * Reed-Solomon error correction support

2261   * 

2262   * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q

2263   * (libfec is released under the GNU Lesser General Public License.)

2264   *

2265   * Based on libqrencode C library distributed under LGPL 2.1

2266   * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>

2267   *

2268   * PHP QR Code is distributed under LGPL 3

2269   * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>

2270   *

2271   * This library is free software; you can redistribute it and/or

2272   * modify it under the terms of the GNU Lesser General Public

2273   * License as published by the Free Software Foundation; either

2274   * version 3 of the License, or any later version.

2275   *

2276   * This library is distributed in the hope that it will be useful,

2277   * but WITHOUT ANY WARRANTY; without even the implied warranty of

2278   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

2279   * Lesser General Public License for more details.

2280   *

2281   * You should have received a copy of the GNU Lesser General Public

2282   * License along with this library; if not, write to the Free Software

2283   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

2284   */
2285   
2286      class QRrsItem {
2287      
2288          public $mm;                  // Bits per symbol 

2289          public $nn;                  // Symbols per block (= (1<<mm)-1) 

2290          public $alpha_to = array();  // log lookup table 

2291          public $index_of = array();  // Antilog lookup table 

2292          public $genpoly = array();   // Generator polynomial 

2293          public $nroots;              // Number of generator roots = number of parity symbols 

2294          public $fcr;                 // First consecutive root, index form 

2295          public $prim;                // Primitive element, index form 

2296          public $iprim;               // prim-th root of 1, index form 

2297          public $pad;                 // Padding bytes in shortened block 

2298          public $gfpoly;
2299      
2300          //----------------------------------------------------------------------

2301          public function modnn($x)
2302          {
2303              while ($x >= $this->nn) {
2304                  $x -= $this->nn;
2305                  $x = ($x >> $this->mm) + ($x & $this->nn);
2306              }
2307              
2308              return $x;
2309          }
2310          
2311          //----------------------------------------------------------------------

2312          public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
2313          {
2314              // Common code for intializing a Reed-Solomon control block (char or int symbols)

2315              // Copyright 2004 Phil Karn, KA9Q

2316              // May be used under the terms of the GNU Lesser General Public License (LGPL)

2317  
2318              $rs = null;
2319              
2320              // Check parameter ranges

2321              if($symsize < 0 || $symsize > 8)                     return $rs;
2322              if($fcr < 0 || $fcr >= (1<<$symsize))                return $rs;
2323              if($prim <= 0 || $prim >= (1<<$symsize))             return $rs;
2324              if($nroots < 0 || $nroots >= (1<<$symsize))          return $rs; // Can't have more roots than symbol values!

2325              if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding

2326  
2327              $rs = new QRrsItem();
2328              $rs->mm = $symsize;
2329              $rs->nn = (1<<$symsize)-1;
2330              $rs->pad = $pad;
2331  
2332              $rs->alpha_to = array_fill(0, $rs->nn+1, 0);
2333              $rs->index_of = array_fill(0, $rs->nn+1, 0);
2334            
2335              // PHP style macro replacement ;)

2336              $NN =& $rs->nn;
2337              $A0 =& $NN;
2338              
2339              // Generate Galois field lookup tables

2340              $rs->index_of[0] = $A0; // log(zero) = -inf

2341              $rs->alpha_to[$A0] = 0; // alpha**-inf = 0

2342              $sr = 1;
2343            
2344              for($i=0; $i<$rs->nn; $i++) {
2345                  $rs->index_of[$sr] = $i;
2346                  $rs->alpha_to[$i] = $sr;
2347                  $sr <<= 1;
2348                  if($sr & (1<<$symsize)) {
2349                      $sr ^= $gfpoly;
2350                  }
2351                  $sr &= $rs->nn;
2352              }
2353              
2354              if($sr != 1){
2355                  // field generator polynomial is not primitive!

2356                  $rs = NULL;
2357                  return $rs;
2358              }
2359  
2360              /* Form RS code generator polynomial from its roots */

2361              $rs->genpoly = array_fill(0, $nroots+1, 0);
2362          
2363              $rs->fcr = $fcr;
2364              $rs->prim = $prim;
2365              $rs->nroots = $nroots;
2366              $rs->gfpoly = $gfpoly;
2367  
2368              /* Find prim-th root of 1, used in decoding */

2369              for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)
2370              ; // intentional empty-body loop!

2371              
2372              $rs->iprim = (int)($iprim / $prim);
2373              $rs->genpoly[0] = 1;
2374              
2375              for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
2376                  $rs->genpoly[$i+1] = 1;
2377  
2378                  // Multiply rs->genpoly[] by  @**(root + x)

2379                  for ($j = $i; $j > 0; $j--) {
2380                      if ($rs->genpoly[$j] != 0) {
2381                          $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];
2382                      } else {
2383                          $rs->genpoly[$j] = $rs->genpoly[$j-1];
2384                      }
2385                  }
2386                  // rs->genpoly[0] can never be zero

2387                  $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
2388              }
2389              
2390              // convert rs->genpoly[] to index form for quicker encoding

2391              for ($i = 0; $i <= $nroots; $i++)
2392                  $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
2393  
2394              return $rs;
2395          }
2396          
2397          //----------------------------------------------------------------------

2398          public function encode_rs_char($data, &$parity)
2399          {
2400              $MM       =& $this->mm;
2401              $NN       =& $this->nn;
2402              $ALPHA_TO =& $this->alpha_to;
2403              $INDEX_OF =& $this->index_of;
2404              $GENPOLY  =& $this->genpoly;
2405              $NROOTS   =& $this->nroots;
2406              $FCR      =& $this->fcr;
2407              $PRIM     =& $this->prim;
2408              $IPRIM    =& $this->iprim;
2409              $PAD      =& $this->pad;
2410              $A0       =& $NN;
2411  
2412              $parity = array_fill(0, $NROOTS, 0);
2413  
2414              for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) {
2415                  
2416                  $feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
2417                  if($feedback != $A0) {      
2418                      // feedback term is non-zero

2419              
2420                      // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must

2421                      // always be for the polynomials constructed by init_rs()

2422                      $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);
2423              
2424                      for($j=1;$j<$NROOTS;$j++) {
2425                          $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])];
2426                      }
2427                  }
2428                  
2429                  // Shift 

2430                  array_shift($parity);
2431                  if($feedback != $A0) {
2432                      array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);
2433                  } else {
2434                      array_push($parity, 0);
2435                  }
2436              }
2437          }
2438      }
2439      
2440      //##########################################################################

2441      
2442      class QRrs {
2443      
2444          public static $items = array();
2445          
2446          //----------------------------------------------------------------------

2447          public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
2448          {
2449              foreach(self::$items as $rs) {
2450                  if($rs->pad != $pad)       continue;
2451                  if($rs->nroots != $nroots) continue;
2452                  if($rs->mm != $symsize)    continue;
2453                  if($rs->gfpoly != $gfpoly) continue;
2454                  if($rs->fcr != $fcr)       continue;
2455                  if($rs->prim != $prim)     continue;
2456  
2457                  return $rs;
2458              }
2459  
2460              $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
2461              array_unshift(self::$items, $rs);
2462  
2463              return $rs;
2464          }
2465      }
2466  
2467  
2468  
2469  //---- qrmask.php -----------------------------
2470  
2471  
2472  
2473  
2474  /*

2475   * PHP QR Code encoder

2476   *

2477   * Masking

2478   *

2479   * Based on libqrencode C library distributed under LGPL 2.1

2480   * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>

2481   *

2482   * PHP QR Code is distributed under LGPL 3

2483   * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>

2484   *

2485   * This library is free software; you can redistribute it and/or

2486   * modify it under the terms of the GNU Lesser General Public

2487   * License as published by the Free Software Foundation; either

2488   * version 3 of the License, or any later version.

2489   *

2490   * This library is distributed in the hope that it will be useful,

2491   * but WITHOUT ANY WARRANTY; without even the implied warranty of

2492   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

2493   * Lesser General Public License for more details.

2494   *

2495   * You should have received a copy of the GNU Lesser General Public

2496   * License along with this library; if not, write to the Free Software

2497   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

2498   */
2499   
2500      define('N1', 3);
2501      define('N2', 3);
2502      define('N3', 40);
2503      define('N4', 10);
2504  
2505      class QRmask {
2506      
2507          public $runLength = array();
2508          
2509          //----------------------------------------------------------------------

2510  		public function __construct() 
2511          {
2512              $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
2513          }
2514          
2515          //----------------------------------------------------------------------

2516          public function writeFormatInformation($width, &$frame, $mask, $level)
2517          {
2518              $blacks = 0;
2519              $format =  QRspec::getFormatInfo($mask, $level);
2520  
2521              for($i=0; $i<8; $i++) {
2522                  if($format & 1) {
2523                      $blacks += 2;
2524                      $v = 0x85;
2525                  } else {
2526                      $v = 0x84;
2527                  }
2528                  
2529                  $frame[8][$width - 1 - $i] = chr($v);
2530                  if($i < 6) {
2531                      $frame[$i][8] = chr($v);
2532                  } else {
2533                      $frame[$i + 1][8] = chr($v);
2534                  }
2535                  $format = $format >> 1;
2536              }
2537              
2538              for($i=0; $i<7; $i++) {
2539                  if($format & 1) {
2540                      $blacks += 2;
2541                      $v = 0x85;
2542                  } else {
2543                      $v = 0x84;
2544                  }
2545                  
2546                  $frame[$width - 7 + $i][8] = chr($v);
2547                  if($i == 0) {
2548                      $frame[8][7] = chr($v);
2549                  } else {
2550                      $frame[8][6 - $i] = chr($v);
2551                  }
2552                  
2553                  $format = $format >> 1;
2554              }
2555  
2556              return $blacks;
2557          }
2558          
2559          //----------------------------------------------------------------------

2560          public function mask0($x, $y) { return ($x+$y)&1;                       }
2561          public function mask1($x, $y) { return ($y&1);                          }
2562          public function mask2($x, $y) { return ($x%3);                          }
2563          public function mask3($x, $y) { return ($x+$y)%3;                       }
2564          public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; }
2565          public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3;           }
2566          public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1;       }
2567          public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1;     }
2568          
2569          //----------------------------------------------------------------------

2570          private function generateMaskNo($maskNo, $width, $frame)
2571          {
2572              $bitMask = array_fill(0, $width, array_fill(0, $width, 0));
2573              
2574              for($y=0; $y<$width; $y++) {
2575                  for($x=0; $x<$width; $x++) {
2576                      if(ord($frame[$y][$x]) & 0x80) {
2577                          $bitMask[$y][$x] = 0;
2578                      } else {
2579                          $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y);
2580                          $bitMask[$y][$x] = ($maskFunc == 0)?1:0;
2581                      }
2582                      
2583                  }
2584              }
2585              
2586              return $bitMask;
2587          }
2588          
2589          //----------------------------------------------------------------------

2590          public static function serial($bitFrame)
2591          {
2592              $codeArr = array();
2593              
2594              foreach ($bitFrame as $line)
2595                  $codeArr[] = join('', $line);
2596                  
2597              return gzcompress(join("\n", $codeArr), 9);
2598          }
2599          
2600          //----------------------------------------------------------------------

2601          public static function unserial($code)
2602          {
2603              $codeArr = array();
2604              
2605              $codeLines = explode("\n", gzuncompress($code));
2606              foreach ($codeLines as $line)
2607                  $codeArr[] = str_split($line);
2608              
2609              return $codeArr;
2610          }
2611          
2612          //----------------------------------------------------------------------

2613          public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false) 
2614          {
2615              $b = 0;
2616              $bitMask = array();
2617              
2618              $fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat';
2619  
2620              if (QR_CACHEABLE) {
2621                  if (file_exists($fileName)) {
2622                      $bitMask = self::unserial(file_get_contents($fileName));
2623                  } else {
2624                      $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
2625                      if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo))
2626                          mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
2627                      file_put_contents($fileName, self::serial($bitMask));
2628                  }
2629              } else {
2630                  $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
2631              }
2632  
2633              if ($maskGenOnly)
2634                  return;
2635                  
2636              $d = $s;
2637  
2638              for($y=0; $y<$width; $y++) {
2639                  for($x=0; $x<$width; $x++) {
2640                      if($bitMask[$y][$x] == 1) {
2641                          $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]);
2642                      }
2643                      $b += (int)(ord($d[$y][$x]) & 1);
2644                  }
2645              }
2646  
2647              return $b;
2648          }
2649          
2650          //----------------------------------------------------------------------

2651          public function makeMask($width, $frame, $maskNo, $level)
2652          {
2653              $masked = array_fill(0, $width, str_repeat("\0", $width));
2654              $this->makeMaskNo($maskNo, $width, $frame, $masked);
2655              $this->writeFormatInformation($width, $masked, $maskNo, $level);
2656         
2657              return $masked;
2658          }
2659          
2660          //----------------------------------------------------------------------

2661          public function calcN1N3($length)
2662          {
2663              $demerit = 0;
2664  
2665              for($i=0; $i<$length; $i++) {
2666                  
2667                  if($this->runLength[$i] >= 5) {
2668                      $demerit += (N1 + ($this->runLength[$i] - 5));
2669                  }
2670                  if($i & 1) {
2671                      if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) {
2672                          $fact = (int)($this->runLength[$i] / 3);
2673                          if(($this->runLength[$i-2] == $fact) &&
2674                             ($this->runLength[$i-1] == $fact) &&
2675                             ($this->runLength[$i+1] == $fact) &&
2676                             ($this->runLength[$i+2] == $fact)) {
2677                              if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) {
2678                                  $demerit += N3;
2679                              } else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) {
2680                                  $demerit += N3;
2681                              }
2682                          }
2683                      }
2684                  }
2685              }
2686              return $demerit;
2687          }
2688          
2689          //----------------------------------------------------------------------

2690          public function evaluateSymbol($width, $frame)
2691          {
2692              $head = 0;
2693              $demerit = 0;
2694  
2695              for($y=0; $y<$width; $y++) {
2696                  $head = 0;
2697                  $this->runLength[0] = 1;
2698                  
2699                  $frameY = $frame[$y];
2700                  
2701                  if ($y>0)
2702                      $frameYM = $frame[$y-1];
2703                  
2704                  for($x=0; $x<$width; $x++) {
2705                      if(($x > 0) && ($y > 0)) {
2706                          $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
2707                          $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
2708                          
2709                          if(($b22 | ($w22 ^ 1))&1) {                                                                     
2710                              $demerit += N2;
2711                          }
2712                      }
2713                      if(($x == 0) && (ord($frameY[$x]) & 1)) {
2714                          $this->runLength[0] = -1;
2715                          $head = 1;
2716                          $this->runLength[$head] = 1;
2717                      } else if($x > 0) {
2718                          if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
2719                              $head++;
2720                              $this->runLength[$head] = 1;
2721                          } else {
2722                              $this->runLength[$head]++;
2723                          }
2724                      }
2725                  }
2726      
2727                  $demerit += $this->calcN1N3($head+1);
2728              }
2729  
2730              for($x=0; $x<$width; $x++) {
2731                  $head = 0;
2732                  $this->runLength[0] = 1;
2733                  
2734                  for($y=0; $y<$width; $y++) {
2735                      if($y == 0 && (ord($frame[$y][$x]) & 1)) {
2736                          $this->runLength[0] = -1;
2737                          $head = 1;
2738                          $this->runLength[$head] = 1;
2739                      } else if($y > 0) {
2740                          if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
2741                              $head++;
2742                              $this->runLength[$head] = 1;
2743                          } else {
2744                              $this->runLength[$head]++;
2745                          }
2746                      }
2747                  }
2748              
2749                  $demerit += $this->calcN1N3($head+1);
2750              }
2751  
2752              return $demerit;
2753          }
2754          
2755          
2756          //----------------------------------------------------------------------

2757          public function mask($width, $frame, $level)
2758          {
2759              $minDemerit = PHP_INT_MAX;
2760              $bestMaskNum = 0;
2761              $bestMask = array();
2762              
2763              $checked_masks = array(0,1,2,3,4,5,6,7);
2764              
2765              if (QR_FIND_FROM_RANDOM !== false) {
2766              
2767                  $howManuOut = 8-(QR_FIND_FROM_RANDOM % 9);
2768                  for ($i = 0; $i <  $howManuOut; $i++) {
2769                      $remPos = rand (0, count($checked_masks)-1);
2770                      unset($checked_masks[$remPos]);
2771                      $checked_masks = array_values($checked_masks);
2772                  }
2773              
2774              }
2775              
2776              $bestMask = $frame;
2777               
2778              foreach($checked_masks as $i) {
2779                  $mask = array_fill(0, $width, str_repeat("\0", $width));
2780  
2781                  $demerit = 0;
2782                  $blacks = 0;
2783                  $blacks  = $this->makeMaskNo($i, $width, $frame, $mask);
2784                  $blacks += $this->writeFormatInformation($width, $mask, $i, $level);
2785                  $blacks  = (int)(100 * $blacks / ($width * $width));
2786                  $demerit = (int)((int)(abs($blacks - 50) / 5) * N4);
2787                  $demerit += $this->evaluateSymbol($width, $mask);
2788                  
2789                  if($demerit < $minDemerit) {
2790                      $minDemerit = $demerit;
2791                      $bestMask = $mask;
2792                      $bestMaskNum = $i;
2793                  }
2794              }
2795              
2796              return $bestMask;
2797          }
2798          
2799          //----------------------------------------------------------------------

2800      }
2801  
2802  
2803  
2804  
2805  //---- qrencode.php -----------------------------
2806  
2807  
2808  
2809  
2810  /*

2811   * PHP QR Code encoder

2812   *

2813   * Main encoder classes.

2814   *

2815   * Based on libqrencode C library distributed under LGPL 2.1

2816   * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>

2817   *

2818   * PHP QR Code is distributed under LGPL 3

2819   * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>

2820   *

2821   * This library is free software; you can redistribute it and/or

2822   * modify it under the terms of the GNU Lesser General Public

2823   * License as published by the Free Software Foundation; either

2824   * version 3 of the License, or any later version.

2825   *

2826   * This library is distributed in the hope that it will be useful,

2827   * but WITHOUT ANY WARRANTY; without even the implied warranty of

2828   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

2829   * Lesser General Public License for more details.

2830   *

2831   * You should have received a copy of the GNU Lesser General Public

2832   * License along with this library; if not, write to the Free Software

2833   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

2834   */
2835   
2836      class QRrsblock {
2837          public $dataLength;
2838          public $data = array();
2839          public $eccLength;
2840          public $ecc = array();
2841          
2842          public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs)
2843          {
2844              $rs->encode_rs_char($data, $ecc);
2845          
2846              $this->dataLength = $dl;
2847              $this->data = $data;
2848              $this->eccLength = $el;
2849              $this->ecc = $ecc;
2850          }
2851      };
2852      
2853      //##########################################################################

2854  
2855      class QRrawcode {
2856          public $version;
2857          public $datacode = array();
2858          public $ecccode = array();
2859          public $blocks;
2860          public $rsblocks = array(); //of RSblock

2861          public $count;
2862          public $dataLength;
2863          public $eccLength;
2864          public $b1;
2865          
2866          //----------------------------------------------------------------------

2867          public function __construct(QRinput $input)
2868          {
2869              $spec = array(0,0,0,0,0);
2870              
2871              $this->datacode = $input->getByteStream();
2872              if(is_null($this->datacode)) {
2873                  throw new Exception('null imput string');
2874              }
2875  
2876              QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec);
2877  
2878              $this->version = $input->getVersion();
2879              $this->b1 = QRspec::rsBlockNum1($spec);
2880              $this->dataLength = QRspec::rsDataLength($spec);
2881              $this->eccLength = QRspec::rsEccLength($spec);
2882              $this->ecccode = array_fill(0, $this->eccLength, 0);
2883              $this->blocks = QRspec::rsBlockNum($spec);
2884              
2885              $ret = $this->init($spec);
2886              if($ret < 0) {
2887                  throw new Exception('block alloc error');
2888                  return null;
2889              }
2890  
2891              $this->count = 0;
2892          }
2893          
2894          //----------------------------------------------------------------------

2895          public function init(array $spec)
2896          {
2897              $dl = QRspec::rsDataCodes1($spec);
2898              $el = QRspec::rsEccCodes1($spec);
2899              $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
2900              
2901  
2902              $blockNo = 0;
2903              $dataPos = 0;
2904              $eccPos = 0;
2905              for($i=0; $i<QRspec::rsBlockNum1($spec); $i++) {
2906                  $ecc = array_slice($this->ecccode,$eccPos);
2907                  $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el,  $ecc, $rs);
2908                  $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
2909                  
2910                  $dataPos += $dl;
2911                  $eccPos += $el;
2912                  $blockNo++;
2913              }
2914  
2915              if(QRspec::rsBlockNum2($spec) == 0)
2916                  return 0;
2917  
2918              $dl = QRspec::rsDataCodes2($spec);
2919              $el = QRspec::rsEccCodes2($spec);
2920              $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
2921              
2922              if($rs == NULL) return -1;
2923              
2924              for($i=0; $i<QRspec::rsBlockNum2($spec); $i++) {
2925                  $ecc = array_slice($this->ecccode,$eccPos);
2926                  $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
2927                  $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
2928                  
2929                  $dataPos += $dl;
2930                  $eccPos += $el;
2931                  $blockNo++;
2932              }
2933  
2934              return 0;
2935          }
2936          
2937          //----------------------------------------------------------------------

2938          public function getCode()
2939          {
2940              $ret;
2941  
2942              if($this->count < $this->dataLength) {
2943                  $row = $this->count % $this->blocks;
2944                  $col = $this->count / $this->blocks;
2945                  if($col >= $this->rsblocks[0]->dataLength) {
2946                      $row += $this->b1;
2947                  }
2948                  $ret = $this->rsblocks[$row]->data[$col];
2949              } else if($this->count < $this->dataLength + $this->eccLength) {
2950                  $row = ($this->count - $this->dataLength) % $this->blocks;
2951                  $col = ($this->count - $this->dataLength) / $this->blocks;
2952                  $ret = $this->rsblocks[$row]->ecc[$col];
2953              } else {
2954                  return 0;
2955              }
2956              $this->count++;
2957              
2958              return $ret;
2959          }
2960      }
2961  
2962      //##########################################################################

2963      
2964      class QRcode {
2965      
2966          public $version;
2967          public $width;
2968          public $data; 
2969          
2970          //----------------------------------------------------------------------

2971          public function encodeMask(QRinput $input, $mask)
2972          {
2973              if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) {
2974                  throw new Exception('wrong version');
2975              }
2976              if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) {
2977                  throw new Exception('wrong level');
2978              }
2979  
2980              $raw = new QRrawcode($input);
2981              
2982              QRtools::markTime('after_raw');
2983              
2984              $version = $raw->version;
2985              $width = QRspec::getWidth($version);
2986              $frame = QRspec::newFrame($version);
2987              
2988              $filler = new FrameFiller($width, $frame);
2989              if(is_null($filler)) {
2990                  return NULL;
2991              }
2992  
2993              // inteleaved data and ecc codes

2994              for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) {
2995                  $code = $raw->getCode();
2996                  $bit = 0x80;
2997                  for($j=0; $j<8; $j++) {
2998                      $addr = $filler->next();
2999                      $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
3000                      $bit = $bit >> 1;
3001                  }
3002              }
3003              
3004              QRtools::markTime('after_filler');
3005              
3006              unset($raw);
3007              
3008              // remainder bits

3009              $j = QRspec::getRemainder($version);
3010              for($i=0; $i<$j; $i++) {
3011                  $addr = $filler->next();
3012                  $filler->setFrameAt($addr, 0x02);
3013              }
3014              
3015              $frame = $filler->frame;
3016              unset($filler);
3017              
3018              
3019              // masking

3020              $maskObj = new QRmask();
3021              if($mask < 0) {
3022              
3023                  if (QR_FIND_BEST_MASK) {
3024                      $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel());
3025                  } else {
3026                      $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel());
3027                  }
3028              } else {
3029                  $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel());
3030              }
3031              
3032              if($masked == NULL) {
3033                  return NULL;
3034              }
3035              
3036              QRtools::markTime('after_mask');
3037              
3038              $this->version = $version;
3039              $this->width = $width;
3040              $this->data = $masked;
3041              
3042              return $this;
3043          }
3044      
3045          //----------------------------------------------------------------------

3046          public function encodeInput(QRinput $input)
3047          {
3048              return $this->encodeMask($input, -1);
3049          }
3050          
3051          //----------------------------------------------------------------------

3052          public function encodeString8bit($string, $version, $level)
3053          {
3054              if(string == NULL) {
3055                  throw new Exception('empty string!');
3056                  return NULL;
3057              }
3058  
3059              $input = new QRinput($version, $level);
3060              if($input == NULL) return NULL;
3061  
3062              $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string));
3063              if($ret < 0) {
3064                  unset($input);
3065                  return NULL;
3066              }
3067              return $this->encodeInput($input);
3068          }
3069  
3070          //----------------------------------------------------------------------

3071          public function encodeString($string, $version, $level, $hint, $casesensitive)
3072          {
3073  
3074              if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) {
3075                  throw new Exception('bad hint');
3076                  return NULL;
3077              }
3078  
3079              $input = new QRinput($version, $level);
3080              if($input == NULL) return NULL;
3081  
3082              $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive);
3083              if($ret < 0) {
3084                  return NULL;
3085              }
3086  
3087              return $this->encodeInput($input);
3088          }
3089          
3090          //----------------------------------------------------------------------

3091          public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false) 
3092          {
3093              $enc = QRencode::factory($level, $size, $margin);
3094              return $enc->encodePNG($text, $outfile, $saveandprint=false);
3095          }
3096  
3097          //----------------------------------------------------------------------

3098          public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) 
3099          {
3100              $enc = QRencode::factory($level, $size, $margin);
3101              return $enc->encode($text, $outfile);
3102          }
3103  
3104          //----------------------------------------------------------------------

3105          public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) 
3106          {
3107              $enc = QRencode::factory($level, $size, $margin);
3108              return $enc->encodeRAW($text, $outfile);
3109          }
3110      }
3111      
3112      //##########################################################################

3113      
3114      class FrameFiller {
3115      
3116          public $width;
3117          public $frame;
3118          public $x;
3119          public $y;
3120          public $dir;
3121          public $bit;
3122          
3123          //----------------------------------------------------------------------

3124          public function __construct($width, &$frame)
3125          {
3126              $this->width = $width;
3127              $this->frame = $frame;
3128              $this->x = $width - 1;
3129              $this->y = $width - 1;
3130              $this->dir = -1;
3131              $this->bit = -1;
3132          }
3133          
3134          //----------------------------------------------------------------------

3135          public function setFrameAt($at, $val)
3136          {
3137              $this->frame[$at['y']][$at['x']] = chr($val);
3138          }
3139          
3140          //----------------------------------------------------------------------

3141          public function getFrameAt($at)
3142          {
3143              return ord($this->frame[$at['y']][$at['x']]);
3144          }
3145          
3146          //----------------------------------------------------------------------

3147          public function next()
3148          {
3149              do {
3150              
3151                  if($this->bit == -1) {
3152                      $this->bit = 0;
3153                      return array('x'=>$this->x, 'y'=>$this->y);
3154                  }
3155  
3156                  $x = $this->x;
3157                  $y = $this->y;
3158                  $w = $this->width;
3159  
3160                  if($this->bit == 0) {
3161                      $x--;
3162                      $this->bit++;
3163                  } else {
3164                      $x++;
3165                      $y += $this->dir;
3166                      $this->bit--;
3167                  }
3168  
3169                  if($this->dir < 0) {
3170                      if($y < 0) {
3171                          $y = 0;
3172                          $x -= 2;
3173                          $this->dir = 1;
3174                          if($x == 6) {
3175                              $x--;
3176                              $y = 9;
3177                          }
3178                      }
3179                  } else {
3180                      if($y == $w) {
3181                          $y = $w - 1;
3182                          $x -= 2;
3183                          $this->dir = -1;
3184                          if($x == 6) {
3185                              $x--;
3186                              $y -= 8;
3187                          }
3188                      }
3189                  }
3190                  if($x < 0 || $y < 0) return null;
3191  
3192                  $this->x = $x;
3193                  $this->y = $y;
3194  
3195              } while(ord($this->frame[$y][$x]) & 0x80);
3196                          
3197              return array('x'=>$x, 'y'=>$y);
3198          }
3199          
3200      } ;
3201      
3202      //##########################################################################    

3203      
3204      class QRencode {
3205      
3206          public $casesensitive = true;
3207          public $eightbit = false;
3208          
3209          public $version = 0;
3210          public $size = 3;
3211          public $margin = 4;
3212          
3213          public $structured = 0; // not supported yet

3214          
3215          public $level = QR_ECLEVEL_L;
3216          public $hint = QR_MODE_8;
3217          
3218          //----------------------------------------------------------------------

3219          public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4)
3220          {
3221              $enc = new QRencode();
3222              $enc->size = $size;
3223              $enc->margin = $margin;
3224              
3225              switch ($level.'') {
3226                  case '0':
3227                  case '1':
3228                  case '2':
3229                  case '3':
3230                          $enc->level = $level;
3231                      break;
3232                  case 'l':
3233                  case 'L':
3234                          $enc->level = QR_ECLEVEL_L;
3235                      break;
3236                  case 'm':
3237                  case 'M':
3238                          $enc->level = QR_ECLEVEL_M;
3239                      break;
3240                  case 'q':
3241                  case 'Q':
3242                          $enc->level = QR_ECLEVEL_Q;
3243                      break;
3244                  case 'h':
3245                  case 'H':
3246                          $enc->level = QR_ECLEVEL_H;
3247                      break;
3248              }
3249              
3250              return $enc;
3251          }
3252          
3253          //----------------------------------------------------------------------

3254          public function encodeRAW($intext, $outfile = false) 
3255          {
3256              $code = new QRcode();
3257  
3258              if($this->eightbit) {
3259                  $code->encodeString8bit($intext, $this->version, $this->level);
3260              } else {
3261                  $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
3262              }
3263              
3264              return $code->data;
3265          }
3266  
3267          //----------------------------------------------------------------------

3268          public function encode($intext, $outfile = false) 
3269          {
3270              $code = new QRcode();
3271  
3272              if($this->eightbit) {
3273                  $code->encodeString8bit($intext, $this->version, $this->level);
3274              } else {
3275                  $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
3276              }
3277              
3278              QRtools::markTime('after_encode');
3279              
3280              if ($outfile!== false) {
3281                  file_put_contents($outfile, join("\n", QRtools::binarize($code->data)));
3282              } else {
3283                  return QRtools::binarize($code->data);
3284              }
3285          }
3286          
3287          //----------------------------------------------------------------------

3288          public function encodePNG($intext, $outfile = false,$saveandprint=false) 
3289          {
3290              try {
3291              
3292                  ob_start();
3293                  $tab = $this->encode($intext);
3294                  $err = ob_get_contents();
3295                  ob_end_clean();
3296                  
3297                  if ($err != '')
3298                      QRtools::log($outfile, $err);
3299                  
3300                  $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin));
3301                  
3302                  QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint);
3303              
3304              } catch (Exception $e) {
3305              
3306                  QRtools::log($outfile, $e->getMessage());
3307              
3308              }
3309          }
3310      }
3311  
3312  


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1