Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Copyright 2012 ZXing authors
  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. #import "ZXBitArray.h"
  17. #import "ZXEAN13Reader.h"
  18. #import "ZXErrors.h"
  19. #import "ZXIntArray.h"
  20. // For an EAN-13 barcode, the first digit is represented by the parities used
  21. // to encode the next six digits, according to the table below. For example,
  22. // if the barcode is 5 123456 789012 then the value of the first digit is
  23. // signified by using odd for '1', even for '2', even for '3', odd for '4',
  24. // odd for '5', and even for '6'. See http://en.wikipedia.org/wiki/EAN-13
  25. //
  26. // Parity of next 6 digits
  27. // Digit 0 1 2 3 4 5
  28. // 0 Odd Odd Odd Odd Odd Odd
  29. // 1 Odd Odd Even Odd Even Even
  30. // 2 Odd Odd Even Even Odd Even
  31. // 3 Odd Odd Even Even Even Odd
  32. // 4 Odd Even Odd Odd Even Even
  33. // 5 Odd Even Even Odd Odd Even
  34. // 6 Odd Even Even Even Odd Odd
  35. // 7 Odd Even Odd Even Odd Even
  36. // 8 Odd Even Odd Even Even Odd
  37. // 9 Odd Even Even Odd Even Odd
  38. //
  39. // Note that the encoding for '0' uses the same parity as a UPC barcode. Hence
  40. // a UPC barcode can be converted to an EAN-13 barcode by prepending a 0.
  41. //
  42. // The encoding is represented by the following array, which is a bit pattern
  43. // using Odd = 0 and Even = 1. For example, 5 is represented by:
  44. //
  45. // Odd Even Even Odd Odd Even
  46. // in binary:
  47. // 0 1 1 0 0 1 == 0x19
  48. //
  49. const int ZX_EAN13_FIRST_DIGIT_ENCODINGS[] = {
  50. 0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A
  51. };
  52. @interface ZXEAN13Reader ()
  53. @property (nonatomic, strong, readonly) ZXIntArray *decodeMiddleCounters;
  54. @end
  55. @implementation ZXEAN13Reader
  56. - (id)init {
  57. if (self = [super init]) {
  58. _decodeMiddleCounters = [[ZXIntArray alloc] initWithLength:4];
  59. }
  60. return self;
  61. }
  62. - (int)decodeMiddle:(ZXBitArray *)row startRange:(NSRange)startRange result:(NSMutableString *)result error:(NSError **)error {
  63. ZXIntArray *counters = self.decodeMiddleCounters;
  64. [counters clear];
  65. int end = row.size;
  66. int rowOffset = (int)NSMaxRange(startRange);
  67. int lgPatternFound = 0;
  68. for (int x = 0; x < 6 && rowOffset < end; x++) {
  69. int bestMatch = [ZXUPCEANReader decodeDigit:row counters:counters rowOffset:rowOffset patternType:ZX_UPC_EAN_PATTERNS_L_AND_G_PATTERNS error:error];
  70. if (bestMatch == -1) {
  71. return -1;
  72. }
  73. [result appendFormat:@"%C", (unichar)('0' + bestMatch % 10)];
  74. rowOffset += [counters sum];
  75. if (bestMatch >= 10) {
  76. lgPatternFound |= 1 << (5 - x);
  77. }
  78. }
  79. if (![self determineFirstDigit:result lgPatternFound:lgPatternFound]) {
  80. if (error) *error = ZXNotFoundErrorInstance();
  81. return -1;
  82. }
  83. NSRange middleRange = [[self class] findGuardPattern:row
  84. rowOffset:rowOffset
  85. whiteFirst:YES
  86. pattern:ZX_UPC_EAN_MIDDLE_PATTERN
  87. patternLen:ZX_UPC_EAN_MIDDLE_PATTERN_LEN
  88. error:error];
  89. if (middleRange.location == NSNotFound) {
  90. return -1;
  91. }
  92. rowOffset = (int)NSMaxRange(middleRange);
  93. for (int x = 0; x < 6 && rowOffset < end; x++) {
  94. int bestMatch = [ZXUPCEANReader decodeDigit:row
  95. counters:counters
  96. rowOffset:rowOffset
  97. patternType:ZX_UPC_EAN_PATTERNS_L_PATTERNS
  98. error:error];
  99. if (bestMatch == -1) {
  100. return -1;
  101. }
  102. [result appendFormat:@"%C", (unichar)('0' + bestMatch)];
  103. rowOffset += [counters sum];
  104. }
  105. return rowOffset;
  106. }
  107. - (ZXBarcodeFormat)barcodeFormat {
  108. return kBarcodeFormatEan13;
  109. }
  110. /**
  111. * Based on pattern of odd-even ('L' and 'G') patterns used to encoded the explicitly-encoded
  112. * digits in a barcode, determines the implicitly encoded first digit and adds it to the
  113. * result string.
  114. *
  115. * @param resultString string to insert decoded first digit into
  116. * @param lgPatternFound int whose bits indicates the pattern of odd/even L/G patterns used to
  117. * encode digits
  118. * @return NO if first digit cannot be determined
  119. */
  120. - (BOOL)determineFirstDigit:(NSMutableString *)resultString lgPatternFound:(int)lgPatternFound {
  121. for (int d = 0; d < 10; d++) {
  122. if (lgPatternFound == ZX_EAN13_FIRST_DIGIT_ENCODINGS[d]) {
  123. [resultString insertString:[NSString stringWithFormat:@"%C", (unichar)('0' + d)] atIndex:0];
  124. return YES;
  125. }
  126. }
  127. return NO;
  128. }
  129. @end