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