survey_seahorse

Software Engineering Project - Fall 2018
Log | Files | Refs | README

qrrscode.php (8485B)


      1 <?php
      2 /*
      3  * PHP QR Code encoder
      4  *
      5  * Reed-Solomon error correction support
      6  * 
      7  * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
      8  * (libfec is released under the GNU Lesser General Public License.)
      9  *
     10  * Based on libqrencode C library distributed under LGPL 2.1
     11  * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
     12  *
     13  * PHP QR Code is distributed under LGPL 3
     14  * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
     15  *
     16  * This library is free software; you can redistribute it and/or
     17  * modify it under the terms of the GNU Lesser General Public
     18  * License as published by the Free Software Foundation; either
     19  * version 3 of the License, or any later version.
     20  *
     21  * This library is distributed in the hope that it will be useful,
     22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
     24  * Lesser General Public License for more details.
     25  *
     26  * You should have received a copy of the GNU Lesser General Public
     27  * License along with this library; if not, write to the Free Software
     28  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
     29  */
     30  
     31     class QRrsItem {
     32     
     33         public $mm;                  // Bits per symbol 
     34         public $nn;                  // Symbols per block (= (1<<mm)-1) 
     35         public $alpha_to = array();  // log lookup table 
     36         public $index_of = array();  // Antilog lookup table 
     37         public $genpoly = array();   // Generator polynomial 
     38         public $nroots;              // Number of generator roots = number of parity symbols 
     39         public $fcr;                 // First consecutive root, index form 
     40         public $prim;                // Primitive element, index form 
     41         public $iprim;               // prim-th root of 1, index form 
     42         public $pad;                 // Padding bytes in shortened block 
     43         public $gfpoly;
     44     
     45         //----------------------------------------------------------------------
     46         public function modnn($x)
     47         {
     48             while ($x >= $this->nn) {
     49                 $x -= $this->nn;
     50                 $x = ($x >> $this->mm) + ($x & $this->nn);
     51             }
     52             
     53             return $x;
     54         }
     55         
     56         //----------------------------------------------------------------------
     57         public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
     58         {
     59             // Common code for intializing a Reed-Solomon control block (char or int symbols)
     60             // Copyright 2004 Phil Karn, KA9Q
     61             // May be used under the terms of the GNU Lesser General Public License (LGPL)
     62 
     63             $rs = null;
     64             
     65             // Check parameter ranges
     66             if($symsize < 0 || $symsize > 8)                     return $rs;
     67             if($fcr < 0 || $fcr >= (1<<$symsize))                return $rs;
     68             if($prim <= 0 || $prim >= (1<<$symsize))             return $rs;
     69             if($nroots < 0 || $nroots >= (1<<$symsize))          return $rs; // Can't have more roots than symbol values!
     70             if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding
     71 
     72             $rs = new QRrsItem();
     73             $rs->mm = $symsize;
     74             $rs->nn = (1<<$symsize)-1;
     75             $rs->pad = $pad;
     76 
     77             $rs->alpha_to = array_fill(0, $rs->nn+1, 0);
     78             $rs->index_of = array_fill(0, $rs->nn+1, 0);
     79           
     80             // PHP style macro replacement ;)
     81             $NN =& $rs->nn;
     82             $A0 =& $NN;
     83             
     84             // Generate Galois field lookup tables
     85             $rs->index_of[0] = $A0; // log(zero) = -inf
     86             $rs->alpha_to[$A0] = 0; // alpha**-inf = 0
     87             $sr = 1;
     88           
     89             for($i=0; $i<$rs->nn; $i++) {
     90                 $rs->index_of[$sr] = $i;
     91                 $rs->alpha_to[$i] = $sr;
     92                 $sr <<= 1;
     93                 if($sr & (1<<$symsize)) {
     94                     $sr ^= $gfpoly;
     95                 }
     96                 $sr &= $rs->nn;
     97             }
     98             
     99             if($sr != 1){
    100                 // field generator polynomial is not primitive!
    101                 $rs = NULL;
    102                 return $rs;
    103             }
    104 
    105             /* Form RS code generator polynomial from its roots */
    106             $rs->genpoly = array_fill(0, $nroots+1, 0);
    107         
    108             $rs->fcr = $fcr;
    109             $rs->prim = $prim;
    110             $rs->nroots = $nroots;
    111             $rs->gfpoly = $gfpoly;
    112 
    113             /* Find prim-th root of 1, used in decoding */
    114             for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)
    115             ; // intentional empty-body loop!
    116             
    117             $rs->iprim = (int)($iprim / $prim);
    118             $rs->genpoly[0] = 1;
    119             
    120             for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
    121                 $rs->genpoly[$i+1] = 1;
    122 
    123                 // Multiply rs->genpoly[] by  @**(root + x)
    124                 for ($j = $i; $j > 0; $j--) {
    125                     if ($rs->genpoly[$j] != 0) {
    126                         $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];
    127                     } else {
    128                         $rs->genpoly[$j] = $rs->genpoly[$j-1];
    129                     }
    130                 }
    131                 // rs->genpoly[0] can never be zero
    132                 $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
    133             }
    134             
    135             // convert rs->genpoly[] to index form for quicker encoding
    136             for ($i = 0; $i <= $nroots; $i++)
    137                 $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
    138 
    139             return $rs;
    140         }
    141         
    142         //----------------------------------------------------------------------
    143         public function encode_rs_char($data, &$parity)
    144         {
    145             $MM       =& $this->mm;
    146             $NN       =& $this->nn;
    147             $ALPHA_TO =& $this->alpha_to;
    148             $INDEX_OF =& $this->index_of;
    149             $GENPOLY  =& $this->genpoly;
    150             $NROOTS   =& $this->nroots;
    151             $FCR      =& $this->fcr;
    152             $PRIM     =& $this->prim;
    153             $IPRIM    =& $this->iprim;
    154             $PAD      =& $this->pad;
    155             $A0       =& $NN;
    156 
    157             $parity = array_fill(0, $NROOTS, 0);
    158 
    159             for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) {
    160                 
    161                 $feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
    162                 if($feedback != $A0) {      
    163                     // feedback term is non-zero
    164             
    165                     // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
    166                     // always be for the polynomials constructed by init_rs()
    167                     $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);
    168             
    169                     for($j=1;$j<$NROOTS;$j++) {
    170                         $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])];
    171                     }
    172                 }
    173                 
    174                 // Shift 
    175                 array_shift($parity);
    176                 if($feedback != $A0) {
    177                     array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);
    178                 } else {
    179                     array_push($parity, 0);
    180                 }
    181             }
    182         }
    183     }
    184     
    185     //##########################################################################
    186     
    187     class QRrs {
    188     
    189         public static $items = array();
    190         
    191         //----------------------------------------------------------------------
    192         public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
    193         {
    194             foreach(self::$items as $rs) {
    195                 if($rs->pad != $pad)       continue;
    196                 if($rs->nroots != $nroots) continue;
    197                 if($rs->mm != $symsize)    continue;
    198                 if($rs->gfpoly != $gfpoly) continue;
    199                 if($rs->fcr != $fcr)       continue;
    200                 if($rs->prim != $prim)     continue;
    201 
    202                 return $rs;
    203             }
    204 
    205             $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
    206             array_unshift(self::$items, $rs);
    207 
    208             return $rs;
    209         }
    210     }