Committed C# port from Mohamad
[zxing.git] / csharp / oned / UPCEReader.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     using System.Text;\r
17     using com.google.zxing.common;\r
18     /**\r
19      * <p>Implements decoding of the UPC-E format.</p>\r
20      * <p/>\r
21      * <p><a href="http://www.barcodeisland.com/upce.phtml">This</a> is a great reference for\r
22      * UPC-E information.</p>\r
23      *\r
24      * @author Sean Owen\r
25      */\r
26 \r
27 \r
28     public sealed class UPCEReader : AbstractUPCEANReader\r
29     { \r
30            /**\r
31            * The pattern that marks the middle, and end, of a UPC-E pattern.\r
32            * There is no "second half" to a UPC-E barcode.\r
33            */\r
34           private int[] MIDDLE_END_PATTERN = new int[]{1, 1, 1, 1, 1, 1};\r
35 \r
36           /**\r
37            * See {@link #L_AND_G_PATTERNS}; these values similarly represent patterns of\r
38            * even-odd parity encodings of digits that imply both the number system (0 or 1)\r
39            * used, and the check digit.\r
40            */\r
41           private static int[][] NUMSYS_AND_CHECK_DIGIT_PATTERNS = new int[][]{\r
42               new int[]{0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25},\r
43               new int[]{0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A}\r
44           };\r
45 \r
46           private int[] decodeMiddleCounters;\r
47 \r
48           public UPCEReader() {\r
49             decodeMiddleCounters = new int[4];\r
50           }\r
51 \r
52           protected override int decodeMiddle(BitArray row, int[] startRange, StringBuilder result) {\r
53             int[] counters = decodeMiddleCounters;\r
54             counters[0] = 0;\r
55             counters[1] = 0;\r
56             counters[2] = 0;\r
57             counters[3] = 0;\r
58             int end = row.getSize();\r
59             int rowOffset = startRange[1];\r
60 \r
61             int lgPatternFound = 0;\r
62 \r
63             for (int x = 0; x < 6 && rowOffset < end; x++) {\r
64               int bestMatch = decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS);\r
65               result.Append((char) ('0' + bestMatch % 10));\r
66               for (int i = 0; i < counters.Length; i++) {\r
67                 rowOffset += counters[i];\r
68               }\r
69               if (bestMatch >= 10) {\r
70                 lgPatternFound |= 1 << (5 - x);\r
71               }\r
72             }\r
73 \r
74             determineNumSysAndCheckDigit(result, lgPatternFound);\r
75 \r
76             return rowOffset;\r
77           }\r
78 \r
79           public int[] decodeEnd(BitArray row, int endStart) {\r
80             return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN);\r
81           }\r
82 \r
83           public bool checkChecksum(string s) {\r
84               return base.checkChecksum(convertUPCEtoUPCA(s));\r
85           }\r
86 \r
87           private static void determineNumSysAndCheckDigit(StringBuilder resultString, int lgPatternFound)\r
88               {\r
89 \r
90             for (int numSys = 0; numSys <= 1; numSys++) {\r
91               for (int d = 0; d < 10; d++) {\r
92                 if (lgPatternFound == NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) {\r
93                   resultString.Insert(0, (char) ('0' + numSys));\r
94                   resultString.Append((char) ('0' + d));\r
95                   return;\r
96                 }\r
97               }\r
98             }\r
99             throw new ReaderException();\r
100           }\r
101 \r
102           public override BarcodeFormat getBarcodeFormat() {\r
103             return BarcodeFormat.UPC_E;  \r
104           }\r
105 \r
106           /**\r
107            * Expands a UPC-E value back into its full, equivalent UPC-A code value.\r
108            *\r
109            * @param upce UPC-E code as string of digits\r
110            * @return equivalent UPC-A code as string of digits\r
111            */\r
112           public static string convertUPCEtoUPCA(string upce) {\r
113             char[] upceChars = new char[6];\r
114             SupportClass.GetCharsFromString(upce, 1, 7, upceChars, 0);\r
115             StringBuilder result = new StringBuilder(12);\r
116             result.Append(upce[0]);\r
117             char lastChar = upceChars[5];\r
118             switch (lastChar) {\r
119               case '0':\r
120               case '1':\r
121               case '2':\r
122                 result.Append(upceChars, 0, 2);\r
123                 result.Append(lastChar);\r
124                 result.Append("0000");\r
125                 result.Append(upceChars, 2, 3);\r
126                 break;\r
127               case '3':\r
128                 result.Append(upceChars, 0, 3);\r
129                 result.Append("00000");\r
130                 result.Append(upceChars, 3, 2);\r
131                 break;\r
132               case '4':\r
133                 result.Append(upceChars, 0, 4);\r
134                 result.Append("00000");\r
135                 result.Append(upceChars[4]);\r
136                 break;\r
137               default:\r
138                 result.Append(upceChars, 0, 5);\r
139                 result.Append("0000");\r
140                 result.Append(lastChar);\r
141                 break;\r
142             }\r
143             result.Append(upce[7]);\r
144             return result.ToString();\r
145           }\r
146     \r
147     \r
148     }\r
149 \r
150 \r
151 }\r