Added code for the Data Matrix decoder.
[zxing.git] / core / src / com / google / zxing / datamatrix / decoder / Version.java
1 /*\r
2  * Copyright 2007 Google Inc.\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *      http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 package com.google.zxing.datamatrix.decoder;\r
18 \r
19 import com.google.zxing.ReaderException;\r
20 import com.google.zxing.common.BitMatrix;\r
21 \r
22 /**\r
23  * The Version object encapsulates attributes about a particular\r
24  * size Data Matrix Code.\r
25  *\r
26  * @author bbrown@google.com (Brian Brown)\r
27  */\r
28 public final class Version {\r
29 \r
30   private static final Version[] VERSIONS = buildVersions();\r
31 \r
32   private final int versionNumber;\r
33   private final int symbolSizeRows;\r
34   private final int symbolSizeColumns;\r
35   private final int dataRegionSizeRows;\r
36   private final int dataRegionSizeColumns;\r
37   private final ECBlocks ecBlocks;\r
38   private final int totalCodewords;\r
39 \r
40   private Version(int versionNumber,\r
41                   int symbolSizeRows,\r
42                   int symbolSizeColumns,\r
43                   int dataRegionSizeRows,\r
44                   int dataRegionSizeColumns,\r
45                   ECBlocks ecBlocks) {\r
46     this.versionNumber = versionNumber;\r
47     this.symbolSizeRows = symbolSizeRows;\r
48     this.symbolSizeColumns = symbolSizeColumns;\r
49     this.dataRegionSizeRows = dataRegionSizeRows;\r
50     this.dataRegionSizeColumns = dataRegionSizeColumns;\r
51     this.ecBlocks = ecBlocks;\r
52     \r
53     // Calculate the total number of codewords\r
54     int total = 0;\r
55     int ecCodewords = ecBlocks.ecCodewords;\r
56     ECB[] ecbArray = ecBlocks.ecBlocks;\r
57     for (int i = 0; i < ecbArray.length; i++) {\r
58       ECB ecBlock = ecbArray[i];\r
59       total += ecBlock.count * (ecBlock.dataCodewords + ecCodewords);\r
60     }\r
61     this.totalCodewords = total;\r
62   }\r
63 \r
64   public int getVersionNumber() {\r
65     return versionNumber;\r
66   }\r
67 \r
68   public int getSymbolSizeRows() {\r
69     return symbolSizeRows;\r
70   }\r
71   \r
72   public int getSymbolSizeColumns() {\r
73     return symbolSizeColumns;\r
74   }\r
75   \r
76   public int getDataRegionSizeRows() {\r
77     return dataRegionSizeRows;\r
78   }\r
79   \r
80   public int getDataRegionSizeColumns() {\r
81     return dataRegionSizeColumns;\r
82   }\r
83   \r
84   public int getTotalCodewords() {\r
85     return totalCodewords;\r
86   }\r
87   \r
88   ECBlocks getECBlocks() {\r
89     return ecBlocks;\r
90   }\r
91 \r
92   /**\r
93    * <p>Deduces version information from Data Matrix dimensions.</p>\r
94    *\r
95    * @param numRows Number of rows in modules\r
96    * @param numRows Number of columns in modules\r
97    * @return {@link Version} for a Data Matrix Code of those dimensions\r
98    * @throws ReaderException if dimensions do correspond to a valid Data Matrix size\r
99    */\r
100   public static Version getVersionForDimensions(int numRows, int numColumns) throws ReaderException {\r
101     if ((numRows & 0x01) != 0 || (numColumns & 0x01) != 0) {\r
102       throw new ReaderException("Dimension must be 0 mod 2");\r
103     }\r
104     \r
105     // TODO(bbrown): This is doing a linear search through the array of versions.\r
106     // If we interleave the rectangular versions with the square versions we could\r
107     // do a binary search.\r
108     int numVersions = VERSIONS.length;\r
109     for (int i = 0; i < numVersions; ++i){\r
110       Version version = VERSIONS[i];\r
111       if (version.symbolSizeRows == numRows) {\r
112         if (version.symbolSizeColumns == numColumns) {\r
113           return version;\r
114         }\r
115       }\r
116     }\r
117     \r
118     throw new ReaderException("Dimensions do not correspond to a valid Data Matrix Version.");\r
119   }\r
120 \r
121   /**\r
122    * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will\r
123    * use blocks of differing sizes within one version, so, this encapsulates the parameters for\r
124    * each set of blocks. It also holds the number of error-correction codewords per block since it\r
125    * will be the same across all blocks within one version.</p>\r
126    */\r
127   static final class ECBlocks {\r
128     private int ecCodewords;\r
129     private ECB[] ecBlocks;\r
130 \r
131     private ECBlocks(int ecCodewords, ECB ecBlocks) {\r
132       this.ecCodewords = ecCodewords;\r
133       this.ecBlocks = new ECB[] { ecBlocks };\r
134     }\r
135 \r
136     private ECBlocks(int ecCodewords, ECB ecBlocks1, ECB ecBlocks2) {\r
137       this.ecCodewords = ecCodewords;\r
138       this.ecBlocks = new ECB[] { ecBlocks1, ecBlocks2 };\r
139     }\r
140 \r
141     int getECCodewords() {\r
142       return ecCodewords;\r
143     }\r
144 \r
145     ECB[] getECBlocks() {\r
146       return ecBlocks;\r
147     }\r
148   }\r
149 \r
150   /**\r
151    * <p>Encapsualtes the parameters for one error-correction block in one symbol version.\r
152    * This includes the number of data codewords, and the number of times a block with these\r
153    * parameters is used consecutively in the Data Matrix code version's format.</p>\r
154    */\r
155   static final class ECB {\r
156     private int count;\r
157     private int dataCodewords;\r
158 \r
159     private ECB(int count, int dataCodewords) {\r
160       this.count = count;\r
161       this.dataCodewords = dataCodewords;\r
162     }\r
163 \r
164     int getCount() {\r
165       return count;\r
166     }\r
167 \r
168     int getDataCodewords() {\r
169       return dataCodewords;\r
170     }\r
171   }\r
172 \r
173   public String toString() {\r
174     return String.valueOf(versionNumber);\r
175   }\r
176 \r
177   /**\r
178    * See ISO 16022:2006 5.5.1 Table 7\r
179    */\r
180   private static Version[] buildVersions() {\r
181     return new Version[]{\r
182         new Version(1, 10, 10, 8, 8,\r
183             new ECBlocks(5, new ECB(1, 3))),\r
184         new Version(2, 12, 12, 10, 10,\r
185             new ECBlocks(7, new ECB(1, 5))),\r
186         new Version(3, 14, 14, 12, 12,\r
187             new ECBlocks(10, new ECB(1, 8))),\r
188         new Version(4, 16, 16, 14, 14,\r
189             new ECBlocks(12, new ECB(1, 12))),\r
190         new Version(5, 18, 18, 16, 16,\r
191             new ECBlocks(14, new ECB(1, 18))),\r
192         new Version(6, 20, 20, 18, 18,\r
193             new ECBlocks(18, new ECB(1, 22))),\r
194         new Version(7, 22, 22, 20, 20,\r
195             new ECBlocks(20, new ECB(1, 30))),\r
196         new Version(8, 24, 24, 22, 22,\r
197             new ECBlocks(24, new ECB(1, 36))),\r
198         new Version(9, 26, 26, 24, 24,\r
199             new ECBlocks(28, new ECB(1, 44))),\r
200         new Version(10, 32, 32, 14, 14,\r
201             new ECBlocks(36, new ECB(1, 62))),\r
202         new Version(11, 36, 36, 16, 16,\r
203             new ECBlocks(42, new ECB(1, 86))),\r
204         new Version(12, 40, 40, 18, 18,\r
205             new ECBlocks(48, new ECB(1, 114))),\r
206         new Version(13, 44, 44, 20, 20,\r
207             new ECBlocks(56, new ECB(1, 144))),\r
208         new Version(14, 48, 48, 22, 22,\r
209             new ECBlocks(68, new ECB(1, 174))),\r
210         new Version(15, 52, 52, 24, 24,\r
211             new ECBlocks(42, new ECB(2, 102))),\r
212         new Version(16, 64, 64, 14, 14,\r
213             new ECBlocks(56, new ECB(2, 140))),\r
214         new Version(17, 72, 72, 16, 16,\r
215             new ECBlocks(36, new ECB(4, 92))),\r
216         new Version(18, 80, 80, 18, 18,\r
217             new ECBlocks(48, new ECB(4, 114))),\r
218         new Version(19, 88, 88, 20, 20,\r
219             new ECBlocks(56, new ECB(4, 144))),\r
220         new Version(20, 96, 96, 22, 22,\r
221             new ECBlocks(68, new ECB(4, 174))),\r
222         new Version(21, 104, 104, 24, 24,\r
223             new ECBlocks(56, new ECB(6, 136))),\r
224         new Version(22, 120, 120, 18, 18,\r
225             new ECBlocks(68, new ECB(6, 175))),\r
226         new Version(23, 132, 132, 20, 20,\r
227             new ECBlocks(62, new ECB(8, 163))),\r
228         new Version(24, 144, 144, 22, 22,\r
229             new ECBlocks(62, new ECB(8, 156), new ECB(2, 155))),\r
230         new Version(25, 8, 18, 6, 16,\r
231             new ECBlocks(7, new ECB(1, 5))),\r
232         new Version(26, 8, 32, 6, 14,\r
233             new ECBlocks(11, new ECB(1, 10))),\r
234         new Version(27, 12, 26, 10, 24,\r
235             new ECBlocks(14, new ECB(1, 16))),\r
236         new Version(28, 12, 36, 10, 16,\r
237             new ECBlocks(18, new ECB(1, 22))),\r
238         new Version(29, 16, 36, 10, 16,\r
239             new ECBlocks(24, new ECB(1, 32))),\r
240         new Version(30, 16, 48, 14, 22,\r
241             new ECBlocks(28, new ECB(1, 49)))\r
242     };\r
243   }\r
244 \r
245 }\r