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