1d5d37874eda41156e824bc17a7228967bd616fc
[zxing.git] / core / src / com / google / zxing / common / reedsolomon / ReedSolomonEncoder.java
1 /*
2  * Copyright 2008 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.common.reedsolomon;
18
19 import java.util.Vector;
20
21 /**
22  * <p>Implements Reed-Solomon enbcoding, as the name implies.</p>
23  *
24  * @author srowen@google.com (Sean Owen)
25  * @author William Rucklidge
26  */
27 public final class ReedSolomonEncoder {
28
29   private final GF256 field;
30   private final Vector cachedGenerators;
31
32   public ReedSolomonEncoder(GF256 field) {
33     if (!GF256.QR_CODE_FIELD.equals(field)) {
34       throw new IllegalArgumentException("Only QR Code is supported at this time");
35     }
36     this.field = field;
37     this.cachedGenerators = new Vector();
38     cachedGenerators.addElement(new GF256Poly(field, new int[] { 1 }));
39   }
40
41   private GF256Poly buildGenerator(int degree) {
42     if (degree >= cachedGenerators.size()) {
43       GF256Poly lastGenerator = (GF256Poly) cachedGenerators.elementAt(cachedGenerators.size() - 1);
44       for (int d = cachedGenerators.size(); d <= degree; d++) {
45         GF256Poly nextGenerator = lastGenerator.multiply(new GF256Poly(field, new int[] { 1, field.exp(d - 1) }));
46         cachedGenerators.addElement(nextGenerator);
47         lastGenerator = nextGenerator;
48       }
49     }
50     return (GF256Poly) cachedGenerators.elementAt(degree);    
51   }
52
53   public void encode(int[] toEncode, int ecBytes) {
54     int dataBytes = toEncode.length - ecBytes;
55     GF256Poly generator = buildGenerator(ecBytes);
56     int[] infoCoefficients = new int[dataBytes];
57     System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);
58     GF256Poly info = new GF256Poly(field, infoCoefficients);
59     info = info.multiplyByMonomial(ecBytes, 1);
60     GF256Poly remainder = info.divide(generator)[1];
61     System.arraycopy(remainder.getCoefficients(), 0, toEncode, dataBytes, ecBytes);
62   }
63
64 }