1<?php 2/** 3 * QRrsItem.php 4 * 5 * Created by arielferrandini 6 */ 7 8namespace PHPQRCode; 9 10class QRrsItem { 11 12 public $mm; // Bits per symbol 13 public $nn; // Symbols per block (= (1<<mm)-1) 14 public $alpha_to = array(); // log lookup table 15 public $index_of = array(); // Antilog lookup table 16 public $genpoly = array(); // Generator polynomial 17 public $nroots; // Number of generator roots = number of parity symbols 18 public $fcr; // First consecutive root, index form 19 public $prim; // Primitive element, index form 20 public $iprim; // prim-th root of 1, index form 21 public $pad; // Padding bytes in shortened block 22 public $gfpoly; 23 24 //---------------------------------------------------------------------- 25 public function modnn($x) 26 { 27 while ($x >= $this->nn) { 28 $x -= $this->nn; 29 $x = ($x >> $this->mm) + ($x & $this->nn); 30 } 31 32 return $x; 33 } 34 35 //---------------------------------------------------------------------- 36 public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) 37 { 38 // Common code for intializing a Reed-Solomon control block (char or int symbols) 39 // Copyright 2004 Phil Karn, KA9Q 40 // May be used under the terms of the GNU Lesser General Public License (LGPL) 41 42 $rs = null; 43 44 // Check parameter ranges 45 if($symsize < 0 || $symsize > 8) return $rs; 46 if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs; 47 if($prim <= 0 || $prim >= (1<<$symsize)) return $rs; 48 if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values! 49 if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding 50 51 $rs = new QRrsItem(); 52 $rs->mm = $symsize; 53 $rs->nn = (1<<$symsize)-1; 54 $rs->pad = $pad; 55 56 $rs->alpha_to = array_fill(0, $rs->nn+1, 0); 57 $rs->index_of = array_fill(0, $rs->nn+1, 0); 58 59 // PHP style macro replacement ;) 60 $NN =& $rs->nn; 61 $A0 =& $NN; 62 63 // Generate Galois field lookup tables 64 $rs->index_of[0] = $A0; // log(zero) = -inf 65 $rs->alpha_to[$A0] = 0; // alpha**-inf = 0 66 $sr = 1; 67 68 for($i=0; $i<$rs->nn; $i++) { 69 $rs->index_of[$sr] = $i; 70 $rs->alpha_to[$i] = $sr; 71 $sr <<= 1; 72 if($sr & (1<<$symsize)) { 73 $sr ^= $gfpoly; 74 } 75 $sr &= $rs->nn; 76 } 77 78 if($sr != 1){ 79 // field generator polynomial is not primitive! 80 $rs = NULL; 81 return $rs; 82 } 83 84 /* Form RS code generator polynomial from its roots */ 85 $rs->genpoly = array_fill(0, $nroots+1, 0); 86 87 $rs->fcr = $fcr; 88 $rs->prim = $prim; 89 $rs->nroots = $nroots; 90 $rs->gfpoly = $gfpoly; 91 92 /* Find prim-th root of 1, used in decoding */ 93 for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn) 94 ; // intentional empty-body loop! 95 96 $rs->iprim = (int)($iprim / $prim); 97 $rs->genpoly[0] = 1; 98 99 for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) { 100 $rs->genpoly[$i+1] = 1; 101 102 // Multiply rs->genpoly[] by @**(root + x) 103 for ($j = $i; $j > 0; $j--) { 104 if ($rs->genpoly[$j] != 0) { 105 $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)]; 106 } else { 107 $rs->genpoly[$j] = $rs->genpoly[$j-1]; 108 } 109 } 110 // rs->genpoly[0] can never be zero 111 $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)]; 112 } 113 114 // convert rs->genpoly[] to index form for quicker encoding 115 for ($i = 0; $i <= $nroots; $i++) 116 $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]]; 117 118 return $rs; 119 } 120 121 //---------------------------------------------------------------------- 122 public function encode_rs_char($data, &$parity) 123 { 124 $MM =& $this->mm; 125 $NN =& $this->nn; 126 $ALPHA_TO =& $this->alpha_to; 127 $INDEX_OF =& $this->index_of; 128 $GENPOLY =& $this->genpoly; 129 $NROOTS =& $this->nroots; 130 $FCR =& $this->fcr; 131 $PRIM =& $this->prim; 132 $IPRIM =& $this->iprim; 133 $PAD =& $this->pad; 134 $A0 =& $NN; 135 136 $parity = array_fill(0, $NROOTS, 0); 137 138 for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) { 139 140 $feedback = $INDEX_OF[$data[$i] ^ $parity[0]]; 141 if($feedback != $A0) { 142 // feedback term is non-zero 143 144 // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must 145 // always be for the polynomials constructed by init_rs() 146 $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback); 147 148 for($j=1;$j<$NROOTS;$j++) { 149 $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])]; 150 } 151 } 152 153 // Shift 154 array_shift($parity); 155 if($feedback != $A0) { 156 array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]); 157 } else { 158 array_push($parity, 0); 159 } 160 } 161 } 162}