Committed C# port from Mohamad
[zxing.git] / csharp / oned / EAN13Reader.cs
1 /*\r
2 * Licensed under the Apache License, Version 2.0 (the "License");\r
3 * you may not use this file except in compliance with the License.\r
4 * You may obtain a copy of the License at\r
5 *\r
6 *      http://www.apache.org/licenses/LICENSE-2.0\r
7 *\r
8 * Unless required by applicable law or agreed to in writing, software\r
9 * distributed under the License is distributed on an "AS IS" BASIS,\r
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
11 * See the License for the specific language governing permissions and\r
12 * limitations under the License.\r
13 */\r
14 namespace com.google.zxing.oned\r
15 {\r
16     /**\r
17      * <p>Implements decoding of the EAN-13 format.</p>\r
18      *\r
19      * @author dswitkin@google.com (Daniel Switkin)\r
20      * @author Sean Owen\r
21      * @author alasdair@google.com (Alasdair Mackintosh)\r
22      */\r
23 \r
24     using System.Text;\r
25     using com.google.zxing.common;\r
26 \r
27     public sealed class EAN13Reader : AbstractUPCEANReader \r
28     {\r
29           // For an EAN-13 barcode, the first digit is represented by the parities used\r
30           // to encode the next six digits, according to the table below. For example,\r
31           // if the barcode is 5 123456 789012 then the value of the first digit is\r
32           // signified by using odd for '1', even for '2', even for '3', odd for '4',\r
33           // odd for '5', and even for '6'. See http://en.wikipedia.org/wiki/EAN-13\r
34           //\r
35           //                Parity of next 6 digits\r
36           //    Digit   0     1     2     3     4     5\r
37           //       0    Odd   Odd   Odd   Odd   Odd   Odd\r
38           //       1    Odd   Odd   Even  Odd   Even  Even\r
39           //       2    Odd   Odd   Even  Even  Odd   Even\r
40           //       3    Odd   Odd   Even  Even  Even  Odd\r
41           //       4    Odd   Even  Odd   Odd   Even  Even\r
42           //       5    Odd   Even  Even  Odd   Odd   Even\r
43           //       6    Odd   Even  Even  Even  Odd   Odd\r
44           //       7    Odd   Even  Odd   Even  Odd   Even\r
45           //       8    Odd   Even  Odd   Even  Even  Odd\r
46           //       9    Odd   Even  Even  Odd   Even  Odd\r
47           //\r
48           // Note that the encoding for '0' uses the same parity as a UPC barcode. Hence\r
49           // a UPC barcode can be converted to an EAN-13 barcode by prepending a 0.\r
50           //\r
51           // The encodong is represented by the following array, which is a bit pattern\r
52           // using Odd = 0 and Even = 1. For example, 5 is represented by:\r
53           //\r
54           //              Odd Even Even Odd Odd Even\r
55           // in binary:\r
56           //                0    1    1   0   0    1   == 0x19\r
57           //\r
58           private static  int[] FIRST_DIGIT_ENCODINGS = {\r
59               0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A\r
60           };\r
61 \r
62           private  int[] decodeMiddleCounters;\r
63 \r
64           public EAN13Reader() {\r
65             decodeMiddleCounters = new int[4];\r
66           }\r
67 \r
68           protected override int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString) {\r
69             int[] counters = decodeMiddleCounters;\r
70             counters[0] = 0;\r
71             counters[1] = 0;\r
72             counters[2] = 0;\r
73             counters[3] = 0;\r
74             int end = row.getSize();\r
75             int rowOffset = startRange[1];\r
76 \r
77             int lgPatternFound = 0;\r
78 \r
79             for (int x = 0; x < 6 && rowOffset < end; x++) {\r
80               int bestMatch = decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS);\r
81               resultString.Append((char) ('0' + bestMatch % 10));\r
82               for (int i = 0; i < counters.Length; i++) {\r
83                 rowOffset += counters[i];\r
84               }\r
85               if (bestMatch >= 10) {\r
86                 lgPatternFound |= 1 << (5 - x);\r
87               }\r
88             }\r
89 \r
90             determineFirstDigit(resultString, lgPatternFound);\r
91 \r
92             int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN);\r
93             rowOffset = middleRange[1];\r
94 \r
95             for (int x = 0; x < 6 && rowOffset < end; x++) {\r
96               int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS);\r
97               resultString.Append((char) ('0' + bestMatch));\r
98               for (int i = 0; i < counters.Length; i++) {\r
99                 rowOffset += counters[i];\r
100               }\r
101             }\r
102 \r
103             return rowOffset;\r
104           }\r
105 \r
106           public override BarcodeFormat getBarcodeFormat() {\r
107             return BarcodeFormat.EAN_13;\r
108           }\r
109 \r
110           /**\r
111            * Based on pattern of odd-even ('L' and 'G') patterns used to encoded the explicitly-encoded digits\r
112            * in a barcode, determines the implicitly encoded first digit and adds it to the result string.\r
113            *\r
114            * @param resultString string to insert decoded first digit into\r
115            * @param lgPatternFound int whose bits indicates the pattern of odd/even L/G patterns used to\r
116            * encode digits\r
117            * @throws ReaderException if first digit cannot be determined\r
118            */\r
119           private static void determineFirstDigit(StringBuilder resultString, int lgPatternFound) {\r
120             for (int d = 0; d < 10; d++) {\r
121               if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d]) {\r
122                 resultString.Insert(0, (char) ('0' + d));\r
123                 return;\r
124               }\r
125             }\r
126             throw new ReaderException();\r
127           }\r
128 \r
129     \r
130     \r
131     }\r
132 }