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
6 * http://www.apache.org/licenses/LICENSE-2.0
\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
14 namespace com.google.zxing.oned
\r
17 using com.google.zxing.common;
\r
19 * <p>Implements decoding of the UPC-E format.</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
28 public sealed class UPCEReader : AbstractUPCEANReader
\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
34 private int[] MIDDLE_END_PATTERN = new int[]{1, 1, 1, 1, 1, 1};
\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
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
46 private int[] decodeMiddleCounters;
\r
48 public UPCEReader() {
\r
49 decodeMiddleCounters = new int[4];
\r
52 protected override int decodeMiddle(BitArray row, int[] startRange, StringBuilder result) {
\r
53 int[] counters = decodeMiddleCounters;
\r
58 int end = row.getSize();
\r
59 int rowOffset = startRange[1];
\r
61 int lgPatternFound = 0;
\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
69 if (bestMatch >= 10) {
\r
70 lgPatternFound |= 1 << (5 - x);
\r
74 determineNumSysAndCheckDigit(result, lgPatternFound);
\r
79 public int[] decodeEnd(BitArray row, int endStart) {
\r
80 return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN);
\r
83 public bool checkChecksum(string s) {
\r
84 return base.checkChecksum(convertUPCEtoUPCA(s));
\r
87 private static void determineNumSysAndCheckDigit(StringBuilder resultString, int lgPatternFound)
\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
99 throw new ReaderException();
\r
102 public override BarcodeFormat getBarcodeFormat() {
\r
103 return BarcodeFormat.UPC_E;
\r
107 * Expands a UPC-E value back into its full, equivalent UPC-A code value.
\r
109 * @param upce UPC-E code as string of digits
\r
110 * @return equivalent UPC-A code as string of digits
\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
122 result.Append(upceChars, 0, 2);
\r
123 result.Append(lastChar);
\r
124 result.Append("0000");
\r
125 result.Append(upceChars, 2, 3);
\r
128 result.Append(upceChars, 0, 3);
\r
129 result.Append("00000");
\r
130 result.Append(upceChars, 3, 2);
\r
133 result.Append(upceChars, 0, 4);
\r
134 result.Append("00000");
\r
135 result.Append(upceChars[4]);
\r
138 result.Append(upceChars, 0, 5);
\r
139 result.Append("0000");
\r
140 result.Append(lastChar);
\r
143 result.Append(upce[7]);
\r
144 return result.ToString();
\r