123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /*
- * Copyright 2012 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- #import "ZXBitArray.h"
- #import "ZXEAN13Reader.h"
- #import "ZXErrors.h"
- #import "ZXIntArray.h"
-
- // For an EAN-13 barcode, the first digit is represented by the parities used
- // to encode the next six digits, according to the table below. For example,
- // if the barcode is 5 123456 789012 then the value of the first digit is
- // signified by using odd for '1', even for '2', even for '3', odd for '4',
- // odd for '5', and even for '6'. See http://en.wikipedia.org/wiki/EAN-13
- //
- // Parity of next 6 digits
- // Digit 0 1 2 3 4 5
- // 0 Odd Odd Odd Odd Odd Odd
- // 1 Odd Odd Even Odd Even Even
- // 2 Odd Odd Even Even Odd Even
- // 3 Odd Odd Even Even Even Odd
- // 4 Odd Even Odd Odd Even Even
- // 5 Odd Even Even Odd Odd Even
- // 6 Odd Even Even Even Odd Odd
- // 7 Odd Even Odd Even Odd Even
- // 8 Odd Even Odd Even Even Odd
- // 9 Odd Even Even Odd Even Odd
- //
- // Note that the encoding for '0' uses the same parity as a UPC barcode. Hence
- // a UPC barcode can be converted to an EAN-13 barcode by prepending a 0.
- //
- // The encoding is represented by the following array, which is a bit pattern
- // using Odd = 0 and Even = 1. For example, 5 is represented by:
- //
- // Odd Even Even Odd Odd Even
- // in binary:
- // 0 1 1 0 0 1 == 0x19
- //
- const int ZX_EAN13_FIRST_DIGIT_ENCODINGS[] = {
- 0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A
- };
-
- @interface ZXEAN13Reader ()
-
- @property (nonatomic, strong, readonly) ZXIntArray *decodeMiddleCounters;
-
- @end
-
- @implementation ZXEAN13Reader
-
- - (id)init {
- if (self = [super init]) {
- _decodeMiddleCounters = [[ZXIntArray alloc] initWithLength:4];
- }
- return self;
- }
-
- - (int)decodeMiddle:(ZXBitArray *)row startRange:(NSRange)startRange result:(NSMutableString *)result error:(NSError **)error {
- ZXIntArray *counters = self.decodeMiddleCounters;
- [counters clear];
- int end = row.size;
- int rowOffset = (int)NSMaxRange(startRange);
-
- int lgPatternFound = 0;
-
- for (int x = 0; x < 6 && rowOffset < end; x++) {
- int bestMatch = [ZXUPCEANReader decodeDigit:row counters:counters rowOffset:rowOffset patternType:ZX_UPC_EAN_PATTERNS_L_AND_G_PATTERNS error:error];
- if (bestMatch == -1) {
- return -1;
- }
- [result appendFormat:@"%C", (unichar)('0' + bestMatch % 10)];
- rowOffset += [counters sum];
- if (bestMatch >= 10) {
- lgPatternFound |= 1 << (5 - x);
- }
- }
-
- if (![self determineFirstDigit:result lgPatternFound:lgPatternFound]) {
- if (error) *error = ZXNotFoundErrorInstance();
- return -1;
- }
-
- NSRange middleRange = [[self class] findGuardPattern:row
- rowOffset:rowOffset
- whiteFirst:YES
- pattern:ZX_UPC_EAN_MIDDLE_PATTERN
- patternLen:ZX_UPC_EAN_MIDDLE_PATTERN_LEN
- error:error];
- if (middleRange.location == NSNotFound) {
- return -1;
- }
- rowOffset = (int)NSMaxRange(middleRange);
-
- for (int x = 0; x < 6 && rowOffset < end; x++) {
- int bestMatch = [ZXUPCEANReader decodeDigit:row
- counters:counters
- rowOffset:rowOffset
- patternType:ZX_UPC_EAN_PATTERNS_L_PATTERNS
- error:error];
- if (bestMatch == -1) {
- return -1;
- }
- [result appendFormat:@"%C", (unichar)('0' + bestMatch)];
- rowOffset += [counters sum];
- }
-
- return rowOffset;
- }
-
- - (ZXBarcodeFormat)barcodeFormat {
- return kBarcodeFormatEan13;
- }
-
- /**
- * Based on pattern of odd-even ('L' and 'G') patterns used to encoded the explicitly-encoded
- * digits in a barcode, determines the implicitly encoded first digit and adds it to the
- * result string.
- *
- * @param resultString string to insert decoded first digit into
- * @param lgPatternFound int whose bits indicates the pattern of odd/even L/G patterns used to
- * encode digits
- * @return NO if first digit cannot be determined
- */
- - (BOOL)determineFirstDigit:(NSMutableString *)resultString lgPatternFound:(int)lgPatternFound {
- for (int d = 0; d < 10; d++) {
- if (lgPatternFound == ZX_EAN13_FIRST_DIGIT_ENCODINGS[d]) {
- [resultString insertString:[NSString stringWithFormat:@"%C", (unichar)('0' + d)] atIndex:0];
- return YES;
- }
- }
- return NO;
- }
-
- @end
|