Rest of cosmetic changes -- simpler, black theme with easier-to-touch buttons and...
[zxing.git] / csharp / oned / EAN13Reader.cs
1 /*\r
2 * Copyright 2008 ZXing authors\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 using System;\r
17 using BarcodeFormat = com.google.zxing.BarcodeFormat;\r
18 using ReaderException = com.google.zxing.ReaderException;\r
19 using BitArray = com.google.zxing.common.BitArray;\r
20 namespace com.google.zxing.oned\r
21 {\r
22         \r
23         /// <summary> <p>Implements decoding of the EAN-13 format.</p>\r
24         /// \r
25         /// </summary>\r
26         /// <author>  dswitkin@google.com (Daniel Switkin)\r
27         /// </author>\r
28         /// <author>  Sean Owen\r
29         /// </author>\r
30         /// <author>  alasdair@google.com (Alasdair Mackintosh)\r
31         /// </author>\r
32         /// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source \r
33         /// </author>\r
34         public sealed class EAN13Reader:UPCEANReader\r
35         {\r
36                 override internal BarcodeFormat BarcodeFormat\r
37                 {\r
38                         get\r
39                         {\r
40                                 return BarcodeFormat.EAN_13;\r
41                         }\r
42                         \r
43                 }\r
44                 \r
45                 // For an EAN-13 barcode, the first digit is represented by the parities used\r
46                 // to encode the next six digits, according to the table below. For example,\r
47                 // if the barcode is 5 123456 789012 then the value of the first digit is\r
48                 // signified by using odd for '1', even for '2', even for '3', odd for '4',\r
49                 // odd for '5', and even for '6'. See http://en.wikipedia.org/wiki/EAN-13\r
50                 //\r
51                 //                Parity of next 6 digits\r
52                 //    Digit   0     1     2     3     4     5\r
53                 //       0    Odd   Odd   Odd   Odd   Odd   Odd\r
54                 //       1    Odd   Odd   Even  Odd   Even  Even\r
55                 //       2    Odd   Odd   Even  Even  Odd   Even\r
56                 //       3    Odd   Odd   Even  Even  Even  Odd\r
57                 //       4    Odd   Even  Odd   Odd   Even  Even\r
58                 //       5    Odd   Even  Even  Odd   Odd   Even\r
59                 //       6    Odd   Even  Even  Even  Odd   Odd\r
60                 //       7    Odd   Even  Odd   Even  Odd   Even\r
61                 //       8    Odd   Even  Odd   Even  Even  Odd\r
62                 //       9    Odd   Even  Even  Odd   Even  Odd\r
63                 //\r
64                 // Note that the encoding for '0' uses the same parity as a UPC barcode. Hence\r
65                 // a UPC barcode can be converted to an EAN-13 barcode by prepending a 0.\r
66                 //\r
67                 // The encoding is represented by the following array, which is a bit pattern\r
68                 // using Odd = 0 and Even = 1. For example, 5 is represented by:\r
69                 //\r
70                 //              Odd Even Even Odd Odd Even\r
71                 // in binary:\r
72                 //                0    1    1   0   0    1   == 0x19\r
73                 //\r
74                 //UPGRADE_NOTE: Final was removed from the declaration of 'FIRST_DIGIT_ENCODINGS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
75                 internal static readonly int[] FIRST_DIGIT_ENCODINGS = new int[]{0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A};\r
76                 \r
77                 //UPGRADE_NOTE: Final was removed from the declaration of 'decodeMiddleCounters '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
78                 private int[] decodeMiddleCounters;\r
79                 \r
80                 public EAN13Reader()\r
81                 {\r
82                         decodeMiddleCounters = new int[4];\r
83                 }\r
84                 \r
85                 protected internal override int decodeMiddle(BitArray row, int[] startRange, System.Text.StringBuilder resultString)\r
86                 {\r
87                         int[] counters = decodeMiddleCounters;\r
88                         counters[0] = 0;\r
89                         counters[1] = 0;\r
90                         counters[2] = 0;\r
91                         counters[3] = 0;\r
92                         int end = row.Size;\r
93                         int rowOffset = startRange[1];\r
94                         \r
95                         int lgPatternFound = 0;\r
96                         \r
97                         for (int x = 0; x < 6 && rowOffset < end; x++)\r
98                         {\r
99                                 int bestMatch = decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS);\r
100                                 resultString.Append((char) ('0' + bestMatch % 10));\r
101                                 for (int i = 0; i < counters.Length; i++)\r
102                                 {\r
103                                         rowOffset += counters[i];\r
104                                 }\r
105                                 if (bestMatch >= 10)\r
106                                 {\r
107                                         lgPatternFound |= 1 << (5 - x);\r
108                                 }\r
109                         }\r
110                         \r
111                         determineFirstDigit(resultString, lgPatternFound);\r
112                         \r
113                         int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN);\r
114                         rowOffset = middleRange[1];\r
115                         \r
116                         for (int x = 0; x < 6 && rowOffset < end; x++)\r
117                         {\r
118                                 int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS);\r
119                                 resultString.Append((char) ('0' + bestMatch));\r
120                                 for (int i = 0; i < counters.Length; i++)\r
121                                 {\r
122                                         rowOffset += counters[i];\r
123                                 }\r
124                         }\r
125                         \r
126                         return rowOffset;\r
127                 }\r
128                 \r
129                 /// <summary> Based on pattern of odd-even ('L' and 'G') patterns used to encoded the explicitly-encoded\r
130                 /// digits in a barcode, determines the implicitly encoded first digit and adds it to the\r
131                 /// result string.\r
132                 /// \r
133                 /// </summary>\r
134                 /// <param name="resultString">string to insert decoded first digit into\r
135                 /// </param>\r
136                 /// <param name="lgPatternFound">int whose bits indicates the pattern of odd/even L/G patterns used to\r
137                 /// encode digits\r
138                 /// </param>\r
139                 /// <throws>  ReaderException if first digit cannot be determined </throws>\r
140                 private static void  determineFirstDigit(System.Text.StringBuilder resultString, int lgPatternFound)\r
141                 {\r
142                         for (int d = 0; d < 10; d++)\r
143                         {\r
144                                 if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d])\r
145                                 {\r
146                                         resultString.Insert(0, (char) ('0' + d));\r
147                                         return ;\r
148                                 }\r
149                         }\r
150                         throw ReaderException.Instance;\r
151                 }\r
152         }\r
153 }