5 * Copyright 2010 ZXing authors All rights reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 #include "UPCEANReader.h"
21 #include <zxing/oned/OneDResultPoint.h>
22 #include <zxing/ReaderException.h>
28 * Start/end guard pattern.
30 static const int START_END_PATTERN[3] = {1, 1, 1};
33 * Pattern marking the middle of a UPC/EAN pattern, separating the two halves.
35 static const int MIDDLE_PATTERN_LEN = 5;
36 static const int MIDDLE_PATTERN[MIDDLE_PATTERN_LEN] = {1, 1, 1, 1, 1};
39 * "Odd", or "L" patterns used to encode UPC/EAN digits.
41 const int L_PATTERNS_LEN = 10;
42 const int L_PATTERNS_SUB_LEN = 4;
43 const int L_PATTERNS[L_PATTERNS_LEN][L_PATTERNS_SUB_LEN] = {
57 * As above but also including the "even", or "G" patterns used to encode UPC/EAN digits.
59 const int L_AND_G_PATTERNS_LEN = 20;
60 const int L_AND_G_PATTERNS_SUB_LEN = 4;
61 const int L_AND_G_PATTERNS[L_AND_G_PATTERNS_LEN][L_AND_G_PATTERNS_SUB_LEN] = {
72 {1, 1, 2, 3}, // 10 reversed 0
73 {1, 2, 2, 2}, // 11 reversed 1
74 {2, 2, 1, 2}, // 12 reversed 2
75 {1, 1, 4, 1}, // 13 reversed 3
76 {2, 3, 1, 1}, // 14 reversed 4
77 {1, 3, 2, 1}, // 15 reversed 5
78 {4, 1, 1, 1}, // 16 reversed 6
79 {2, 1, 3, 1}, // 17 reversed 7
80 {3, 1, 2, 1}, // 18 reversed 8
81 {2, 1, 1, 3} // 19 reversed 9
85 const int UPCEANReader::getMIDDLE_PATTERN_LEN() {
86 return MIDDLE_PATTERN_LEN;
89 const int* UPCEANReader::getMIDDLE_PATTERN() {
90 return MIDDLE_PATTERN;
93 UPCEANReader::UPCEANReader() {
97 Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row) {
100 if (findStartGuardPattern(row, &rangeStart, &rangeEnd)) {
102 return decodeRow(rowNumber, row, rangeStart, rangeEnd);
103 } catch (ReaderException const& re) {
106 return Ref<Result>();
109 Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, int startGuardBegin,
111 std::string tmpResultString;
112 std::string& tmpResultStringRef = tmpResultString;
113 int endStart = decodeMiddle(row, startGuardBegin, startGuardEnd, tmpResultStringRef);
115 return Ref<Result>();
120 if (!decodeEnd(row, endStart, &endGuardBegin, &endGuardEnd)) {
121 return Ref<Result>();
124 // Make sure there is a quiet zone at least as big as the end pattern after the barcode.
125 // The spec might want more whitespace, but in practice this is the maximum we can count on.
126 size_t quietEnd = endGuardEnd + (endGuardEnd - endGuardBegin);
127 if (quietEnd >= row->getSize() || !row->isRange(endGuardEnd, quietEnd, false)) {
128 return Ref<Result>();
131 if (!checkChecksum(tmpResultString)) {
132 return Ref<Result>();
135 Ref<String> resultString(new String(tmpResultString));
136 float left = (float) (startGuardBegin + startGuardEnd) / 2.0f;
137 float right = (float) (endGuardBegin + endGuardEnd) / 2.0f;
139 std::vector< Ref<ResultPoint> > resultPoints(2);
140 Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber));
141 Ref<OneDResultPoint> resultPoint2(new OneDResultPoint(right, (float) rowNumber));
142 resultPoints[0] = resultPoint1;
143 resultPoints[1] = resultPoint2;
145 ArrayRef<unsigned char> resultBytes(1);
146 return Ref<Result>(new Result(resultString, resultBytes, resultPoints, getBarcodeFormat()));
149 bool UPCEANReader::findStartGuardPattern(Ref<BitArray> row, int* rangeStart, int* rangeEnd) {
151 while (findGuardPattern(row, nextStart, false, START_END_PATTERN,
152 sizeof(START_END_PATTERN) / sizeof(int), rangeStart, rangeEnd)) {
153 int start = *rangeStart;
154 nextStart = *rangeEnd;
155 // Make sure there is a quiet zone at least as big as the start pattern before the barcode.
156 // If this check would run off the left edge of the image, do not accept this barcode,
157 // as it is very likely to be a false positive.
158 int quietStart = start - (nextStart - start);
159 if (quietStart >= 0 && row->isRange(quietStart, start, false)) {
166 bool UPCEANReader::findGuardPattern(Ref<BitArray> row, int rowOffset, bool whiteFirst,
167 const int pattern[], int patternLen, int* start, int* end) {
168 int patternLength = patternLen;
169 int counters[patternLength];
170 int countersCount = sizeof(counters) / sizeof(int);
171 for (int i = 0; i < countersCount; i++) {
174 int width = row->getSize();
175 bool isWhite = false;
176 while (rowOffset < width) {
177 isWhite = !row->get(rowOffset);
178 if (whiteFirst == isWhite) {
184 int counterPosition = 0;
185 int patternStart = rowOffset;
186 for (int x = rowOffset; x < width; x++) {
187 bool pixel = row->get(x);
188 if (pixel ^ isWhite) {
189 counters[counterPosition]++;
191 if (counterPosition == patternLength - 1) {
192 if (patternMatchVariance(counters, countersCount, pattern,
193 MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
194 *start = patternStart;
198 patternStart += counters[0] + counters[1];
199 for (int y = 2; y < patternLength; y++) {
200 counters[y - 2] = counters[y];
202 counters[patternLength - 2] = 0;
203 counters[patternLength - 1] = 0;
208 counters[counterPosition] = 1;
215 bool UPCEANReader::decodeEnd(Ref<BitArray> row, int endStart, int* endGuardBegin,
217 return findGuardPattern(row, endStart, false, START_END_PATTERN,
218 sizeof(START_END_PATTERN) / sizeof(int), endGuardBegin, endGuardEnd);
221 int UPCEANReader::decodeDigit(Ref<BitArray> row, int counters[], int countersLen, int rowOffset,
222 UPC_EAN_PATTERNS patternType) {
223 if (!recordPattern(row, rowOffset, counters, countersLen)) {
226 unsigned int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
230 switch (patternType) {
231 case UPC_EAN_PATTERNS_L_PATTERNS:
232 max = L_PATTERNS_LEN;
233 for (int i = 0; i < max; i++) {
234 int pattern[countersLen];
235 for(int j = 0; j< countersLen; j++){
236 pattern[j] = L_PATTERNS[i][j];
239 unsigned int variance = patternMatchVariance(counters, countersLen, pattern,
240 MAX_INDIVIDUAL_VARIANCE);
241 if (variance < bestVariance) {
242 bestVariance = variance;
247 case UPC_EAN_PATTERNS_L_AND_G_PATTERNS:
248 max = L_AND_G_PATTERNS_LEN;
249 for (int i = 0; i < max; i++) {
250 int pattern[countersLen];
251 for(int j = 0; j< countersLen; j++){
252 pattern[j] = L_AND_G_PATTERNS[i][j];
255 unsigned int variance = patternMatchVariance(counters, countersLen, pattern,
256 MAX_INDIVIDUAL_VARIANCE);
257 if (variance < bestVariance) {
258 bestVariance = variance;
270 * @return {@link #checkStandardUPCEANChecksum(String)}
272 bool UPCEANReader::checkChecksum(std::string s) {
273 return checkStandardUPCEANChecksum(s);
277 * Computes the UPC/EAN checksum on a string of digits, and reports
278 * whether the checksum is correct or not.
280 * @param s string of digits to check
281 * @return true iff string of digits passes the UPC/EAN checksum algorithm
283 bool UPCEANReader::checkStandardUPCEANChecksum(std::string s) {
284 int length = s.length();
290 for (int i = length - 2; i >= 0; i -= 2) {
291 int digit = (int) s[i] - (int) '0';
292 if (digit < 0 || digit > 9) {
298 for (int i = length - 1; i >= 0; i -= 2) {
299 int digit = (int) s[i] - (int) '0';
300 if (digit < 0 || digit > 9) {
305 return sum % 10 == 0;
308 UPCEANReader::~UPCEANReader() {