Add Encoder/Decoder for Data Matrix Barcode.
QR-CODE
Data Matrix Barcode
@@ -0,0 +1,21 @@ | ||
1 | +package jp.sourceforge.reedsolomon; | |
2 | + | |
3 | +/** | |
4 | + * Galois Field GF(2^8) for Data Matrix Barcode | |
5 | + * | |
6 | + * @author Masayuki Miyazaki | |
7 | + * http://sourceforge.jp/projects/reedsolomon/ | |
8 | + */ | |
9 | +public final class GaloisDM | |
10 | + extends Galois { | |
11 | + public static final int POLYNOMIAL = 0x2d; // x^8 + x^5 + x^3 + x^2 + 1 | |
12 | + private static final Galois instance = new GaloisDM(); | |
13 | + | |
14 | + private GaloisDM() { | |
15 | + super(POLYNOMIAL, 1); | |
16 | + } | |
17 | + | |
18 | + public static Galois getInstance() { | |
19 | + return instance; | |
20 | + } | |
21 | +} |
@@ -0,0 +1,21 @@ | ||
1 | +package jp.sourceforge.reedsolomon; | |
2 | + | |
3 | +/** | |
4 | + * Galois Field GF(2^8) for QR-CODE | |
5 | + * | |
6 | + * @author Masayuki Miyazaki | |
7 | + * http://sourceforge.jp/projects/reedsolomon/ | |
8 | + */ | |
9 | +public final class GaloisQR | |
10 | + extends Galois { | |
11 | + public static final int POLYNOMIAL = 0x1d; // x^8 + x^4 + x^3 + x^2 + 1 | |
12 | + private static final Galois instance = new GaloisQR(); | |
13 | + | |
14 | + private GaloisQR() { | |
15 | + super(POLYNOMIAL, 0); | |
16 | + } | |
17 | + | |
18 | + public static Galois getInstance() { | |
19 | + return instance; | |
20 | + } | |
21 | +} |
@@ -7,28 +7,26 @@ | ||
7 | 7 | * http://sourceforge.jp/projects/reedsolomon/ |
8 | 8 | */ |
9 | 9 | public class RsEncode { |
10 | - private static final Galois galois = Galois.getInstance(); | |
10 | + private final Galois galois; | |
11 | 11 | private int npar; |
12 | 12 | private int[] encodeGx; |
13 | 13 | |
14 | - public RsEncode(int npar) { | |
14 | + public RsEncode(Galois galois, int npar) { | |
15 | + this.galois = galois; | |
16 | + this.npar = npar; | |
15 | 17 | if(npar <= 0 || npar >= 128) { |
16 | 18 | throw new IllegalArgumentException("bad npar"); |
17 | 19 | } |
18 | - this.npar = npar; | |
19 | - makeEncodeGx(); | |
20 | + encodeGx = galois.makeEncodeGx(npar); | |
20 | 21 | } |
21 | 22 | |
22 | - private void makeEncodeGx() { | |
23 | - encodeGx = new int[npar]; | |
24 | - encodeGx[npar - 1] = 1; | |
25 | - for(int kou = 0; kou < npar; kou++) { | |
26 | - int ex = galois.toExp(kou); | |
27 | - for(int i = 0; i < npar - 1; i++) { | |
28 | - encodeGx[i] = galois.mul(encodeGx[i], ex) ^ encodeGx[i + 1]; | |
29 | - } | |
30 | - encodeGx[npar - 1] = galois.mul(encodeGx[npar - 1], ex); | |
23 | + public RsEncode(int npar) { | |
24 | + this.galois = GaloisQR.getInstance(); | |
25 | + this.npar = npar; | |
26 | + if(npar <= 0 || npar >= 128) { | |
27 | + throw new IllegalArgumentException("bad npar"); | |
31 | 28 | } |
29 | + encodeGx = galois.makeEncodeGx(npar); | |
32 | 30 | } |
33 | 31 | |
34 | 32 | public int encode(int[] data, int length, int[] parity, int parityStartPos) { |
@@ -8,14 +8,23 @@ | ||
8 | 8 | */ |
9 | 9 | public class RsDecode { |
10 | 10 | public static final int RS_CORRECT_ERROR = -2; |
11 | - private static final Galois galois = Galois.getInstance(); | |
11 | + private Galois galois = GaloisQR.getInstance(); | |
12 | 12 | private int npar; |
13 | 13 | |
14 | + public RsDecode(Galois galois, int npar) { | |
15 | + this.galois = galois; | |
16 | + this.npar = npar; | |
17 | + if(npar <= 0 || npar >= 128) { | |
18 | + throw new IllegalArgumentException("bad npar"); | |
19 | + } | |
20 | + } | |
21 | + | |
14 | 22 | public RsDecode(int npar) { |
23 | + this.galois = GaloisQR.getInstance(); | |
24 | + this.npar = npar; | |
15 | 25 | if(npar <= 0 || npar >= 128) { |
16 | 26 | throw new IllegalArgumentException("bad npar"); |
17 | 27 | } |
18 | - this.npar = npar; | |
19 | 28 | } |
20 | 29 | |
21 | 30 | /** |
@@ -99,8 +108,7 @@ | ||
99 | 108 | return pos; |
100 | 109 | } |
101 | 110 | int posIdx = jisu - 1; |
102 | - for(int i = 0; i < length; i++) { | |
103 | - final int z = 255 - i; | |
111 | + for(int i = 0, z = 255; i < length; i++, z--) { | |
104 | 112 | int wz = z; |
105 | 113 | int wk = 1; |
106 | 114 | for(int j = 1; j <= jisu; j++) { |
@@ -137,24 +145,10 @@ | ||
137 | 145 | * @param omega int[] |
138 | 146 | */ |
139 | 147 | private void doForney(int[] data, int length, int[] pos, int[] sigma, int[] omega) { |
140 | - final int jisu = sigma.length - 1; | |
141 | 148 | for(int ps: pos) { |
142 | 149 | final int zlog = 255 - galois.toLog(ps); |
143 | - int wz = zlog; | |
144 | - int ov = omega[0]; | |
145 | - for(int i = 1; i < jisu; i++) { | |
146 | - ov ^= galois.mulExp(omega[i], wz); | |
147 | - wz = (wz + zlog) % 255; | |
148 | - } | |
149 | - | |
150 | - final int zlog2 = (zlog * 2) % 255; | |
151 | - wz = zlog2; | |
152 | - int dv = sigma[1]; | |
153 | - for(int i = 3; i <= jisu; i += 2) { | |
154 | - dv ^= galois.mulExp(sigma[i], wz); | |
155 | - wz = (wz + zlog2) % 255; | |
156 | - } | |
157 | - | |
150 | + int ov = galois.calcOmegaValue(omega, zlog); | |
151 | + int dv = galois.calcSigmaDashValue(sigma, zlog); | |
158 | 152 | data[galois.toPos(length, ps)] ^= galois.mul(ps, galois.div(ov, dv)); |
159 | 153 | } |
160 | 154 | } |
@@ -214,20 +208,43 @@ | ||
214 | 208 | |
215 | 209 | /* |
216 | 210 | public static void main(String[] args) { |
217 | - int[] data = new int[] { | |
218 | - 32, 65, 205, 69, 41, 220, 46, 128, 236, | |
219 | - 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61 | |
220 | - }; | |
211 | + final int[] ref = new int[] {32, 65, 205, 69, 41, 220, 46, 128, 236}; | |
212 | + | |
213 | + // Encoding QR-CODE | |
214 | + int[] qrData = new int[ref.length + 17]; | |
215 | + System.arraycopy(ref, 0, qrData, 0, ref.length); | |
216 | + RsEncode enc = new RsEncode(17); | |
217 | + enc.encode(qrData); | |
218 | + System.out.println("qrData=" + java.util.Arrays.toString(qrData)); | |
219 | + // parity = 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61 | |
220 | + | |
221 | + // force add errors | |
222 | + qrData[0] ^= 0x55; | |
223 | + qrData[1] ^= 0xaa; | |
224 | + | |
225 | + // Decoding QR-CODE | |
221 | 226 | RsDecode dec = new RsDecode(17); |
222 | - int r = dec.decode(data); | |
227 | + int r = dec.decode(qrData); | |
223 | 228 | System.out.println("r=" + r); |
224 | - for(int i = 0; i < 8; i++) { | |
225 | - data[i] ^= (int) (Math.random() * 256); | |
226 | - } | |
227 | - System.out.println(java.util.Arrays.toString(data)); | |
228 | - r = dec.decode(data); | |
229 | + System.out.println("qrData=" + java.util.Arrays.toString(qrData)); | |
230 | + | |
231 | + // Encoding Data Matrix Barcode | |
232 | + int[] dmData = new int[ref.length + 17]; | |
233 | + System.arraycopy(ref, 0, dmData, 0, ref.length); | |
234 | + RsEncode encDM = new RsEncode(GaloisDM.getInstance(), 17); | |
235 | + encDM.encode(dmData); | |
236 | + System.out.println("dmData=" + java.util.Arrays.toString(dmData)); | |
237 | + // parity = 41, 41, 15, 250, 121, 58, 190, 205, 164, 103, 63, 149, 42, 247, 1, 214, 148 | |
238 | + | |
239 | + // force add errors | |
240 | + dmData[0] ^= 0x55; | |
241 | + dmData[1] ^= 0xaa; | |
242 | + | |
243 | + // Decoding Data Matrix Barcode | |
244 | + RsDecode decDM = new RsDecode(GaloisDM.getInstance(), 17); | |
245 | + r = decDM.decode(dmData); | |
229 | 246 | System.out.println("r=" + r); |
230 | - System.out.println(java.util.Arrays.toString(data)); | |
247 | + System.out.println("dmData=" + java.util.Arrays.toString(dmData)); | |
231 | 248 | } |
232 | 249 | */ |
233 | 250 | } |
@@ -6,20 +6,18 @@ | ||
6 | 6 | * @author Masayuki Miyazaki |
7 | 7 | * http://sourceforge.jp/projects/reedsolomon/ |
8 | 8 | */ |
9 | -public final class Galois { | |
10 | - public static final int POLYNOMIAL = 0x1d; | |
11 | - private static final Galois instance = new Galois(); | |
9 | +public class Galois { | |
10 | + private final int polynomial; | |
11 | + private final int symStart; | |
12 | 12 | private int[] expTbl = new int[255 * 2]; |
13 | 13 | private int[] logTbl = new int[255 + 1]; |
14 | 14 | |
15 | - private Galois() { | |
15 | + protected Galois(int polynomial, int symStart) { | |
16 | + this.polynomial = polynomial; | |
17 | + this.symStart = symStart; | |
16 | 18 | initGaloisTable(); |
17 | 19 | } |
18 | 20 | |
19 | - public static Galois getInstance() { | |
20 | - return instance; | |
21 | - } | |
22 | - | |
23 | 21 | private void initGaloisTable() { |
24 | 22 | int d = 1; |
25 | 23 | for(int i = 0; i < 255; i++) { |
@@ -27,7 +25,7 @@ | ||
27 | 25 | logTbl[d] = i; |
28 | 26 | d <<= 1; |
29 | 27 | if((d & 0x100) != 0) { |
30 | - d = (d ^ POLYNOMIAL) & 0xff; | |
28 | + d = (d ^ polynomial) & 0xff; | |
31 | 29 | } |
32 | 30 | } |
33 | 31 | } |
@@ -83,11 +81,11 @@ | ||
83 | 81 | |
84 | 82 | public boolean calcSyndrome(int[] data, int length, int[] syn) { |
85 | 83 | int hasErr = 0; |
86 | - for(int i = 0; i < syn.length; i++) { | |
84 | + for(int i = 0, s = symStart; i < syn.length; i++, s++) { | |
87 | 85 | int wk = 0; |
88 | 86 | for(int idx = 0; idx < length; idx++) { |
89 | 87 | if(wk != 0) { |
90 | - wk = expTbl[logTbl[wk] + i]; | |
88 | + wk = expTbl[logTbl[wk] + s]; | |
91 | 89 | } |
92 | 90 | wk ^= data[idx]; |
93 | 91 | } |
@@ -96,4 +94,42 @@ | ||
96 | 94 | } |
97 | 95 | return hasErr == 0; |
98 | 96 | } |
97 | + | |
98 | + public int[] makeEncodeGx(int npar) { | |
99 | + int[] encodeGx = new int[npar]; | |
100 | + encodeGx[npar - 1] = 1; | |
101 | + for(int i = 0, kou = symStart; i < npar; i++, kou++) { | |
102 | + int ex = toExp(kou); | |
103 | + for(int j = 0; j < npar - 1; j++) { | |
104 | + encodeGx[j] = mul(encodeGx[j], ex) ^ encodeGx[j + 1]; | |
105 | + } | |
106 | + encodeGx[npar - 1] = mul(encodeGx[npar - 1], ex); | |
107 | + } | |
108 | + return encodeGx; | |
109 | + } | |
110 | + | |
111 | + public int calcOmegaValue(int[] omega, int zlog) { | |
112 | + int wz = zlog; | |
113 | + int ov = omega[0]; | |
114 | + for(int i = 1; i < omega.length; i++) { | |
115 | + ov ^= mulExp(omega[i], wz); | |
116 | + wz = (wz + zlog) % 255; | |
117 | + } | |
118 | + if(symStart != 0) { | |
119 | + ov = mulExp(ov, (zlog * symStart) % 255); | |
120 | + } | |
121 | + return ov; | |
122 | + } | |
123 | + | |
124 | + public int calcSigmaDashValue(int[] sigma, int zlog) { | |
125 | + final int jisu = sigma.length - 1; | |
126 | + final int zlog2 = (zlog * 2) % 255; | |
127 | + int wz = zlog2; | |
128 | + int dv = sigma[1]; | |
129 | + for(int i = 3; i <= jisu; i += 2) { | |
130 | + dv ^= mulExp(sigma[i], wz); | |
131 | + wz = (wz + zlog2) % 255; | |
132 | + } | |
133 | + return dv; | |
134 | + } | |
99 | 135 | } |